- Android non-AAC audio is now transcoded to AAC (matching iOS) via a
source-decoder -> AAC-encoder pre-pass that captures the encoder's
output format before the muxer starts, then writes buffered samples
after the video pipeline finishes. Falls back to dropping audio if
the transcode fails.
- compress.ts wraps probe() in try/catch and falls through to
passthrough on failure instead of throwing.
- Probers expose isHDR (HLG/PQ via color transfer, plus Dolby Vision
codecs/mimes); shouldCompress forces compression for HDR sources so
the SDR BT.709 path always runs. Also sets
KEY_COLOR_TRANSFER_REQUEST=SDR on the Android decoder (API 31+) so
HDR sources tone-map to SDR pixels instead of being mislabeled.
Replaces react-native-compressor's video path with a local Expo module.
Native pipeline:
- iOS: AVAssetReader + AVMutableVideoComposition + AVAssetWriter with
VideoToolbox encode, BGRA reader for HDR -> SDR conversion, BT.709
color tagging, DataRateLimits hard cap, AAC re-encode.
- Android: MediaExtractor -> MediaCodec(decoder) -> GL pipeline ->
MediaCodec(encoder) -> MediaMuxer. BITRATE_MODE_CBR for tight target
enforcement, GL transform-matrix rotation (no double-rotation),
raw AAC passthrough, hardware encoder selection with software
fallback, QTI AVC denylist.
Codec selection: 'auto' resolves to h264 (HLS pipeline + licensing).
HEVC remains opt-in via codec: 'hevc' for future feature-flagged use.
compress.ts adds probe-based smart-skip: clips that are already at or
below 5 Mbps / 1920px / 100MB bypass re-encoding entirely.
react-native-compressor stays as a dep for now since pickVideo and
VideoTranscodeBackdrop still use its non-compression helpers; full
removal is a follow-up.