mrousavy / react-native-vision-camera

📸 A powerful, high-performance React Native Camera library.
https://react-native-vision-camera.com
MIT License
7.3k stars 1.07k forks source link

Camera device is getting null.🐛 #2326

Closed favaztechcurve closed 8 months ago

favaztechcurve commented 8 months ago

What's happening?

I wan to use react native vision camera in my rn app, but in some devices it works very fine. but in some device iam getting device as null or undefiend, happening in older device and latest devices. i am getting different errors also.

Reproduceable Code

import React, {
  useRef,
  useState,
  forwardRef,
  useCallback,
  useEffect,
  useImperativeHandle,
} from 'react';
import {useIsFocused} from '@react-navigation/core';

import {StyleSheet, Text, View} from 'react-native';
import {Camera, useCameraDevices, VideoFile} from 'react-native-vision-camera';
import Reanimated from 'react-native-reanimated';

import {useIsForeground} from '../hooks/UseIsForeground';

const AppCamera = forwardRef((props, ref) => {
  const camera = useRef(null);

  // Create a ref for the camera function
  const cameraFunctionRef = useRef();

  const [isCameraInitialized, setIsCameraInitialized] = useState(false);
  const [hasMicrophonePermission, setHasMicrophonePermission] = useState(false);
  const [recordingData, setRecordingData] = useState(null);

  // check if camera page is active
  const isFocussed = useIsFocused();
  const isForeground = useIsForeground();
  const isActive = isFocussed && isForeground;

  const [cameraPosition, setCameraPosition] = useState('back');

  // camera format settings
  const devices = useCameraDevices();
  const device = devices.front;

  useEffect(() => {
    Camera.getMicrophonePermissionStatus().then(status =>
      setHasMicrophonePermission(status === 'authorized'),
    );
  }, []);

  useImperativeHandle(ref, () => ({
    onCaptureVideo: onCaptureVideo,
    onStopRecording: onStopRecording,
    recordingData: recordingData,
  }));

  const onError = useCallback(error => {
    console.error(error);
  }, []);

  const onInitialized = useCallback(() => {
    console.log('Camera initialized!');
    setIsCameraInitialized(true);
  }, []);

  const onCaptureVideo = useCallback(() => {
    if (isCameraInitialized && isActive && camera) {
      setRecordingData(null);

      camera.current.startRecording({
        onRecordingFinished: video => {
          setRecordingData({...video, type: 'video/mp4', fileType: 'video'});
        },
        onRecordingError: error => console.error(error),
      });
    }
  }, [isCameraInitialized, isActive, camera]);

  const onStopRecording = useCallback(async () => {
    if (isCameraInitialized && isActive && camera) {
      await camera.current.stopRecording();
    }
  }, [isCameraInitialized, isActive, camera]);

  if (device != null) {
    console.log(
      `Re-rendering camera page with ${
        isActive ? 'active' : 'inactive'
      } camera. ` + `Device: "${device.name}" `,
    );
  } else {
    console.log('re-rendering camera page without active camera');
  }

  return (
    <View style={styles.container}>
      {device && device !== null && (
        <Reanimated.View style={StyleSheet.absoluteFill}>
          <Camera
            ref={camera}
            style={StyleSheet.absoluteFill}
            device={device}
            isActive={isActive}
            onInitialized={onInitialized}
            onError={onError}
            video={true}
            audio={hasMicrophonePermission}
            orientation="portrait"
          />
        </Reanimated.View>
      )}
    </View>
  );
});

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'black',
  },
  //   captureButton: {
  //     position: 'absolute',
  //     alignSelf: 'center',
  //     bottom: SAFE_AREA_PADDING.paddingBottom,
  //   },
  //   button: {
  //     marginBottom: CONTENT_SPACING,
  //     width: BUTTON_SIZE,
  //     height: BUTTON_SIZE,
  //     borderRadius: BUTTON_SIZE / 2,
  //     backgroundColor: 'rgba(140, 140, 140, 0.3)',
  //     justifyContent: 'center',
  //     alignItems: 'center',
  //   },
  //   rightButtonRow: {
  //     position: 'absolute',
  //     right: SAFE_AREA_PADDING.paddingRight,
  //     top: SAFE_AREA_PADDING.paddingTop,
  //   },
  //   text: {
  //     color: 'white',
  //     fontSize: 11,
  //     fontWeight: 'bold',
  //     textAlign: 'center',
  //   },
});

export default AppCamera;

Relevant log output

re-rendering camera page without active camera

Camera Device

undefined, i am not getting the device anything.

Device

Samsung galaxy note 5, redmi 11 pro +5g

VisionCamera Version

3.6.10

Can you reproduce this issue in the VisionCamera Example app?

I didn't try (⚠️ your issue might get ignored & closed if you don't try this)

Additional information

AlexDef commented 8 months ago

Same issue for me. I just downgraded to 3.6.16 and everything works fine

mrousavy commented 8 months ago

@AlexDef can you absolutely confirm that in 3.6.17 you get null, and in 3.6.16 it works properly? Nothing of the getCameraDevices logic has changed so this is very weird to me.

AlexDef commented 8 months ago

Yes I can confirm it, just downgrade and the useCameraDevice function start to work again. The bug was only on Android and not on every device, of course...

mrousavy commented 8 months ago

Wait - I just noticed that you are using useCameraDevices(). In V3, useCameraDevices() does something else. You should use the new useCameraDevice(...) (no s) hook instead. Read the docs for more info.

favaztechcurve commented 8 months ago

@mrousavy actually i was using 2.16.0 before and its works fine for me in my react native app. but for implimenting the video pausing functionality i updated the package to latest and the blank screen isssue arises in som e device for example samsung galaxy note 5, redmi 11 pro + etc..

"react-native-vision-camera": "^3.6.10",

i will give some of the code in implimented there.

`const camera = useRef(null); useEffect(() => { requestCameraPermissions().then(hasPermission => { if (hasPermission) { setCameraPermission(true); } else { console.error('Permissions not granted'); // Handle lack of permissions appropriately } }); }, []);

async function requestCameraPermissions() { if (Platform.OS === 'android') { const cameraPermission = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.CAMERA, ); const microphonePermission = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, ); return ( cameraPermission === PermissionsAndroid.RESULTS.GRANTED && microphonePermission === PermissionsAndroid.RESULTS.GRANTED ); } else { // For iOS, use react-native-vision-camera's requestCameraPermission method const cameraPermissionStatus = await Camera.requestCameraPermission(); const microphonePermissionStatus = await Camera.requestMicrophonePermission(); return ( cameraPermissionStatus === 'authorized' && microphonePermissionStatus === 'authorized' ); } } const cameraDevice = useCameraDevice('front'); const handleRecordVideo = async () => { if (camera.current) { try { console.log('camera.current.startRecording', camera.current); camera.current.startRecording({ flash: 'on', videoBitrate: 1000000, video: { codec: 'h264', frameRate: 30, }, onRecordingFinished: video => { setVideoPath(video.path); }, onRecordingError: error => console.error(error), }); startPlaying(); setRecordingStarted(true); } catch (e) { console.log(e); } } }; const toggleVideoPlaying = async () => { try { if (!paused) { await camera.current.pauseRecording(); await TrackPlayer.pause(); setPaused(true); } else { await camera.current.resumeRecording(); await TrackPlayer.play(); setPaused(false); } // setRecordingStarted(false); } catch (e) { console.log(e); } }; return (

{ // videoPath ? ( //