web-dev-qa-db-ja.com

「HTMLMediaElement」で「play」を実行できませんでした:APIはユーザージェスチャによってのみ開始できます

SoundManager 2 for AngularJs を使用する音楽再生ページを作成しています。再生する曲のURLを取得するためにリモートAPIを使用しています。 angular-soundmanager2クリックイベントハンドラーを強化しました。

_element.bind('click', function () {
    if (angular.isFunction(scope.loadFunction)) {
        scope.loadFunction(scope.song, function () {
            $log.debug('adding song to playlist');
            addToPlaylist(scope.song.playDetails);

        })
    } else {
        $log.debug('adding song to playlist');
        addToPlaylist(scope.song);
    }
});
_

scope.loadFunction(song,callback)を呼び出すパーツを追加し、この関数が曲のURLを読み込んだ後、コールバックを呼び出してコントロールをangle-soundmanager2に戻します。

問題は、chrome for Androidエラーが表示されることです:

_Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
_

曲の先頭からURLがあり、非同期読み込みが使用されていない場合は発生しません。

回避策はありますか?

24
andreybavt

Chrome=サウンドを再生します。クリックなどのユーザージェスチャの後でも1000ms待機し、サウンドが再生されない場合は上記の例外がスローされます。問題が非同期トラックURLの読み込みに起因していた場合。

しかし、最初のトラックが再生された後、chromeはこの1000msの遅延を気にしなくなり、タイムアウトをプログラムで呼び出すことができます。

したがって、解決策は、ユーザーが最初にトラックをクリックしてから目的のトラックURLを読み込んだ後、静的リソースからほぼゼロ秒の長いミュートサウンドを再生することでした。

それが役立つか、誰かが他の解決策を見つけることを願っています。

23
andreybavt
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  webSettings.setMediaPlaybackRequiresUserGesture(false);
}
3

以下に、このソリューションをsoundmanager2に埋め込む方法を示します。

関数を作成します。

function playMicroTrack(scope, angularPlayer) {
if (!scope.$root.isInitialized) {
    soundManager.createSound({
        id: '-1',
        url: '../../assets/lib/microSound.mp3'
    });
    soundManager.play('-1');
    scope.$root.isInitialized = true;
    }
}

次に、playディレクティブ内で次を使用します。

ngSoundManager.directive('playAll', ['angularPlayer', '$log',
function (angularPlayer, $log) {
    return {
        restrict: "EA",
        scope: {
            songs: '=playAll'
        },
        link: function (scope, element, attrs) {
            element.bind('click', function (event) {

                playMicroTrack(scope, angularPlayer);

                //first clear the playlist
                angularPlayer.clearPlaylist(function (data) {
                    $log.debug('cleared, ok now add to playlist');
                    //add songs to playlist
                    for (var i = 0; i < scope.songs.length; i++) {
                        angularPlayer.addTrack(scope.songs[i]);
                    }

                    if (attrs.play != 'false') {
                        //play first song
                        angularPlayer.play();
                    }
                });
            });
        }
    };
}
]);

私の場合、soundManager.playには、サーバーに非同期呼び出しを送信してトラックURLを取得するコードが含まれています。これが問題の原因でした。

お役に立てれば

2
andreybavt

Andreybavtのソリューションに似ています。ここに私が問題を解決した方法があります。使用するすべてのサウンドを再生/一時停止する関数を作成しました。この関数はonClickと呼ばれます。このクリックは非常に重要です。ユーザーのジェスチャーが必要になります。

$("#myBtn").on("click", function(){
 setSounds();
});

function setSounds() {

  //Play and pause all sounds you want to use
  var audio1 = $("#mus_1")[0];
  var audio2 = $("#mus_2")[0];

  audio1.play();
  audio1.pause();

  audio2.play();
  audio2.pause();
}

すぐに再生して一時停止すると、再生が聞こえないすべてのサウンドが「クライアントジェスチャの後に読み込まれ」、プログラムで呼び出し/再生できるようになります。お役に立てれば。

1
Charles R.