skip to Main Content

I try to start the users camera in an html5 app. On my pc this works fine, but testing this on iphone (chrome and safari) the event playing is not triggered.

I created a minimalistic html-page to test this.

<!DOCTYPE html>
<html>
    <head>
        
    </head>
    <body onload="pageLoaded()"> </body>
    <script >
        async function startCamera() {
            let stream = await navigator.mediaDevices.getUserMedia({ video: {facingMode: 'user'}, audio: false});
            if(!stream) return;
            let video = document.createElement("video");
            video.srcObject = stream;
            video.oncanplay = (ev) => {
                console.log("video can play");
                video.oncanplay = "";
            }
            video.onplaying = (ev) => {
                console.log("video is playing");
            }
            video.play();
        }


        function pageLoaded() {
            startCamera();
        }
    </script>
</html>

On mobile I use chrome://inspect to see the logs.
"video can play" is shown, but "video is playing" never shows up.

On my desktop pc, this works just fine.
I didn’t test firefox, edge and opera though…
And I don’t have an android device to test this.
But as I looked up the specification it showed up that the "playing" event is supported by every modern browser.

Does anyone know what I am missing here? Do need to make an additional request for user rights? Do I need to wait for another event to chain the events?

After another test (thx for the comment), this code works.
The trick seems to be clicking the video element to play the camera video stream. Here is the code:

<!DOCTYPE html>
<script >
    async function startCamera() {
        let stream = await navigator.mediaDevices.getUserMedia({ video: {facingMode: 'user'}, audio: false});
        if(!stream) return;
        let video = document.createElement("video");
        video.style.width = 400;
        video.style.height = 400;
        video.style.border = "1px solid red";
        document.body.appendChild(video);
        

        video.srcObject = stream;
        video.oncanplay = (ev) => {
            console.log("video can play");
            video.oncanplay = "";
        }
        video.onplaying = (ev) => {
            console.log("video is playing");
        }
        video.onclick = () => { video.play();}
        //video.play();
    }


    function pageLoaded() {
        startCamera();
    }
</script>

It would be nice if the user didn’t have to do the click, but I guess for now I’ll use it that way until I figure out how to solve this. Help is appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    I made some further tests. It seems, you don't have to add the video element to the document. But on mobile you can't start the video automatically but have to user to "click" something to activly start the video.

    Here is a piece of code to show the behaviour on ios.

    <!DOCTYPE html>
    
    <script >
        async function startCamera() {
            let stream = await navigator.mediaDevices.getUserMedia({ video: {facingMode: 'user'}, audio: false});
            if(!stream) return;
            let video = document.createElement("video");
            
            let btn = document.createElement("button");
            btn.innerHTML = "click me";
            document.body.appendChild(btn);
            btn.onclick = () => {video.play(); } //THIS WORKS
    
            video.srcObject = stream;
            video.oncanplay = (ev) => {
                console.log("video can play");
                video.oncanplay = "";
                //video.play(); //THIS DOESN'T WORK
            }
            video.onplaying = (ev) => {
                console.log("video is playing");
            }
            video.onclick = () => { video.play();} //THIS WORKS
            //video.play(); THIS DOESN'T WORK
        }
    
    
        function pageLoaded() {
            startCamera();
        }
    </script>
    

    So "clicking" the video elements works (you will have to add it then) or "clicking" some button will also do the trick. One thing though. If I do not display the video element (not added to document or display = none) the camera screen on my mobile keeps black. Displaying the video element on the website shows me looking into the camera.


  2. To prevent nasty ads from playing automatically, some browsers prevent autoplay, which includes calling .play() without user interaction. play () returns a promise to indicate the success.

    https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play#usage_notes

    Although the term "autoplay" is usually thought of as referring to pages that immediately begin playing media upon being loaded, web browsers’ autoplay policies also apply to any script-initiated playback of media, including calls to play().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search