DOMException: play () может быть инициирован только жестом пользователя

Я работаю над QRCode Reader с JavaScript. Если пользователь находится на моем Wensite, он запрашивает разрешение на использование камеры. Как только пользователь примет это, он включит безумную камару. Я использую Samsung Galaxy S4 с последней версией Chrome, и пока это работает отлично.

Я добавил выпадающий список для изменения от передней к задней камаре. Как только я меняю камеру, поток видео останавливается, и я получаю эту ошибку.

Uncaught (в обещании) 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();

}

Ответы на вопрос(2)

Решение Вопроса

вероятно, связано с надежной моделью безопасности. Некоторые операции разрешены, только если они инициированы пользователем. , например, как работает много блокировщиков всплывающих окон. Кроме того, 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 элемент?

 Mihawk05 авг. 2016 г., 16:46
Все еще не работает. Элемент Видео превращается в черное поле. Как я знаю, автовоспроизведение отключено от Google, чтобы сохранить пропускную способность пользователей. Странная вещь на старой версии, она также попросила у Камары разрешение на Изменения. В последней версии это не так.
 mchiasson20 сент. 2017 г., 22:19
в моем случае «щелчок» не вызывается в Chrome для Android. Единственный тип событий, который работает для сенсорного экрана, это «touchstart» или «touchend». К сожалению, это все еще дает мне то же самое DOMException с этими событиями. Похоже, Android не рассматривает сенсорный запуск / касание как жест пользователя.

может быть, немного поздно, но я выяснил, как решить эту проблему после нескольких экспериментов. Я пытался создать бесконечный цикл для звука, который начинается после кнопки воспроизведения, и я не хотел этого с HTMLautoplay атрибут, который создавал разрыв, пока он повторялся. Тогда я понял, что если я создам<audio> пометить дважды одинаковым звукомsrc и тогда я могsetTimeout(function); начать второй сразу после окончания первого, и это будет цикл. Вот где я столкнулся с этимplay() DOMException, На рабочем столе он был безупречен, но на мобильном он останавливался, потому что требовался жест. Тогда я узнал, что если тыplay() аудио с жестом в течение 1 раза, то вы сможетеpause() задаватьcurrentTime = 0; а потомplay() снова без жеста пользователя. Код ниже создает бесконечный цикл для мобильных и настольных компьютеров без каких-либо проблем.

ЗдесьDEMO

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

Ваш ответ на вопрос