react-native-vision-camera icon indicating copy to clipboard operation
react-native-vision-camera copied to clipboard

🐛 Potrait mode video is flipped to wrong direction

Open sw-tt-hitendrachavda opened this issue 1 year ago • 15 comments

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. IMG_2013

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

sw-tt-hitendrachavda avatar Sep 19 '24 08:09 sw-tt-hitendrachavda

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 @mrousavy to take a look.

maintenance-hans[bot] avatar Sep 19 '24 08:09 maintenance-hans[bot]

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.

mrousavy avatar Oct 10 '24 14:10 mrousavy

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

davetodd avatar Oct 17 '24 14:10 davetodd

Same here, for android is working good, but for iOS with isMirrored={false} we are getting this error.

colaquecez avatar Oct 17 '24 17:10 colaquecez

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?

flyingL123 avatar Oct 28 '24 23:10 flyingL123

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.

paragbarsar99 avatar Oct 29 '24 04:10 paragbarsar99

@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 avatar Oct 29 '24 12:10 davetodd

@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?

flyingL123 avatar Oct 29 '24 13:10 flyingL123

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?

PatriciaRomaniuc avatar Nov 18 '24 10:11 PatriciaRomaniuc

I am also seeing this issue on IOS. Currently having to add a workaround to rotate the videos that are upside down.

juliajungle avatar Nov 20 '24 16:11 juliajungle

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)

angelos3lex avatar Jan 17 '25 11:01 angelos3lex

Hey @juliajungle, can you share the workaround, I'm still having the issue on iOS (all versions)

MatteoGauthier avatar Jun 19 '25 09:06 MatteoGauthier

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 avatar Jun 19 '25 13:06 juliajungle

@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 avatar Jun 20 '25 07:06 MatteoGauthier

@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,

Sidebook avatar Aug 31 '25 04:08 Sidebook