From b28393eb7636720102e41796bd6f8fd7ebcd8746 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Thu, 4 Jun 2026 04:28:11 +0000 Subject: [PATCH] Revert "fix(capture): skip video-only pre-roll in standby to stop A/V pitch drift" This reverts commit 51b66d882fe24cf29faab5e0fc5cffca1ed07197. --- services/capture/src/capture-manager.js | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/services/capture/src/capture-manager.js b/services/capture/src/capture-manager.js index aba129f..9e77cdc 100644 --- a/services/capture/src/capture-manager.js +++ b/services/capture/src/capture-manager.js @@ -1078,26 +1078,13 @@ exit "$BMXRC" if (sourceAudioChannels && wantAudioChannels) audioChannels = effAudioChannels; // ── Pre-roll: discard initial unstable frames ──────────────────────────── - // CRITICAL A/V-SYNC NOTE: this drains ONLY the VIDEO pipe (fc_pipe stdout). - // The audio FIFO is opened by ffmpeg, not here, so it keeps BUFFERING during - // the drain — when ffmpeg starts it reads that buffered pre-roll audio, - // making the audio stream ~PRE_ROLL_SECONDS longer than video. Synced to the - // video length that surplus audio is compressed → a slight pitch-up. - // - // In STANDBY mode the framecache slot has been warm for a long time, so there - // are NO unstable startup frames to discard — skip the asymmetric drain - // entirely and let ffmpeg open video (fc_pipe) and audio (FIFO) together so - // both streams start from the same instant. Only the legacy on-demand spawn - // (cold slot) still needs the brief drain. - if (bridgeProcess && !_standbyMode - && (sourceType === 'deltacast' || sourceType === 'blackmagic' || sourceType === 'sdi')) { + if (bridgeProcess && (sourceType === 'deltacast' || sourceType === 'blackmagic' || sourceType === 'sdi')) { console.log(`[capture] pre-rolling: discarding ${PRE_ROLL_SECONDS}s of frames`); - bridgeProcess.stdout.on('data', () => {}); + // Attach temporary drain listener. + bridgeProcess.stdout.on('data', () => {}); await new Promise(r => setTimeout(r, PRE_ROLL_SECONDS * 1000)); bridgeProcess.stdout.removeAllListeners('data'); console.log(`[capture] pre-roll complete.`); - } else if (bridgeProcess) { - console.log('[capture] standby/warm slot — skipping video-only pre-roll to keep A/V aligned'); } const startedAt = new Date().toISOString();