Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Recorded video is stretched #452

Closed
3 of 4 tasks
HorbachAndrii opened this issue Sep 23, 2021 · 9 comments · Fixed by #1466 or #2519
Closed
3 of 4 tasks

🐛 Recorded video is stretched #452

HorbachAndrii opened this issue Sep 23, 2021 · 9 comments · Fixed by #1466 or #2519
Labels
🐛 bug Something isn't working 📢 help wanted Extra attention is needed

Comments

@HorbachAndrii
Copy link

HorbachAndrii commented Sep 23, 2021

What were you trying to do?

Record video.

Reproduceable Code

<Camera
 ref={cameraRef}
 style={styles.recordVideo}
 device={devices.front}
 video={true}
 audio={true}
 isActive={isActiveRecordVideo}
 preset="iframe-1280x720"
/>


or Full code

import React, {useLayoutEffect, useRef, useState} from 'react';
import {
  Pressable,
  SafeAreaView,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import {VLCPlayer} from 'react-native-vlc-media-player';
import {Camera, useCameraDevices} from 'react-native-vision-camera';
import {RNCamera} from 'react-native-camera';


const AppVisionCamera = () => {
  const devices = useCameraDevices();

  const [isRecordingVide, setIsRecordingVide] = useState(false);
  const [recordedVideo, setRecordedVideo] = useState(null);

  const cameraRef = useRef();

  useLayoutEffect(() => {
    const getPermissions = async () => {
      const cameraPermission = await Camera.getCameraPermissionStatus();
      if (cameraPermission === 'not-determined') {
        const newCameraPermission = await Camera.requestCameraPermission();
        console.log('newCameraPermission', newCameraPermission);
      }
      const microphonePermission = await Camera.getMicrophonePermissionStatus();
      console.log('microphonePermission', microphonePermission);
      if (microphonePermission === 'not-determined') {
        const newMicrophonePermission =
          await Camera.requestMicrophonePermission();
        console.log('newMicrophonePermission', newMicrophonePermission);
      }
    };
    getPermissions();
  }, []);

  const onStartRecording = async () => {
    setRecordedVideo(null);
    setIsRecordingVide(true);
    console.log('cameraRef', cameraRef.current);
    cameraRef.current.startRecording({
      fileType: 'mp4',
      onRecordingFinished: async (video) => {
        console.log('onRecordingFinished', video);
        setRecordedVideo(video.path);
      },
      onRecordingError: (error) => {
        console.error('onRecordingError', error);
      },
    });
  };

  const onStopRecording = async () => {
    await cameraRef.current.stopRecording();
    setIsRecordingVide(false);
  };

  return (
    <SafeAreaView style={StyleSheet.absoluteFill}>
      <StatusBar barStyle="dark-content"/>
      <ScrollView contentInsetAdjustmentBehavior="automatic">
        
          <View style={styles.viewRecordVideo}>
            {devices.front && (
              <Camera
                ref={cameraRef}
                style={styles.recordVideo}
                device={devices.front}
                video={true}
                audio={true}
                isActive={true}
                preset="high"
              />
            )}
          </View>

        <View style={styles.viewButtons}>
          {isRecordingVide ? (
            <Pressable onPress={onStopRecording}>
              <Text style={styles.buttonText}>Stop record</Text>
            </Pressable>
          ) : (
            <Pressable onPress={onStartRecording}>
              <Text style={styles.buttonText}>Start record</Text>
            </Pressable>
          )}
        </View>

        <View style={styles.viewPlayer}>
          {recordedVideo && (
            <VLCPlayer
              style={styles.player}
              resizeMode="contain"
              repeat={true}
              source={{uri: recordedVideo}}
            />
          )}
        </View>
        <View style={styles.viewButtons}>
          <Pressable
            onPress={() => setRecordedVideo(null)}>
            <Text style={styles.buttonText}>Remove video</Text>
          </Pressable>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};


const styles = StyleSheet.create({
  viewPlayer: {
    width: '100%',
    height: 220,
  },
  player: {
    flex: 1,
  },

  viewRecordVideo: {
    width: '100%',
    height: 300,
  },
  recordVideo: {
    flex: 1,
  },

  viewButtons: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    width: '100%',
    height: 50,
    backgroundColor: `black`
  },
  buttonText: {
    padding: 10,
    fontSize: 20,
    color: 'white',
    borderWidth: 1,
    borderColor: 'white',
    borderRadius: 8,
  },
});


export default AppVisionCamera;

What happened instead?

When I playback recorded video with preset="iframe-1280x720 or iframe-960x540" I have stretched video.
You can see a bug on this video

Relevant log output

No response

Device

iPhone 7 (IOS 15.0)

VisionCamera Version

2.8.0

Additional information

@HorbachAndrii HorbachAndrii added the 🐛 bug Something isn't working label Sep 23, 2021
@HorbachAndrii
Copy link
Author

HorbachAndrii commented Sep 23, 2021

update:
When I added props fps={24} to Camera component, video doesn't stretched anymore

@mrousavy
Copy link
Owner

Are you sure that the video is not just streched because your <Video> component is stretched? What resizeMode did you pass to the <Video> component?

@HorbachAndrii
Copy link
Author

yes, I'm sure.
I did download the recorded video and watched it on my computer and the video also was be stretched.

@mrousavy mrousavy added the 📢 help wanted Extra attention is needed label Sep 26, 2021
@mrousavy mrousavy changed the title Recorded video is stretched🐛 🐛 Recorded video is stretched Sep 27, 2021
@mrousavy
Copy link
Owner

Does it work if you don't use the preset?

@HorbachAndrii
Copy link
Author

If I don't use preset, recording video works well. I mean recorded video will not be stretched.

@dylan-westbury
Copy link

For me preset seems to work fine with mp4, however when adding videoCodec as h264 (so it can be viewed in chrome) is when the video stretches.

Any ideas if it can be resolved?

We need to record in mp4 not mov because of a service we use, however chrome will only show videos in h264

   flash: "off",
   fileType: "mp4",
   onRecordingFinished,
   onRecordingError,
 };

 if (availableCodes.includes("h264")) {
   cameraOptions.videoCodec = "h264"; // video stretches if codec is h264
 }```

  ```<Camera
     ref={camera}
     style={StyleSheet.absoluteFill}
     device={device}
     preset="iframe-1280x720"
     orientation="portrait"
     onError={onCameraError}
     video
     audio
     isActive={isActive}
   />```

@HorbachAndrii
Copy link
Author

HorbachAndrii commented May 26, 2022

@dylan-westbury

For works well. Using react-native-vision-camera: 2.12.1

const newVideoPath = await new Promise((resolve, reject) => {
  cameraRef.current.startRecording({
    fileType: `mp4`,
    videoCodec: Platform.OS === `android` ? undefined : `h264`,
    onRecordingFinished: (video) => {
      resolve(video.path);
    },
    onRecordingError: (error) => {
      reject(error);
    },
  });
});
<Camera
  style={styles.camera}
  ref={cameraRef}
  device={device}
  video={true}
  audio={true}
  isActive={true}
  fps={25}
  preset="iframe-960x540"
  orientation="portrait"
  onInitialized={() => setCameraIsReady(true)}
  onError={(error) => {
    console.log(`Camera onError`, error);
  }}
/>

@TexxUkr
Copy link

TexxUkr commented May 15, 2023

have "stretched" video on iphone 12 mini iOS 16.4.1 in case if recording uses h264 codec and camera preset is medium or low. In case if no preset video is ok.
Adding fps={25} fixed the issue.

recording- cameraRef.current.startRecording({ // flash: flash, videoCodec: 'h264', fileType: 'mp4', onRecordingError: (error) => { console.error('### Recording failed!', error) }, onRecordingFinished: (video) => { console.log(Recording successfully finished! ${video.path}) onMediaCaptured(video) }, })

    camera- `<CameraView
      ref={cameraRef}
      device={device}
      isActive={true}
      onInitialized={onInitialized}
      onError={(err) => {
        console.log('### error:', err)
      }}
      enableZoomGesture={false}
      photo={true}
      video={true}
      audio={true}
      orientation="portrait"
      preset="medium"
  />`
    
    this works well - `<CameraView
      ref={cameraRef}
      device={device}
      isActive={true}
      onInitialized={onInitialized}
      onError={(err) => {
        console.log('### error:', err)
      }}
      enableZoomGesture={false}
      photo={true}
      video={true}
      audio={true}
      orientation="portrait"
      preset="medium"
      fps={25}
    />`

@mrousavy
Copy link
Owner

Hey!

After 8 hours of debugging, I finally found the culprit! I fixed the preview stretching issue in this PR: #2377

If you appreciate my dedication and free support, please consider 💖 sponsoring me on GitHub 💖 so I can keep providing fixes and building out new features for my open-source libraries in my free time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working 📢 help wanted Extra attention is needed
Projects
None yet
4 participants