无法在'HTMLMediaElement'上执行'play':API只能通过用户手势

时间:2015-09-06 14:48:34

标签: javascript android angularjs google-chrome soundmanager2

我正在制作音乐播放页面,我使用SoundManager 2 for AngularJs。 我正在使用远程API来播放歌曲URL。我增强了一个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之后调用一个回调来将控件返回到angular-soundmanager2。

问题是在chrome for android上我得到一个错误:

Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
如果歌曲从头开始并且未使用异步加载,则不会发生这种情况。

是否有任何解决方法?

4 个答案:

答案 0 :(得分:22)

我不得不尝试使用Chrome播放声音。事实证明,即使在用户手势(例如点击)之后,它等待1000毫秒,如果没有播放声音,则抛出上述异常。就我而言,问题来自异步跟踪URL加载。

但事实证明,在第一首曲目播放后,Chrome不再关心此1000毫秒的延迟,您可以通过编程方式调用所需的任何超时。

因此,解决方案是在用户第一次点击某个曲目后加载所需的曲目网址后,从静态资源中播放几乎为零秒的长静音。

希望它有所帮助或有人找到其他解决方案。

答案 1 :(得分:2)

以下是我将此解决方案嵌入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 :(得分:2)

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

答案 3 :(得分:1)

与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();
}

通过立即播放和暂停所有您听不到的声音,他们将在客户手势后加载#34;然后您就可以通过编程方式调用/播放它们。 希望这会有所帮助。