Skip to content

fix(ios): return frame-count duration from IOSFileWriter::closeFile - #1320

Merged
mdydek merged 2 commits into
software-mansion:mainfrom
wildseansy:fix/ios-close-file-frame-count-duration
Sep 25, 2026
Merged

mdydek merged 2 commits into
software-mansion:mainfrom
wildseansy:fix/ios-close-file-frame-count-duration

Conversation

@wildseansy

@wildseansy wildseansy commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Closes # — no existing issue tracks this.

⚠️ Breaking changes ⚠️

Introduced changes

  • IOSFileWriter::closeFile() returned AVURLAsset.duration for the file it had just closed. For containerless streams such as raw AAC in ADTS framing (feat: add ADTS AAC file format for crash-recoverable compressed recording #1319) AVFoundation has no stored duration and estimates size ÷ bitrate of the first packets. With VBR AAC and a quiet opening that estimate runs 20–70 % long: 30 s recordings were reported as 38, 44, 41 and 39 s.
  • closeFile() now returns getCurrentDuration() (frames written ÷ file sample rate), read after offloader_.reset() has drained every queued buffer so the count is final. This matches what the recorder already reports mid-recording and what the Android writer returns at stop, and removes an AVFoundation asset open from the stop path.
  • Other paths checked: pause/resume writes nothing while paused, so file and count agree; an input-format change keeps framesWritten_ and counts at the file sample rate on the converter path; dropped buffers are skipped in both the file and the count; IOSRotatingFileWriter sums per-segment closeFile() durations and each segment has its own counter.

Checklist

  • Linked relevant issue — none exists
  • Updated relevant documentation — N/A, FileInfo.duration semantics are unchanged
  • Added/Conducted relevant tests — manual, see below; iOS Objective-C++ has no unit harness in the repo (gtests cover common C++)
  • Performed self-review of the code
  • Updated Web Audio API coverage — N/A
  • Added support for web — N/A, iOS-only writer
  • Updated old arch android spec file — N/A

Verification

  • Synthetic quiet-then-loud ADTS file, real length 25.0 s: the AVURLAsset estimate reports 37.6 s, the frame count reports 25.0 s.
  • iOS simulator, ADTS recordings auto-stopped at 30 s of audio (1300–1334 AAC frames ≈ 30.2–31.0 s): before this change stop() reported 38, 44, 41, 39 and 31 s.
  • iOS simulator with this change: record → pause → resume → stop reports a duration that excludes the paused time and matches ffprobe -count_packets × 1024 ÷ 44100 within 1 s.
  • Note: a decoded raw ADTS file plays ~50 ms longer than the frame count because of AAC priming and last-packet padding; the frame count is the content length.
  • clang-format 23 and commitlint (config-conventional) clean.

🤖 Generated with Claude Code

closeFile() asked AVURLAsset for the duration of the file it had just
closed. For containerless streams such as raw AAC (ADTS) AVFoundation has
no duration to read and estimates size / early bitrate; with VBR AAC and
a quiet opening that estimate runs 20-70% long. Return
getCurrentDuration() (frames written / file sample rate) instead, read
after the offloader has drained every queued buffer. This matches what
the recorder already reports mid-recording and what Android returns at
stop, and removes an AVFoundation asset open from the stop path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

WPT non-regression comparison

PASS — no regressions · 0 improved section(s) · overall 2717 → 2717 (0)

Unchanged sections (28)
Spec section Base pass Head pass Delta
Processing model 0 0 0
Other 52 52 0
AnalyserNode 138 138 0
AudioBuffer 140 140 0
AudioBufferSourceNode 218 218 0
AudioContext 58 58 0
AudioNode 261 261 0
AudioParam 629 629 0
BiquadFilterNode 275 275 0
ChannelMergerNode 30 30 0
ChannelSplitterNode 7 7 0
ConstantSourceNode 64 64 0
ConvolverNode 203 203 0
DelayNode 104 104 0
DestinationNode 0 0 0
DynamicsCompressorNode 4 4 0
GainNode 15 15 0
IIRFilterNode 87 87 0
MediaElementAudioSourceNode 0 0 0
MediaStreamAudioDestinationNode 1 1 0
MediaStreamAudioSourceNode 0 0 0
OfflineAudioContext 35 35 0
OscillatorNode 104 104 0
PannerNode 75 75 0
PeriodicWave 33 33 0
ScriptProcessorNode 0 0 0
StereoPannerNode 102 102 0
WaveShaperNode 82 82 0

Baseline: 0494fdc08c00b4cea1927d3b66df8b2c6416760a · Candidate: 03b9ec8b751cd387c47521625d60d620ec5d32ff

Workflow run · this comment is updated on every push.

@mdydek
mdydek merged commit 015e937 into software-mansion:main Sep 25, 2026
1 check passed
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.

3 participants