react-native-webview: Camera Freezes on Android

When I open https://simpl.info/getusermedia/sources/ on Chrome in Android, I’m able to see the camera and switch between front and back camera’s too. But when I open the same uri on webView , it works fine on iOS but on android the camera stucks in some devices and in some devices I’m not able to toggle between front and back Cam (where i’m taking frontCam as the first Camera Id and backCam as the last camera id) Get User Media is not giving me the ID when I log the data from web to native but the camera is still getting frozen on Android. I have used gUM logic of this website in my react Video conferencing app and I’m facing issues in both the links.

To Reproduce: My Web Code >

  function getStream() {
    const constraints = {
      audio: { deviceId: undefined },
      video: { deviceId: undefined },
    };
    return navigator.mediaDevices.getUserMedia(constraints);
  }
  
    function getDevices() {
    return navigator.mediaDevices.enumerateDevices();
  }
  
    useEffect(() => {
    getStream()
      .then(getDevices)
      .then((res) => {
        var cameraArray = res.filter((device) => device.kind === "videoinput");
        var MicArray = res.filter((device) => device.kind === "audioinput");
        setMicrophones(MicArray);
        setCameras(cameraArray);
      });
  }, []);

My Webview >

      <View  renderToHardwareTextureAndroid={true}>
        <WebView
          ref={webviewRef}
          source={{
            uri: "https://simpl.info/getusermedia/sources/",
          }}
          style={{
            minHeight: 100 * global.mpx,
            height: '100%',
            //opacity :0.99
          }}
          javaScriptEnabled
          onMessage={(e) => {
            webViewCommunicationFn(e);
          }}
          scalesPageToFit={false}
          mediaCapturePermissionGrantType={true}
          textZoom={100}
          allowsInlineMediaPlayback={true}
          mediaPlaybackRequiresUserAction={false}
          originWhitelist={['*']}
          scrollEnabled={false}
          androidHardwareAccelerationDisabled={true}
          onLoadEnd={() => {
            setIsWebViewLoaded(true);
          }}
        ></WebView>
        </View>

Expected behavior: Front Cam should work without freezing smoothly and Back Cam toggle should also function like how it does on iOS Screenshots/Videos:

Environment:

  • OS: macOS
  • OS version: 12.4
  • react-native version: 0.67.4
  • react-native-webview version: ^11.17.2

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 19

Most upvoted comments

@callmemonky sure thing.

Here is a simplified version of my code that uses Chakra UI’s dependency emotion keyframes method to animate an icon from react-icons

// webcam.tsx

import React, { useRef } from 'react';
import ReactWebcam from 'react-webcam';
import { useBreakpointValue } from '@chakra-ui/react';
import { RedBlinkingDot } from './red-blinking-dot';

export const Webcam = () => {
  const webcamRef = useRef<ReactWebcam | null>(null);

  const videoConstraints: MediaStreamConstraints['video'] = useBreakpointValue({
    base: {
      width: 640,
      height: 720,
      aspectRatio: 4 / 3,
    },
  });

  return <>
    <ReactWebcam
      style={{ margin: '0 auto' }}
      ref={webcamRef}
      onUserMedia={/* your callback*/}
      onUserMediaError={/* your callback */}
      audio={false}
      autoPlay
      playsInline
      screenshotFormat={'image/png'}
      videoConstraints={videoConstraints}
    />
    <RedBlinkingDot />
  </>;
};
// red-blinking-dot.tsx

import React from 'react';
import { GoPrimitiveDot as Dot } from 'react-icons/go';
import { Icon } from '@chakra-ui/icons';
import { keyframes } from '@chakra-ui/react';
import { Colors } from '@ss/theme';

const animationKeyframes = keyframes({
  '0%': {
    transform: 'scale(1)',
  },
  '100%': {
    transform: 'scale(1.5)',
  },
});

const animation = `${animationKeyframes} 1s ease-in-out infinite`;

export const RedBlinkingDot = () => {
  return <Icon as={Dot} animation={animation} color={Colors.red} />;
};

Any solutions for this?

As mentioned by the chromium issue, adding a spinner helps to keep the video feed live. Worked for me on a current project.

What closed this issue?

I’m also having the same problem with webview and a site that uses navigator.mediaDevices.getUserMedia.

It works fine on some android devices, but on others it does freeze or drop a lot of frames.

It looks like a focus issue, because if i touch the screen and hold(anywhere inside the webview), the camera works fine with a good FPS.

As soon as I stop moving my finger or end the touch, the fps starts dropping and/or video freezes.

are there any news on this? We are facing the same problem especially on Samsung Devices. Sometimes it works sometimes it doesn’t. Doesn’t matter if the app that uses React Native Webview is installed in the Samsung Secure Folder or not. Does not matter if Android System Webview is installed or not in any version. There is also nothing in the logs. The only thing we see is that most frames are dropped in the preview but using the Webview to take pictures or use libraries using the Webview features still works. So it’s basically the preview delivered by React Native Webview

The only thing we see is in the VideoPlaybackQuality:

VideoPlaybackQuality (creationTime: 267489.59999999404,
  corruptedVideoFrames: 0
  creationTime:267489.59999999404
  droppedVideoFrames:3885
  totalVideoFrames:4068