react-webcam icon indicating copy to clipboard operation
react-webcam copied to clipboard

Switching deviceId in audio/video constraints freezes the browser in Chrome for Android

Open keithpickering opened this issue 3 years ago • 14 comments

Hi, please see this example for testing: https://dev.boothpics.com/booth/xlqp3o

This previous (now closed) issue features some codepen examples that also exhibit the issue: https://github.com/mozmorris/react-webcam/issues/170

Changing the videoConstraints or audioConstraints seems to freeze the entire browser, requiring a force close. I've tried to solve the issue by stopping media streams before switching the constraints, unmounting the Webcam component before remounting with the new constraints, and even a 5 second timeout (currently active in the example I linked)

Does anyone have a known solution for this?

keithpickering avatar Oct 29 '20 14:10 keithpickering

Hi @keithpickering - thanks for the report and trying to solve it.

I don't currently have an Android I can test on as I'm working from home. As a suggestion, I was wondering you might try creating a pure js solution eg no React, on user input calling getUserMedia with the new constraints, and seeing what result you get.

If that works, then it might be easier to track down where in the lifecycle we're doing something wrong.

mozmorris avatar Oct 29 '20 18:10 mozmorris

I've been running into the same problem, but also notice chrome will freeze in Android if I just try and capture an image. Tried all types of video constraints. I haven't been able to isolate the problem yet, but I started using https://github.com/MABelanger/react-html5-camera-photo as a drop in replacement and it seems to work when changing the facing mode on the fly, and also captures images without any problems. Maybe that will help someone.

ChrisZieba avatar Dec 01 '20 19:12 ChrisZieba

I have this same issue on all Android 11 devices. Are there any updates on this?

I found that putting the phone in standbye and on again "unstucks" it. Maybe it reinitializes the camera?

jellevwezel avatar Jan 12 '21 12:01 jellevwezel

Still looking for updates on this as well. We're on a tight sprint schedule so I haven't had time to debug the package itself. I just know the way it's supposed to work is causing a freeze.

@jellevwezel I've noticed this as well. Sometimes just going to the home screen and back can initiate the "unstick". I've tried a bunch of solutions for unmounting/remounting the camera, including totally removing the Webcam component from the DOM and then reinserting it with a different deviceId. Nothing seems to make it work as intended.

keithpickering avatar Jan 15 '21 16:01 keithpickering

Hey guys,

I had the same issue, the problem can be replicated when stopping media tracks on android 11.

I found that this is a bug with this version of android and it can be found here:

https://issuetracker.google.com/u/1/issues/173142922

RodolfoSarkisRocha avatar Feb 21 '21 17:02 RodolfoSarkisRocha

@RodolfoSarkisRocha thanks for the link.

I'm still working from home (🦠) and don't have access to any Android devices to observe the bug myself.

mozmorris avatar Feb 21 '21 18:02 mozmorris

@keithpickering I know you've been looking for an update for a while now. Did you ever come up with a workaround?

mozmorris avatar Feb 21 '21 18:02 mozmorris

It looks like in a near future Android Chrome version will fix this:

https://issuetracker.google.com/u/0/issues/173142922

Another thread: https://bugs.chromium.org/p/chromium/issues/detail?id=1138823#c25

Here's a really hacky workaround I haven't tested yet: https://gist.github.com/erdgzl/4220083e8f69083c42eda8b1aafb1ad9

Maybe programmatically resizing the window for just a split second will fix it as well.

ctrlaltdylan avatar Mar 26 '21 12:03 ctrlaltdylan

From what I can tell, you can't access the stream object outside of the context of the Webcam class. Which means the workaround can't be used without forking the library.

The other option is to somehow access the MediaStream from the video ref object. I'm just not sure if that's possible or not.

Then you could do something like this:

          const stream = videoRef.current.srcObject; // or however you'd access the stream from the video ref
          if (stream) {
            stream.getTracks().forEach(track => {
                track.stop();
            });
            stream = null;
        }

Excuse the spacing, I'm just pseudocoding right in Github here.

ctrlaltdylan avatar Mar 26 '21 12:03 ctrlaltdylan

@ctrlaltdylan that should work. And the stream is also passed to the onUserMedia callback prop.

mozmorris avatar Mar 26 '21 13:03 mozmorris

This worked for me : https://github.com/twilio/twilio-video-app-react/issues/355#issuecomment-780368725

guilngou avatar Mar 26 '21 15:03 guilngou

This is my final solution, works on my Pixel 4.

I use this little hack after uploading the photo from the videoRef.current.doScreenshot. Hopefully it helps y'all!

                        let stream = videoRef.current.video.srcObject;
                        if (stream) {
                          videoRef.current.video.srcObject = null;
                          stream.getTracks().forEach((track) => {
                            stream.removeTrack(track);
                            track.stop();
                          });
                          stream = null; // this is probably redundant, but it fixes it so I'm happy.
                        }

ctrlaltdylan avatar Mar 27 '21 12:03 ctrlaltdylan

@keithpickering thanks to the help of @BrendonSled there's a new version published under the next tag and a CodePen using it here: https://codepen.io/mozmorris/pen/vYxZgrP

Could you see if this solves the problem?

mozmorris avatar May 25 '21 15:05 mozmorris

Now released in 5.2.4

mozmorris avatar May 25 '21 20:05 mozmorris