MacWhisper Crash Recovery
When to Use
Use this skill when MacWhisper crashed during a recording and the resulting .m4a files are corrupted (missing moov atom). Symptoms:
- •MacWhisper force-quit or crashed mid-recording
- •
.m4afiles exist but won't play or open - •
ffprobereports "moov atom not found" - •Files have structure:
ftyp(28) + wide(8) + mdat(size=0)
Prerequisites
- •
faad2:brew install faad2 - •
ffmpeg:brew install ffmpeg - •Python 3
Recovery Workflow
Step 1: Locate corrupted files
Check these locations for broken recordings:
- •
~/Desktop/— user may have already copied them - •
/var/folders/— search for.recordkitdirectories containing.m4afiles:bashfind /var/folders -name "*.recordkit" -type d 2>/dev/null
- •Inside
.recordkitdirs, look formicrophone-*.m4aandappaudio-sck-*.m4a
Step 2: Verify files are corrupted
bash
ffprobe <file.m4a> # Should show "moov atom not found"
python3 -c "
d=open('<file.m4a>','rb').read(52)
print('ftyp:', d[4:8])
print('wide:', d[32:36])
print('mdat:', d[40:44])
print('mdat_size:', int.from_bytes(d[36:40],'big'))
"
Corrupted signature: ftyp at 4, wide at 32, mdat at 40, mdat_size=0.
Step 3: Find a reference M4A
A working M4A with the same codec (AAC-LC, 48kHz) is needed for the stsd box:
bash
ls ~/Library/Application\ Support/MacWhisper/Database/ExternalMedia/*.m4a
Pick one _mic-audio_ file as mic reference and one _app-audio_ file as app reference.
Step 4: Run the recovery script
bash
python3 ~/.claude/skills/macwhisper-recover/scripts/recover.py \ --broken <corrupted.m4a> \ --reference <working.m4a> \ --output <recovered.m4a> \ --channels mono|stereo
The script:
- •Compiles the C AAC scanner if needed (
aac_scan.c) - •Extracts raw AAC data from the broken file (offset 44)
- •Scans frame boundaries using faad2
- •Builds a valid moov atom (stsd from reference, computed stsz/stco/stsc/stts)
- •Writes a valid M4A:
ftyp(28) + mdat(8+data) + moov
Step 5: Verify recovery
bash
ffprobe <recovered.m4a> ffmpeg -i <recovered.m4a> -c:a aac -b:a 128k -t 30 /tmp/test_30s.m4a -y
Step 6: Merge tracks (optional)
bash
ffmpeg -i mic_recovered.m4a -i app_recovered.m4a \ -filter_complex amerge=inputs=2 -ac 2 -c:a aac -b:a 256k \ merged.m4a -y
Technical Details
- •Broken structure:
ftyp(28) + wide(8) + mdat(size=0, data to EOF)— data at offset 44 - •Output structure:
ftyp(28) + mdat(correct size, 8+data) + moov— data at offset 36 - •stco offsets: must point to 36 (start of data in output file), NOT 44
- •stsd: copied verbatim from reference file (same codec config)
- •Frame size: each AAC frame = 1024 samples; discovered via faad2
bytesconsumed - •ASC mono mic:
0x11 0x88(AAC-LC, 48kHz, 1ch) - •ASC stereo app:
0x11 0x90(AAC-LC, 48kHz, 2ch) - •Chunks: 46 samples per chunk (matches MacWhisper's default)
- •Movie timescale: 600; audio timescale: 48000