DOMException: play() может быть инициирован только жестом пользователя
Я работаю над QRCode Reader с JavaScript.
Если пользователь находится на моем Wensite, он запрашивает разрешение на использование камеры. Как только пользователь примет его, он включит фрэм-камару. Я использую Samsung Galaxy S4 с последней версией Chrome, и это пока прекрасно работает.
Я добавил Dropdown to Change от передней части к задней части камеры.
Как только я сменил камеру, поток видео останавливается, и я получаю эту ошибку.
Невозможно (в обещании) DOMException: play() может быть инициирован только пользовательский жест.
Я пробовал это на старой версии Chrome, которая отлично работала даже с изменением камеры.
var videoElement = document.createElement("video");
var videoSelect = document.querySelector("select#videoSource");
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
function start() {
if (window.stream) {
videoElement.src = null;
window.stream.stop();
}
var videoSource = videoSelect.value;
var tw = 640 // 320 // 640 // 1280;
var th = 480 // 240 // 480 // 720
var hdConstraints = {
audio: false,
video: {
mandatory: {
maxWidth: tw,
maxHeight: th
},
optional: [{
sourceId: videoSource
}]
}
};
if (navigator.getUserMedia) {
navigator.getUserMedia(hdConstraints, success, errorCallback);
} else {
errorCallback("");
}
}
videoSelect.onchange = start;
start();
function gotSources(sourceInfos) {
for (var i = 0; i !== sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
var option = document.createElement("option");
option.value = sourceInfo.id;
if (sourceInfo.kind === "video") {
option.text = sourceInfo.label || "camera " + (videoSelect.length + 1);
videoSelect.appendChild(option);
} else {
console.log("Some other kind of source: ", sourceInfo);
}
}
}
if (typeof MediaStreamTrack === "undefined") {
alert("This browser does not support MediaStreamTrack.\n\nTry Chrome.");
} else {
MediaStreamTrack.getSources(gotSources);
}
function errorCallback(e) {
console.log("Cant access user media", e);
}
function success(stream) {
window.stream = stream;
videoElement.src = window.URL.createObjectURL(stream);
videoElement.onclick = function() { videoElement.play(); };
videoElement.play(); //Here is the Error
function getFrame() {
requestAnimationFrame(getFrame);
if (!videoElement.videoWidth) return;
if (!image) {
width = videoElement.videoWidth, height = videoElement.videoHeight;
log("videoElement", width, height, videoElement);
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
canvas.style.transform = "scale(1, 1)";
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
log("start");
image = Module._xsetup(width, height);
log("_xsetup", image, "pointer");
return;
}
ctx.drawImage(videoElement, 0, 0, width, height);
var imageData = ctx.getImageData(0,0, width, height);
data = imageData.data;
gofill();
}
getFrame();
}
Ответы
Ответ 1
Вероятно, это связано с надежной моделью безопасности. Некоторые операции разрешены только в том случае, если они инициированы пользователем. Это, например, как работает много блокировщиков всплывающих окон. Также Chrome может защитить пользователей от видео с автоматическим воспроизведением.
Убедитесь, что вы вызываете videoElement.play()
в обработчике событий, который связан с жестом.
// this should be ok
videoElement.addEventListener("click", function () {
videoElement.play();
});
// this is not ok
setTimeout(function () {
videoElement.play();
});
Поскольку ваша функция вызывается в navigator.getUserMedia
, было бы странно снова запрашивать ввод пользователя. Вы пытались использовать autoplay
в элементе video
?
Ответ 2
Для кого все это имеет и пытается решить эту проблему с автоигрой; может быть, немного поздно, но я выяснил, как решить эту проблему, после нескольких экспериментов. Я пытался создать бесконечный цикл для звука, который начинается после кнопки воспроизведения, и я не хотел этого с атрибутом autoplay
HTML, который создавал пробел, пока он повторялся. Затем я понял, что если я дважды создаю <audio>
с одним и тем же звуком src
то я setTimeout(function);
установить setTimeout(function);
начать второй сразу после окончания первого, и это будет цикл. Вот где я столкнулся с этим play() DOMException
. На рабочем столе он был безупречен, но на мобильном он останавливался, потому что требовал жеста. Затем я обнаружил, что если вы play()
звук жестом в течение 1 раза, то вы можете сделать pause()
set currentTime = 0;
и затем play()
снова без пользовательского жеста. Код ниже создает бесконечный цикл для мобильных и настольных компьютеров без каких-либо проблем.
Вот ДЕМО
HTML
<audio id="rain" src="https://www.soundjay.com/nature/sounds/water-dripping-1.mp3" preload="auto">
</audio>
<audio id="rainloop" src="https://www.soundjay.com/nature/sounds/water-dripping-1.mp3" preload="auto">
</audio>
<button>
Rain
</button>
<div id="slider"></div>
JS
$(document).ready(function(){
var interloop;
var aud = document.getElementById("rain");
var audloop = document.getElementById('rainloop');
var wplay = aud;
$('button').click(function(){
if(aud.paused && audloop.paused){
audloop.play();
audloop.pause()
audloop.currentTime = 0;
looper();
} else {
aud.pause();
aud.currentTime = 0;
audloop.pause();
audloop.currentTime = 0;
clearInterval(interloop);
}
});
function looper(){
wplay.play();
if(wplay == aud){
wplay = audloop;
} else {
wplay = aud;
}
interloop = setTimeout(looper, 4600);
}
$('#slider').slider({
value: 100,
slide:changevolume,
stop:changevolume
});
function changevolume(){
var val = $('#slider').slider('value');
aud.volume = (val/100);
audloop.volume = (val/100);
}
});
Ответ 3
Это может помочь.
webViewSettings.setMediaPlaybackRequiresUserGesture(false);