LoginSignup
0

posted at

mediaDevices.getUserMedia() と iOS の Safari でハマった

はじめに

これらの記事で紹介したように、ウェブブラウザで動作するアプリでカメラ画像を扱うプログラムを書きました。
このとき、自分は Windows 機の Edge ブラウザで確認していて問題なかったのですが、他の環境で上手く動作しないことが分かりました。

最初のエラー

上記の記事で使ったのが、以下のコードです。

app.html
    <video id="video"></video>
app.js
    var video = document.querySelector('#video');
    navigator.mediaDevices.getUserMedia({
        video: {
            facingMode: 'environment'
        },
        audio: false
    })
    .then(function(stream){
        video.srcObject = stream;
        video.play();
    })
    .catch(function(e){

    });

Android 端末の Firefox は OK 。
Android 端末の Edge および Chrome は NG 。以下のエラーになりました。

Uncaught (in promise) DOMException: play() can only be initiated by a user gesture.

以下のコードにして回避しました。

app.html
    <video id="video"></video>
    <button id="start">開始</button>
app.js
    document.querySelector('#start').addEventListener('click', function(){
        var video = document.querySelector('#video');
        navigator.mediaDevices.getUserMedia({
            video: {
                facingMode: 'environment'
            },
            audio: false
        })
        .then(function(stream){
            video.srcObject = stream;
            video.play();
        })
        .catch(function(e){

        });
    });

次のエラー

上記のコードはどちらも、iOS の Safari で NG でした。以下のエラーになりました。

Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

同じ Safari でも Mac OS は OK でした。
iOS の Chrome も NG でした。以下のような訳だったんですね。

調べていくと、以下のような記事を見つけられました。

これらの記事を参考に、以下のコードにして回避しました。

app.html
    <video id="video" autoplay muted playsinline></video>

次のエラー

上記のコードは video タグにカメラ画像を表示していますが、その内容を canvas タグにコピーして表示するようにします。

app.html
    <canvas id="canvas"></canvas>
app.js
    var video = document.createElement('video');
    var canvas = document.querySelector('#canvas');
    navigator.mediaDevices.getUserMedia({
        video: {
            facingMode: 'environment'
        },
        audio: false
    })
    .then(function(stream){
        video.srcObject = stream;
        video.play();
        setInterval(function(){
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, canvas.width, canvas.height);
        }, 200);
    })
    .catch(function(e){

    });

これも iOS の Safari で NG でした。
以下のコードにすればどうでしょうか。

app.js
    var video = document.createElement('video');
    video.autoplay = true;
    video.muted = true;
    video.playsInline = true;
    以下略

これでよさそうです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0