- Accumulate stderr in FFmpegRecorder during recording
- Log last 2000 chars of stderr when ffmpeg exits non-zero
- Log ffmpeg input URL and args at start
- RecordingError.processFailed now includes optional stderr string
- Error message shows ffmpeg error details to user
proc.waitUntilExit() blocks cooperative thread pool threads and
deadlocks in Swift Concurrency Task context because NSRunLoop
notifications aren't processed. Replace with terminationHandler +
withCheckedContinuation pattern.
-movflags +faststart requires ffmpeg to write moov atom at the end,
which fails when SIGINT interrupts a live HLS recording — the mp4
file has no moov atom and is unplayable (0 bytes effective).
Switch to -movflags +frag_keyframe+empty_moov+default_base_moof
(fragmented MP4): moov atom written immediately at file start,
each segment is self-contained. Even if ffmpeg is killed mid-recording,
the file remains fully playable with both video and audio intact.
Verified: HLS live stream (CBS News) → 45s 1280x720 h264 + AAC 48kHz,
13MB, SIGINT-safe. Local files unaffected.
-c copy may produce mp4 files with AC3/DTS/FLAC audio that macOS
AVPlayer cannot decode, resulting in silent playback.
Change to -c:v copy -c:a aac -b:a 192k to preserve video quality
while ensuring universally playable audio.