4

I'm trying to capture the camera input and play it in a video element. This code always works on desktop Chrome and Safari. On iOS it always works while in browser mode using Safari.

The problem I'm facing is it will only sometimes not work in standalone PWA mode (saved to Home Screen) for iOS. I'm not getting any errors, and it will happen seemingly randomly. I'll think I fixed it only for it to happen again hours later. Sometimes closing the app and re-opening works, sometimes it takes 10+ tries. I've tried so many different versions of the code, async, promise based, waiting for onload, canplay, etc.

The stream loads and is active (when permissions are granted), the srcObject shows as properly set, but video.play() doesn't work. I tried waiting for the play promise but sometimes it would just never resolve. The video readyState stays at 0. Sometimes the code will work fine though and the video plays the camera stream like normal.

Any help would be greatly appreciated.

navigator.mediaDevices
    .getUserMedia({
        video: {
            width: { min: 640, ideal: 1280, max: 1920 },
            height: { min: 480, ideal: 720, max: 1080 },
            facingMode: 'environment'
        },
        audio: true
    })
    .then((stream) => {
        let video = document.createElement('video');
        video.controls = true;
        video.muted = true;
        video.playsInline = true;
        video.onerror = function (e) {
            console.log(e);
        };
        video.onabort = function (e) {
            console.log(e);
        };
        console.log(stream);
        try {
            video.srcObject = stream;
        } catch (e) {
            console.log(e);
            window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
            video.src = window.URL && window.URL.createObjectURL(stream);
        }
        console.log('source: ', video.src);
        console.log('sourceObj: ', video.srcObject);
        console.log(video);
        //Dirty hack to try and debug, same result, tried waiting for play promise, play() onloaded, play() oncanplay, all same result
        //video state sometimes gets to 4, sometimes stays at 0
        let interval = setInterval(() => {
            console.log(video.isConnected);
            console.log(video.readyState);
            console.log(video);
            console.log(stream);
            //will sometimes just stay at readyState 0
            if (video.readyState === 4) {
                video.play();
                window.clearInterval(interval);
            }
        }, 500);
    });

Christopher Thompson
  • 3,293
  • 1
  • 10
  • 16
  • Did you ever figure this out? – Alex Cory Aug 05 '22 at 18:37
  • Not entirely. I think it's a webkit bug, possibly related to this: https://bugs.webkit.org/show_bug.cgi?id=179363. I did find a way to "fix" it when it happens though, which is to close/quit the app while the prompt to give permissions for camera/mic is showing. So far it has worked every time to make the problem go away (until it happens again "randomly") – Christopher Thompson Aug 06 '22 at 17:13
  • I figured out it's getting stuck on either an `onloadedmetadata` event or when trying to call `video.play()`. To work around this for now I just put a setTimeout on it. If the video doesn't play after 3000ms, then I just prompt the user to do something else. – Alex Cory Aug 18 '22 at 22:50
  • I came to the same conclusion but have been unable to figure out why it happens, and for my use case I can't prompt the user to just do something else sadly. – Christopher Thompson Sep 05 '22 at 14:12
  • There is a newer WebKit bug opened at the moment for this, please comment and show your support for Apple to sort this - https://bugs.webkit.org/show_bug.cgi?id=252465 – Chris Mar 01 '23 at 12:16
  • Having this exact same issue. It's in Apple's hands for now... – zero_cool May 25 '23 at 16:37

0 Answers0