diff --git a/apps/media-worker/src/producer/assemble-builder.ts b/apps/media-worker/src/producer/assemble-builder.ts index 8fb990c..41f2baf 100644 --- a/apps/media-worker/src/producer/assemble-builder.ts +++ b/apps/media-worker/src/producer/assemble-builder.ts @@ -143,7 +143,12 @@ export function clipVideoChain(rotate: EdlRotate, fit: "cover" | "contain", aspe function clipAudioChain(volumeDb: number, hasAudio: boolean, inputIndex: number, trimSpanSec: string): string { const aformat = `aformat=sample_fmts=fltp:sample_rates=${ASSEMBLE_PRESET.sampleRate}:channel_layouts=stereo`; - if (!hasAudio) return `anullsrc=r=${ASSEMBLE_PRESET.sampleRate}:cl=stereo,aformat=sample_fmts=fltp:sample_rates=${ASSEMBLE_PRESET.sampleRate}:channel_layouts=stereo`; + if (!hasAudio) { + // anullsrc is an INFINITE source — unbounded, concat never finishes the + // segment and the encode deadlocks (2026-10-16 production hang). atrim pins + // the bed to the clip's trim span; asetpts restarts timestamps. + return `anullsrc=r=${ASSEMBLE_PRESET.sampleRate}:cl=stereo,atrim=0:${trimSpanSec},asetpts=PTS-STARTPTS,aformat=sample_fmts=fltp:sample_rates=${ASSEMBLE_PRESET.sampleRate}:channel_layouts=stereo`; + } return `[${inputIndex}:a]${aformat}${volumeDb === 0 ? "" : `,volume=${volumeDb}dB`}`; }