diff --git a/internal/ingest/decoder/fallback/ffmpeg.go b/internal/ingest/decoder/fallback/ffmpeg.go index 6dc4198..27f10ee 100644 --- a/internal/ingest/decoder/fallback/ffmpeg.go +++ b/internal/ingest/decoder/fallback/ffmpeg.go @@ -81,7 +81,16 @@ func (d *FFmpegDecoder) DecodeStream(ctx context.Context, r io.Reader, meta deco } }() - stderrData, _ := io.ReadAll(stderr) + // DEADLOCK FIX: stderr and stdout must be drained concurrently. + // Reading stderr synchronously before readPCM means ffmpeg blocks when + // stdout's pipe buffer fills (typically 64KB), which prevents it from + // closing stderr, which prevents ReadAll from returning — deadlock. + var stderrData []byte + wg.Add(1) + go func() { + defer wg.Done() + stderrData, _ = io.ReadAll(stderr) + }() readErr := d.readPCM(ctx, stdout, sampleRate, channels, meta.SourceID, emit) waitErr := cmd.Wait() wg.Wait()