margelo / margelo/react-native-vision-camera
iOS: video output `outputOrientation` reports the set value, not connection state; `currentResolution` returns undefined
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 9.6k
- Forks
- 1.4k
- Avg merge
- 1d 28m
- Merged PRs (30d)
- 4
Description
What's happening?
On iOS, CameraVideoOutput.outputOrientation reports the value that was last set, not the connection's actual orientation — so it cannot be used to find out how a recording was oriented. Separately, CameraVideoOutput.currentResolution returns undefined for me even while the session is running.
1. outputOrientation is effectively write-only on a video output
ios/Hybrid Objects/Outputs/HybridCameraVideoOutput.swift:
var outputOrientation: CameraOrientation = .up {
didSet {
guard let connection = output.connection(with: .video) else { return }
try? connection.setOrientation(outputOrientation)
}
}
It is a stored property whose didSet writes to the connection. Reading it returns the stored value, never the connection state.
The preview output does implement the getter properly, which is what makes this look like an oversight rather than a deliberate choice — HybridCameraPreviewOutput.swift:
var outputOrientation: CameraOrientation {
get { return previewLayer.connection?.orientation ?? .up }
set { /* ... */ }
}
AVCaptureConnection.orientation already exists in this repo (AVCaptureConnection+orientation.swift), so the video output could use the same accessor.
I want to be precise about what this would and would not fix: since configure(config:) already calls connection.setOrientation(outputOrientation) with the default .up, a corrected getter would return .up — the connection genuinely is .portrait. It would make the getter honest, but it still would not tell a caller how the resulting file is oriented, which is what I was actually after (see below).
2. currentResolution returns undefined
var currentResolution: Size? {
guard let connection = output.connection(with: .video) else { return nil }
return connection.inputStreamResolution
}
I read it both immediately after await session.start() and again at stop time; it was undefined both times, on a running session that was recording successfully. configure(config:) uses the same output.connection(with: .video) lookup and clearly succeeds, since orientation and mirroring are applied — so I have not been able to work out the cause and am reporting it as an observation rather than a diagnosis.
This matters because it is the only way to detect a resolution substitution. Requesting targetResolution: 3024x4224 with a { fps: 120 } constraint was accepted, and the session recorded 3840x2160 instead. Without currentResolution there is no way to learn that from the API.
Context: what I was trying to do
Report the true rotation and dimensions of a finished recording. Rotation turns out to be format-dependent — the same portrait-locked app produced:
| Camera | Config | Stored | Rotation | Presents |
|---|---|---|---|---|
| front | 1080x1920 @ 30fps | 1080x1920 | none | portrait |
| rear | 4K @ 120fps | 3840x2160 | -90 | portrait |
Both present portrait, but only one carries a transform, so no single assumption is correct and no connection-level read reports it. I ended up deriving rotation server-side with ffprobe instead, which works fine — but a recorder-level "what did the finished file actually get" (resolution + rotation) would remove the need.
Environment
react-native-vision-camera5.2.2react-native-nitro-modules0.36.5react-native0.81.5, New Architecture, bridgeless- Expo SDK 54 (
expo54.0.36), dev client - Xcode 26.6, iOS 27.0, iPhone 17 Pro Max (physical device)
Ground truth in the table above is ffprobe on the files pulled off the device.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ios/Hybrid Objects/Outputs/HybridCameraVideoOutput.swift and compare its outputOrientation accessor with HybridCameraPreviewOutput.swift and AVCaptureConnection+orientation.swift. Reproduce currentResolution during a running and stopped session, then trace the connection used by configure(config:). Done means the orientation getter reflects connection state and the resolution behavior is either corrected or clearly scoped, with the reported recording cases accounted for.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, react-native, swift
- Domain
- mobile, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100