🐛 Recorded video is stretched
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
- [ ] I am using Expo
- [X] I have read the Troubleshooting Guide
- [X] I agree to follow this project's Code of Conduct
- [X] I searched for similar issues in this repository and found none.
update:
When I added props fps={24} to Camera component, video doesn't stretched anymore
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?
yes, I'm sure. I did download the recorded video and watched it on my computer and the video also was be stretched.
Does it work if you don't use the preset?
If I don't use preset, recording video works well. I mean recorded video will not be stretched.
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}
/>```
@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);
}}
/>
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}
/>`
Hey!
After 8 hours of debugging, I finally found the culprit! I fixed the preview stretching issue in this PR: https://github.com/mrousavy/react-native-vision-camera/pull/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.