From 298589d7cc6a5808f34fd8bc15cba85419c7ce77 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Thu, 12 Mar 2026 12:21:30 +0300 Subject: [PATCH] fix(web-test): fix amix silence with many adelay inputs (int64 overflow) ffmpeg amix + adelay with large delays causes timestamp overflow (dts near INT64_MAX), producing silent/truncated audio. Fix: use a silence reference track as first amix input with duration=first, so amix runs for full video length regardless of delayed stream timestamps. Co-Authored-By: Claude Opus 4.6 --- .claude/skills/web-test/scripts/browser.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.claude/skills/web-test/scripts/browser.mjs b/.claude/skills/web-test/scripts/browser.mjs index 96db4a4b..2d77b891 100644 --- a/.claude/skills/web-test/scripts/browser.mjs +++ b/.claude/skills/web-test/scripts/browser.mjs @@ -3331,15 +3331,20 @@ export async function addNarration(videoPath, opts = {}) { const label = `a${i}`; mixLabels.push(`[${label}]`); - filterParts.push(`[${i}]${filters.length ? filters.join(',') : 'acopy'}[${label}]`); + // Input indices are shifted by 1 because silence reference is input [0] + filterParts.push(`[${i + 1}]${filters.length ? filters.join(',') : 'acopy'}[${label}]`); } + // Generate a silence reference track as input [0] so amix runs for full video duration + const silencePath = pathJoin(tempDir, 'silence.mp3'); + generateSilence(silencePath, Math.ceil(videoDuration), ffmpegPath); + const filterComplex = filterParts.join(';') + ';' + - mixLabels.join('') + `amix=inputs=${captions.length}:normalize=0`; + `[0]${mixLabels.join('')}amix=inputs=${captions.length + 1}:normalize=0:duration=first`; const narrationPath = pathJoin(tempDir, 'narration.mp3'); execFileSync(ffmpegPath, [ - '-y', ...ffmpegInputs, + '-y', '-i', silencePath, ...ffmpegInputs, '-filter_complex', filterComplex, '-t', String(Math.ceil(videoDuration)), '-c:a', 'libmp3lame', '-b:a', '128k', narrationPath,