🐛 Potrait mode video is flipped to wrong direction
What's happening?
I am capturing the video in front camera with portrait and landscape mode. In Landscape mode it's working fine. but when i capture the video in portrait mode the video is flipped to wrong direction.
Please suggest.
Reproduceable Code
const frontformate = useCameraFormat(devicesFront, [
{ fps: 30 },
{videoStabilizationMode : 'off'},
{ videoResolution: { width: 1280, height: 720 } },
]);
const backformate = useCameraFormat(devicesBack, [
{ fps: 30 },
{videoStabilizationMode : 'off'},
{ videoResolution: { width: 1280, height: 720 } },
]);
<Camera
ref={cameraRef}
style={[styles.camera]}
audio={true}
video={true}
isMirrored={false}
device={cameraType === 'front' ? devicesFront : devicesBack}
isActive={true}
format={cameraType === 'front' ? frontformate : backformate}
/>
Relevant log output
2024-09-19 13:42:53.376174+0530 utrapp[3037:204765] [javascript] Permission: ios.permission.MICROPHONE, Status: granted
2024-09-19 13:42:53.384531+0530 utrapp[3037:204765] [javascript] 'isTablet', false
2024-09-19 13:42:53.384797+0530 utrapp[3037:204765] [javascript] 'isIpad', false
2024-09-19 13:42:53.385081+0530 utrapp[3037:204765] [javascript] 'iPhone', false
13:42:53.472: [info] 📸 VisionCamera.didSetProps(_:): Updating 25 props: [onInitialized, cameraId, position, enableBufferCompression, preview, onOutputOrientationChanged, onStarted, onCodeScanned, top, right, isActive, video, onViewReady, onError, onStopped, isMirrored, onPreviewOrientationChanged, onPreviewStopped, enableFrameProcessor, onPreviewStarted, format, left, bottom, audio, onShutter]
13:42:53.473: [info] 📸 VisionCamera.configurePreviewOrientation(_:): Updating Preview rotation: portrait...
13:42:53.473: [info] 📸 VisionCamera.configureOutputOrientation(_:): Updating Outputs rotation: portrait...
13:42:53.473: [info] 📸 VisionCamera.configure(_:): configure { ... }: Waiting for lock...
13:42:53.476: [info] 📸 VisionCamera.configure(_:): configure { ... }: Updating CameraSession Configuration... Difference(inputChanged: true, outputsChanged: true, videoStabilizationChanged: true, orientationChanged: true, formatChanged: true, sidePropsChanged: true, torchChanged: true, zoomChanged: true, exposureChanged: true, audioSessionChanged: true, locationChanged: true)
13:42:53.476: [info] 📸 VisionCamera.configureDevice(configuration:): Configuring Input Device...
13:42:53.476: [info] 📸 VisionCamera.configureDevice(configuration:): Configuring Camera com.apple.avfoundation.avcapturedevice.built-in_video:1...
13:42:53.482: [info] 📸 VisionCamera.configureDevice(configuration:): Successfully configured Input Device!
13:42:53.482: [info] 📸 VisionCamera.configureOutputs(configuration:): Configuring Outputs...
13:42:53.482: [info] 📸 VisionCamera.configureOutputs(configuration:): Adding Video Data output...
13:42:53.483: [info] 📸 VisionCamera.configurePreviewOrientation(_:): Updating Preview rotation: portrait...
13:42:53.483: [info] 📸 VisionCamera.configureOutputOrientation(_:): Updating Outputs rotation: portrait...
13:42:53.483: [info] 📸 VisionCamera.configureOutputs(configuration:): Successfully configured all outputs!
13:42:53.484: [info] 📸 VisionCamera.setTargetOutputOrientation(_:): Setting target output orientation from device to device...
13:42:53.484: [info] 📸 VisionCamera.configureFormat(configuration:device:): Configuring Format (3840x2160 | [email protected] (ISO: 19.0..1824.0))...
13:42:53.485: [info] 📸 VisionCamera.configureFormat(configuration:device:): Successfully configured Format!
13:42:53.486: [info] 📸 VisionCamera.getPixelFormat(for:): Available Pixel Formats: ["420v", "420f", "BGRA"], finding best match... (pixelFormat="yuv", enableHdr={false}, enableBufferCompression={true})
13:42:53.486: [info] 📸 VisionCamera.getPixelFormat(for:): Using PixelFormat: 420f...
13:42:53.647: [info] 📸 VisionCamera.init(frame:session:): Preview Layer started previewing.
13:42:53.648: [info] 📸 VisionCamera.configure(_:): Beginning AudioSession configuration...
13:42:53.648: [info] 📸 VisionCamera.configureAudioSession(configuration:): Configuring Audio Session...
13:42:53.648: [info] 📸 VisionCamera.configure(_:): Beginning Location Output configuration...
13:42:53.648: [info] 📸 VisionCamera.configureAudioSession(configuration:): Adding Audio input...
13:42:53.652: [info] 📸 VisionCamera.configureAudioSession(configuration:): Adding Audio Data output...
13:42:53.652: [info] 📸 VisionCamera.configure(_:): Finished Location Output configuration!
13:42:53.654: [info] 📸 VisionCamera.configure(_:): Committed AudioSession configuration!
Camera Device
Front formate {
"formats": [],
"minFocusDistance": 0,
"sensorOrientation": "portrait",
"maxZoom": 135,
"minZoom": 1,
"hasTorch": false,
"hardwareLevel": "full",
"position": "front",
"maxExposure": 8,
"supportsLowLightBoost": false,
"id": "com.apple.avfoundation.avcapturedevice.built-in_video:1",
"name": "Front Camera",
"minExposure": -8,
"hasFlash": true,
"physicalDevices": [
"wide-angle-camera"
],
"neutralZoom": 1,
"supportsFocus": false,
"supportsRawCapture": false,
"isMultiCam": false
}
back formate {
"formats": [],
"position": "back",
"minFocusDistance": 10,
"hardwareLevel": "full",
"hasTorch": true,
"isMultiCam": false,
"supportsLowLightBoost": false,
"maxExposure": 8,
"supportsFocus": true,
"supportsRawCapture": false,
"neutralZoom": 1,
"physicalDevices": [
"wide-angle-camera"
],
"name": "Back Camera",
"minExposure": -8,
"hasFlash": true,
"maxZoom": 16,
"id": "com.apple.avfoundation.avcapturedevice.built-in_video:0",
"sensorOrientation": "portrait",
"minZoom": 1
}
Device
iPhoneX OS 16.7.10
VisionCamera Version
4.5.3
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
- [X] I am using Expo
- [X] I have enabled Frame Processors (react-native-worklets-core)
- [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.
Guten Tag, Hans here! 🍻 Thanks for reporting zis issue. It looks like you might be encountering an unexpected behavior with video orientation in portrait mode.
Can you please verify if you have tried reproducing zis issue in ze VisionCamera Example app? It's important to ensure zis problem persists outside of your setup. Also, if possible, please provide any additional logs from Xcode or adb logcat when zis issue occurs. Zis will help mrousavy a lot in diagnosing ze problem.
If you're unsure how to gather logs, for iOS you can find them in ze Xcode console. For Android, use adb logcat in your terminal.
Once you have more information, we can work towards resolving zis. Danke!
Note: If you think I made a mistake, please ping
@mrousavyto take a look.
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)
Please try if you can reproduce here.
I was able to reproduce this with the front camera in the example app by adding isMirrored={false} to the Camera. It only seems to happen with video output on iOS. Photo output is correctly flipped around the vertical axis. Android works fine with both video and photo.
Edit: Tested with version 4.5.3
Same here, for android is working good, but for iOS with isMirrored={false} we are getting this error.
I am seeing this error as well. If isMirrored={false}, the resulting video is mirrored horizontally instead of vertically (the output video is upside down). However, I am also finding that video mirroring with the front camera on iOS isn't working.
In other words, if I record a video with the front camera, without using this isMirrored prop at all, the resulting output video does not get flipped like it should (like the default iOS camera would do). If I record a video, and hold up my right hand, it looks like my left hand in the preview, but then when I watch the output, it still looks like my left hand. If I do the same with the iOS built-in camera, the output properly looks like my right hand.
The code is below:
const device = useCameraDevice('front');
<Camera
ref={cameraRef}
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
video={true}
audio={true}
onInitialized={() => {
onCameraReady();
}}
onError={(error) => console.error(error)}
/>
@colaquecez @davetodd Am I missing something obvious here or is the front camera not working properly on iOS?
is this happening only in IOS version 16 or below 16 i saw the same issue in iphone x and in 7 but working fine in 13,14 device.
@flyingL123 per this comment I think the default behavior is intentional -- unlike the default iOS camera's output, react-native-vision-camera's output is mirrored. So the bug is that isMirrored={false} should disable this, and instead it flips the output upside down.
@davetodd ok got it. That makes sense. My built-in camera has the mirroring setting disabled, so if I'm trying to have react-native-vision-camera mimic that behavior, I should pass isMirrored={false}. I can confirm when I do that, the output video is upside down.
I am on iPhone XR - iOS v17.6.1
@mrousavy any idea what's causing this?
I also need a fix for this, mirroring on IOS is turning the video upside down instead of vertical mirroring as the documentations says it should. Any update?
I am also seeing this issue on IOS. Currently having to add a workaround to rotate the videos that are upside down.
Same for me on latest version for iOS. Happens with front camera, portrait, and camera placed on top. Not happening when in landscape with camera on the left. (isMirroredFlag set as false)
Hey @juliajungle, can you share the workaround, I'm still having the issue on iOS (all versions)
Hey @MatteoGauthier I was also working with ffmpeg to do some processing stuff on the videos so I had the copy function include a rotation. I can grab the exact command if you need it.
@juliajungle Thanks for your reply! However, ffmpeg feels a bit heavy for my needs. I'm hoping to find something more lightweight. Let me know if you know of any alternatives!
Does someone find a workaround .patch file ?
@MatteoGauthier
Does someone find a workaround .patch file ?
I managed to fix this with a small patch file! I'm using [email protected].
When I have time, I may revise this change into a more proper PR, but I'm more than happy if somebody else does that. This change is generated by Claude Code, I'm not sure if this is a good change from the architecturual perspective :)
diff --git a/node_modules/react-native-vision-camera/ios/Core/CameraSession+Video.swift b/node_modules/react-native-vision-camera/ios/Core/CameraSession+Video.swift
index 8e57710..4253f99 100644
--- a/node_modules/react-native-vision-camera/ios/Core/CameraSession+Video.swift
+++ b/node_modules/react-native-vision-camera/ios/Core/CameraSession+Video.swift
@@ -89,7 +89,16 @@ extension CameraSession {
do {
// Orientation is relative to our current output orientation
- let orientation = self.outputOrientation.relativeTo(orientation: videoOutput.orientation)
+ var orientation = self.outputOrientation.relativeTo(orientation: videoOutput.orientation)
+
+ // Fix front camera portrait recording orientation when mirroring is disabled
+ if let videoDeviceInput = self.videoDeviceInput,
+ videoDeviceInput.device.position == .front,
+ let config = self.configuration,
+ !config.isMirrored,
+ self.outputOrientation.isPortrait {
+ orientation = orientation.flipped()
+ }
// Create RecordingSession for the temp file
let recordingSession = try RecordingSession(url: options.path,