Skip to content

fix: Encode with a compressed codec when targetBitRate is set on iOS - #4222

Open
don4325 wants to merge 1 commit into
margelo:mainfrom
don4325:fix/ios-compressed-codec-under-target-bitrate
Open

don4325 wants to merge 1 commit into
margelo:mainfrom
don4325:fix/ios-compressed-codec-under-target-bitrate

Conversation

@don4325

@don4325 don4325 commented Oct 16, 2026 •

Copy link
Copy Markdown

Problem

HybridCameraVideoOutput.setBitRate(bitRate:for:) reads the connection's current codec from
output.outputSettings(for:) and applies the bit-rate to that codec. On a format whose default
movie codec is ProRes (the 10-bit 4:2:2 formats of the Pro iPhones) the connection reports
ProRes and supportedOutputSettingsKeys(for:) does not include AVVideoCompressionPropertiesKey,
so the guard in setOutputSettings(bitRate:codec:for:) logs an error and returns. The
targetBitRate the caller asked for is dropped silently and the recorder keeps writing ProRes.

Observed on an iPhone 17 Pro Max (iOS 27.0.1): the rear camera negotiated a 10-bit 4:2:2 format,
and a recording with targetBitRate set wrote 33.1 MB in 1.03 s (about 257 Mbps) until
maxFileSize stopped the take. The only log line was the "cannot use custom bit-rate" error.

Fix

  • compressedCodec(preferring:): an HEVC/H.264 allow-list. Keep the current codec when it is one
    of those and the output offers it; otherwise pick the first of HEVC, H.264 that
    availableVideoCodecTypes contains; return nil when neither is offered, in which case
    setBitRate logs and leaves the connection untouched (setting a codec the output does not offer
    raises). An allow-list rather than a ProRes deny-list because any other codec (JPEG, or one the
    converter does not know) would drop the bit-rate the same way.
  • setOutputSettings(bitRate:codec:for:) now applies the codec on its own before reading
    supportedOutputSettingsKeys(for:), because the supported keys are reported for the
    connection's current codec, and a ProRes connection does not list compression properties
    until it has been moved to a compressed one.

A targetBitRate is a request for a compressed codec, so this does not change behaviour for
the common H.264/HEVC formats: there the current codec is already compressed and is kept.

Verification

  • swift format --configuration config/.swift-format on the file produces no diff.
  • The resulting file is byte-identical to the one we carry as a pnpm patch on
    react-native-vision-camera@5.2.3. That patch is in review and has not yet reached a device;
    the production evidence above is of the defect, not of the fix.
  • No Xcode build was run while preparing this branch.

Limits

  • The explicit setOutputSettings(settings:) path (user-chosen codec) is untouched; if a user
    explicitly selects ProRes and also sets targetBitRate, the bit-rate call will move the
    codec to HEVC. Happy to gate on "codec was not explicitly selected" if you prefer.
  • Not exercised on a device while preparing this branch beyond the production evidence above.

馃 Generated with Claude Code

@vercel

vercel Bot commented Oct 16, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

`HybridCameraVideoOutput.setBitRate` read the connection's current codec
and applied the bit-rate to it. On formats whose default movie codec is
ProRes (the 10-bit 4:2:2 formats of Pro iPhones) the connection does not
list `AVVideoCompressionPropertiesKey`, so the guard bailed, the
bit-rate was dropped silently and the recorder kept writing ProRes.
Observed on an iPhone 17 Pro Max (iOS 27.0.1): the rear camera wrote
33.1 MB in 1.03 s (~257 Mbps) until `maxFileSize` stopped the take.

Resolve the codec first: keep the current codec when it is already a
compressed one the output offers, otherwise move to HEVC, else H.264.
Apply that codec on its own before reading `supportedOutputSettingsKeys`,
because the supported keys are reported for the connection's current
codec.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@don4325
don4325 force-pushed the fix/ios-compressed-codec-under-target-bitrate branch from a787e1b to 98b510d Compare October 16, 2026 19:37

This branch has not been deployed

No deployments
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.

1 participant