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

Я создаю страницу для воспроизведения музыки, где я использую SoundManager 2 для AngularJs . Я использую удаленный API для получения URL-адреса песни. Я усовершенствовал обработчик события click-angman-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-адрес песни, он вызывает обратный вызов, чтобы вернуть управление угловому-soundmanager2.

Проблема в том, что на chrome для android я получаю сообщение об ошибке:

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

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

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

Solutions Collecting From Web of "Не удалось выполнить «play» в «HTMLMediaElement»: API может быть инициирован только жестом пользователя"

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

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

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

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

Вот как я включил это решение в 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-адреса трека. Это вызвало проблему.

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

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

Похоже на решение 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(); } 

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