Skip to content

Fix the CI-only AVFoundation crash in audio extraction - #6

Closed
maxthegray wants to merge 2 commits into
mainfrom
fix/audio-extraction-ci
Closed

Fix the CI-only AVFoundation crash in audio extraction#6
maxthegray wants to merge 2 commits into
mainfrom
fix/audio-extraction-ci

Conversation

@maxthegray

Copy link
Copy Markdown
Owner

Diagnosis

swift test has taken SIGSEGV in testExtractAudioWritesM4AWithoutChangingSource on every macos-15 run since audio extraction landed. Key evidence:

  • eb906ae failed with the same signal 11 in the same test — one commit before 272936c. Both the old exportAsynchronously path and the newer export(to:as:) path crash identically, so 272936c is not the cause and stays.
  • Not a fixture problem: WAV and QuickTime both crash, and the original WAV fixture is valid (the old path produces a correct 1.0s m4a locally).
  • Not a race: TSan and ASan are clean, and the CI failure is deterministic.

What is left is AVAssetExportSession with AVAssetExportPresetAppleM4A. The preset always re-encodes, and the runner is a headless Apple Silicon VM that logs a failed media IOService match. It faults instead of returning an error.

Fix

Replace the export session with an AVAssetReader/AVAssetWriter copy. Audio that is already AAC is passed straight through into the .m4a container — lossless, faster, and no codec is instantiated at all. Other formats are decoded to PCM and re-encoded.

This also removes the back-deployed export(to:as:) shim, which on macOS 15–25 ran inside Perch's own binary and does throw self.error! plus fatalError on any non-terminal status. With a macOS 14 deployment target that could trap the process for a large share of users on a failed export.

The test now uses a committed 4.8 KB AAC movie instead of building one at run time, and asserts the extracted duration so a truncated copy cannot pass.

Verification

  • Focused test: passed
  • swift test: 270 tests, 0 failures
  • swift build -c release: clean
  • TSan / ASan: clean

AVAssetExportSession's AppleM4A preset is what CI dies on: swift test has
taken SIGSEGV in testExtractAudioWritesM4AWithoutChangingSource on every
macos-15 run since audio extraction landed, under both the old
exportAsynchronously path and the newer export(to:as:) one, and with both
the WAV and the QuickTime fixture. The preset always re-encodes, and on a
headless runner that cannot supply its media services it faults rather
than returning an error.

Replace it with an AVAssetReader/AVAssetWriter copy. Audio that is already
AAC is passed straight through into the .m4a container, so extraction is
lossless, faster, and instantiates no codec at all; other formats are
decoded to PCM and re-encoded. This also drops the deprecated
status/error/exportAsynchronously surface and, with it, the back-deployed
export(to:as:) shim that force-unwraps error and calls fatalError on any
non-terminal status.

Feed the test a committed 4.8 KB AAC movie instead of building one at run
time, so it no longer depends on the host having a working encoder, and
assert the extracted duration so a truncated copy cannot pass.
@maxthegray

Copy link
Copy Markdown
Owner Author

Superseded — the fix is on beta instead.

@maxthegray maxthegray closed this Aug 12, 2026
@maxthegray
maxthegray deleted the fix/audio-extraction-ci branch August 12, 2026 03:49
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