Skip to content

feat(android): add high-speed video recording mode#3803

Open
Aniketiitk21 wants to merge 1 commit intomrousavy:mainfrom
Aniketiitk21:video-recording-mode-high-speed
Open

feat(android): add high-speed video recording mode#3803
Aniketiitk21 wants to merge 1 commit intomrousavy:mainfrom
Aniketiitk21:video-recording-mode-high-speed

Conversation

@Aniketiitk21
Copy link
Copy Markdown

Summary

  • add a new { videoRecordingMode: 'high-speed' | 'slow-motion' } constraint for Android video sessions
  • expose the negotiated result as selectedVideoRecordingMode on CameraSessionConfig
  • build CameraX HighSpeedVideoSessionConfig sessions when the requested outputs are compatible
  • automatically choose the lowest supported high-speed FPS when no explicit { fps: ... } constraint is provided
  • gracefully fall back to regular video recording when a high-speed session cannot be created
  • document the new high-speed/slow-motion flow in the Constraints and FPS docs
  • regenerate the Nitro bridge/types for the new API surface

Why

Issue #3688 asks for a way to use Android high-speed recording from VisionCamera.

Today, developers can request higher FPS values, but there is no direct way to tell the session resolver that the recording itself should be negotiated as a high-speed or slow-motion session. That makes the behavior harder to reason about and leaves some devices unable to enter their dedicated high-speed capture path even when CameraX supports it.

This change adds an explicit recording-mode constraint so apps can opt into that capability in a predictable way.

Implementation

  • add a new public VideoRecordingMode type with 'high-speed' | 'slow-motion'
  • add VideoRecordingModeConstraint to the constraint system
  • plumb the resolved mode through CameraSessionConfig as selectedVideoRecordingMode
  • on Android, teach ConstraintResolver to:
    • request a HighSpeedVideoSessionConfig
    • keep the session limited to supported output combinations
    • derive a valid high-speed FPS automatically when only the recording mode is specified
    • mark slow-motion sessions via CameraX when requested
    • downgrade cleanly if the device or output graph cannot satisfy the request
  • skip VideoCapture mirror-mode configuration in high-speed sessions because CameraX does not allow it there
  • on iOS, keep the new API shape available so the bridge stays consistent, while leaving behavior unchanged for now
  • update docs to explain when to use videoRecordingMode, how it interacts with fps, and what fallback behavior to expect

Behavior

  • { videoRecordingMode: 'high-speed' } requests a high-speed recording session
  • { videoRecordingMode: 'slow-motion' } requests a high-speed session that is flagged for slow-motion capture
  • if fps is omitted, the resolver selects the lowest supported high-speed FPS for the chosen format/device
  • if the requested session is not supported, VisionCamera falls back to a regular recording session instead of failing hard
  • the final negotiated mode is exposed through selectedVideoRecordingMode

Testing

  • npm run typecheck
  • tsc --noEmit false && nitrogen
  • .\gradlew.bat :react-native-vision-camera:compileDebugKotlin --no-daemon --console=plain

Notes

  • this change is implemented for Android
  • iOS keeps the API surface in sync but does not add high-speed session behavior yet

Closes #3688

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

@Aniketiitk21 is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Owner

@mrousavy mrousavy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your PR, but I am unfortunately not a big fan of this prop at all.
Two reasons:

  1. I think the concept of High Speed Recording sessions should not be exposed to the user - it is an implementation detail imo - just like how iOS does it. We can abstract this away in VisionCamera too
  2. High Speed Recording Video Sessions currently have way too many limitations for them to be a seriously first-class supported feature imo. They dont support Camera Extensions, no Mirror Mode, and afaik no ImageAnalysis (Frame Processor) or ImageCapture (photos). That's basically crippling the Camera

I think overall this is something I don't yet want in VisionCamera - maybe soon if High Speed Capture Sessions are becoming a bit more powerful in CameraX, but for now this is too limiting.

Comment on lines +100 to +103
if (config.videoRecordingMode == null) {
// High-speed sessions cannot set mirror mode on VideoCapture.
setMirrorMode(mirrorMode.toMirrorMode())
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Limitations like these are super weird, and I personally would love to completely avoid that unsafe code.
It's possible by API design to write code that crashes here, and I don't understand why a High Speed Video Session doesn't support mirror mode tbh.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The guard is only there because CameraX crashes when mirror mode is set on a high-speed VideoCapture, which is itself a sign that this is too leaky for a public first-class API.

},
{ true }, // PixelFormat: let downgrade loop handle it
{ true }, // Binning: not configurable in CameraX
{ Recorder.getHighSpeedVideoCapabilities(cameraInfo) != null },
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not very explicit - I would probably add an extension (or a var above) like isHighSpeedVideoRecordingSupported instead of comparing for null

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. If this direction were to continue, I would rename that for clarity. But after your broader feedback, I think the bigger fix is to avoid surfacing this mode directly in the public API at all.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that makes sense

let r = binned.resolve(for: format)
return ConstraintEvaluation(penalty: r.penalty, resolved: .formatOnly)
case .ninth( /* videoRecordingMode */ _):
// High-speed session orchestration is currently Android-only.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not currently; it is an Android only concept. iOS doesnt care about high speed or "normal" - everything is normal. You can just record higher FPS. Just like a Camera library should work, not two completely separate concepts just because FPS go higher.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, agreed. I only threaded it through iOS to keep the bridge shape compiling consistently, not because I think iOS should expose a separate “high-speed vs normal” concept.

*
* @platform Android
*/
export interface VideoRecordingModeConstraint {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm

@Aniketiitk21
Copy link
Copy Markdown
Author

Thank you for your PR, but I am unfortunately not a big fan of this prop at all. Two reasons:

  1. I think the concept of High Speed Recording sessions should not be exposed to the user - it is an implementation detail imo - just like how iOS does it. We can abstract this away in VisionCamera too
  2. High Speed Recording Video Sessions currently have way too many limitations for them to be a seriously first-class supported feature imo. They dont support Camera Extensions, no Mirror Mode, and afaik no ImageAnalysis (Frame Processor) or ImageCapture (photos). That's basically crippling the Camera

I think overall this is something I don't yet want in VisionCamera - maybe soon if High Speed Capture Sessions are becoming a bit more powerful in CameraX, but for now this is too limiting.

Thanks, that makes sense.

I agree with your higher-level concern here: videoRecordingMode leaks a CameraX-specific session detail into the public API, and that is probably the wrong abstraction for VisionCamera. I took this route because CameraX requires a distinct HighSpeedVideoSessionConfig, but I agree that this should stay an internal implementation detail if we support it at all.

I also agree that the current limitations are too heavy for something that would look like a first-class feature: no mirror mode, no camera extensions, and restricted output combinations make it much harder to present this cleanly in the library surface.

So I’m aligned with not pushing this prop-based version further. The better long-term direction seems to be keeping the public API centered on fps, and internally opting into Android high-speed sessions only when the requested FPS and output graph require it and the combination is actually supported.

Happy to leave this PR as-is for reference or close it and revisit later with that abstraction instead.

@mrousavy
Copy link
Copy Markdown
Owner

Yea that makes sense.

Thanks for your insights. I think it's best if we leave this PR open for future reference (not only code, but also the discussion around it), and in the future when CameraX has better support for high speed capture sessions we can abstract this more nicely and blend high speed with normal capture sessions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Implement High-speed and Slow-motion Recording on Android

2 participants