feat: add ADTS AAC file format for crash-recoverable compressed recording - #1319
Open
wildseansy wants to merge 1 commit into
Open
wildseansy wants to merge 1 commit into
wildseansy wants to merge 1 commit into
Conversation
…ding
Adds FileFormat.Adts as a recorder output option. ADTS frames are
self-delimiting (each carries a sync word and a frame-length header), so
a recording interrupted by a crash or force-kill stays decodable up to
the last complete frame - the same recoverability FLAC offers today, at
lossy-AAC file sizes (~10x smaller) and with no post-processing
transcode.
iOS: maps ADTS to kAudioFormatMPEG4AAC with an .aac extension; the
existing AAC bitrate settings path applies unchanged.
Android: the FFmpeg writer produces ADTS without a muxer. The prebuilt
FFmpeg from software-mansion-labs/rn-audio-libs is configured with
--enable-muxer=wav,mp4,flac,caf (no adts), so
avformat_alloc_output_context2("adts") would fail at record start.
ADTS does not need one: for each encoded AAC packet the writer builds
the 7-byte ADTS header by hand (syncword 0xFFF, MPEG-4, AAC-LC profile,
sample-rate index from the encoder rate, channel configuration, 13-bit
frame length = 7 + packet size, buffer fullness 0x7FF) and writes header
plus raw packet straight to an AVIOContext opened with avio_open. The
encoder, resampler and FIFO paths are unchanged; the periodic avio_flush
is retained on the ADTS AVIOContext so crash durability is the same as
the container path. No trailer is written - an ADTS stream is complete
after its last frame. rollbackFailedOpen() closes the ADTS AVIOContext
and clears the flag, and finalizeOutput() derives the ADTS duration from
nextPts_ / encoder sample rate like the container path.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 of 7 tasks
Member
|
currently in #1183 we are deleting ffmpeg support when it comes to encoding in favor of OS apis, but it looks like ADTS AAC format will be easy to onboard there. Leaving for now to not forget about it, but we will not proceed with this implementation at this time |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes # — no existing issue tracks this. The format has been in production use through a fork of this library (the Tonic music-lesson recorder); design notes are below, and I am happy to move them into a discussion or feature request first if you prefer that flow.
FileFormat.Adts = 4is appended; existing values, defaults and behaviour are unchanged.Introduced changes
FileFormat.Adtsrecorder output: raw AAC-LC frames in ADTS framing,.aacextension. Every frame carries its own sync word and length header, so a recording cut off by a crash or force-kill stays decodable up to the last complete frame — the recoverabilityFlacalready offers, at lossy-AAC file sizes (~10× smaller) and without a post-processing transcode. The existing AAC bitrate/quality properties apply exactly as forM4A.FileOptions.mmmapsADTStokAudioFormatMPEG4AACwith theaacextension. AVFoundation selects the ADTS file type from the extension; the existing AAC settings path is unchanged.FFmpegAudioFileWriterwrites ADTS without a muxer. The prebuilt FFmpeg fromsoftware-mansion-labs/rn-audio-libsis configured with--enable-muxer=wav,mp4,flac,caf(noadts), soavformat_alloc_output_context2("adts")would fail at record start. ADTS does not need a muxer: for every encoded packet the writer emits a hand-built 7-byte header (syncword, MPEG-4, AAC-LC profile, sample-rate index, channel configuration, 13-bit frame length, VBR buffer fullness) followed by the raw packet, through anAVIOContextopened withavio_open. Encoder, resampler and FIFO paths are unchanged; the periodicavio_flushruns on the ADTS context so crash durability matches the container path; no trailer is written (an ADTS stream is complete after its last frame);rollbackFailedOpen()closes the ADTS context;finalizeOutput()derives the duration fromnextPts_as before.openAdtsIO()rejects sample rates with no ADTS frequency index and channel counts outside 1–6 up front, so an unsupported configuration fails at start instead of producing an undecodable file.openFile()now routes every failure in the init chain through a singleor_else→rollbackFailedOpen(), so a late failure cannot leak an openAVIOContextor a partial output file (previously only the pool-allocation failure rolled back).FileFormatenum and the Android/FFmpeg caution ininputs/audio-recorder.mdx; FFmpeg usage table inother/runtime-flags.mdx.Design notes
adtsmuxer? It is not compiled into the prebuilt libraries, and enabling it means a rebuild and re-release ofrn-audio-libs. The ADTS header is 7 bytes of fixed layout, so writing it by hand is a smaller change than the dependency bump and works on today's binaries.FileFormatrather than an option onM4A? The output has a different (absent) container and a different extension, and consumers need to know to expect a raw stream. A distinct enum value keeps that explicit and mirrors howFlacandCafare exposed.concatAudioFiles; that can follow separately if wanted.Checklist
Verification
stop()match the file. A snapshot of the file taken mid-recording is a frame-aligned byte prefix of the final file, confirming the periodic flush keeps a killed recording decodable..aacfiles pulled mid-recording parse with every ADTS header valid.clang-format23,cpplint2.0.2,prettier3.3.3 andcommitlint(config-conventional) clean on the changed files.🤖 Generated with Claude Code