Подтвердить что ты не робот

Не удалось выполнить "воспроизведение" в "HTMLMediaElement": API может быть инициирован только жестом пользователя

Я создаю страницу для воспроизведения музыки, где я использую SoundManager 2 для 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 для android я получаю сообщение об ошибке:

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

это не происходит, если песня имеет URL-адрес с самого начала, а асинхронная загрузка не используется.

Есть ли какие-нибудь обходные пути?

4b9b3361

Ответ 1

Мне пришлось поэкспериментировать с игровыми звуками в Chrome. Оказалось, что даже после жестов пользователя (например, щелчка) он ждет 1000 мс, и если звук не воспроизводится, он выдает исключение выше. В моем случае проблема заключалась в асинхронной загрузке URL трека.

Но также выяснилось, что после того, как первый трек будет воспроизведен, хром больше не заботится об этой задержке в 1000 мс, и вы можете вызвать программу программно с любым тайм-аутом, который вы хотите.

Таким образом, решение заключалось в том, чтобы воспроизводить микро почти почти нулевой секундой звук без звука из статических ресурсов после того, как пользователь впервые нажимает на трек и после этого загружает желаемый URL-адрес трека.

Надеюсь, что это поможет, или кто-то найдет другие решения.

Ответ 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;
    }
}

Затем внутри директивы воспроизведения используйте:

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-адреса трека. Это вызвало проблему.

Надеюсь, что это поможет

Ответ 3

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

Ответ 4

Аналогично решению 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();
}

Играя и приостанавливая сразу все звуки, вы не услышите их воспроизведение, они будут "загружены после жесты клиента", и вы сможете впоследствии их вызвать и воспроизвести. Надеюсь, это поможет.