Skip to content

fix(media-use): remove clicks and ~25ms gaps at every transcript-cut splice - #4179

Open
larrylicuanan2488-wq wants to merge 1 commit into
heygen-com:mainfrom
larrylicuanan2488-wq:fix/transcript-cut-splice-artifacts
Open

larrylicuanan2488-wq wants to merge 1 commit into
heygen-com:mainfrom
larrylicuanan2488-wq:fix/transcript-cut-splice-artifacts

Conversation

@larrylicuanan2488-wq

Copy link
Copy Markdown

The problem

skills/media-use/scripts/transcript-cut.mjs extracts each kept range to its own final-codec file, then concat-copies them. Two audible artifacts result at every cut, and they are separate bugs:

  1. No boundary fades. Concat splices raw segment edges together, so the waveform steps discontinuously and each cut clicks.
  2. Encoder priming silence. Each segment is encoded to AAC independently, so the encoder pads every one with priming samples; stream-copy concat bakes that in as a silent gap. It also accumulates — the nth splice lands roughly 25n ms late, so splice positions no longer match the sum of the preceding segment durations.

The second survives the first. Adding fades alone still leaves the gap, which is what made it easy to miss.

Reproduce

node skills/media-use/scripts/transcript-cut.mjs \
  --input take.mp4 --transcript take.json --keep "5-10,20-25,40-45" --out out.mp4

Widest run of digital silence within ±0.25 s of each nominal splice:

splice @5S splice @10s
main 24.4 ms 24.1 ms
this PR 0.1 ms 0.1 ms

The fix

Intermediates carry PCM (.mkv for video, .wav for audio-only) rather than the final codec, so audio is encoded exactly once — at concat. Per-segment 30 ms afade in/out ramps handle the click, scaled down on segments shorter than 4× the ramp and skipped on degenerate ones.

Not changed

  • --copy — stream copy cannot filter, so it still produces final-codec segments and a copy concat. The flag already trades accuracy for speed; this leaves that trade alone.
  • Audio-only output — identical duration before and after (10.000000 s on the same two-range cut). .wav intermediates avoid the aac-in-wav timing break the existing encodeArgsFor comment warns about.

Verification

  • scripts/lib/*.test.mjs: 34/35. The one failure, lut-preset-provider.test.mjs, reproduces on unmodified main and is unrelated (it reads a packages/core/src/colorGrading.ts that does not exist in this repo).
  • Measurements above taken on public-domain footage (Prelinger Archives, The Quiet Revolution, 1956).

🤖 Generated with Claude Code

…splice

transcript-cut extracts each kept range to its own final-codec file, then
concat-copies them. That produces two audible artifacts at every cut:

1. No boundary fades. Concat splices raw segment edges together, so the
   waveform steps discontinuously and each cut clicks.

2. Encoder priming silence. Each segment is encoded to AAC independently,
   so the encoder pads every one with priming samples. Stream-copy concat
   bakes that padding in as a silent gap at each splice. Measured 24.4 ms
   and 24.1 ms at the two splices of a three-range cut. It accumulates:
   the nth splice lands roughly 25n ms late, so splice positions drift
   away from the sum of the preceding segment durations.

The second survives the first -- adding fades alone leaves the gap.

Fix: intermediates carry PCM (.mkv for video, .wav for audio-only) instead
of the final codec, so audio is encoded exactly once, at concat. Boundary
fades of 30 ms are applied per segment, scaled down on segments shorter
than 4x the ramp and skipped on degenerate ones.

Measured on the same three-range cut, widest run of digital silence at
each splice:

  before  24.4 ms / 24.1 ms
  after    0.1 ms /  0.1 ms

--copy is unchanged: stream copy cannot filter, so it keeps producing
final-codec segments and a copy concat. Audio-only output is byte-identical
in duration before and after. scripts/lib test suite: 34/35, the one
failure (lut-preset-provider) pre-exists on main and is unrelated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@miguel-heygen
miguel-heygen enabled auto-merge (squash) September 19, 2026 16:06
@miguel-heygen

Copy link
Copy Markdown
Collaborator

The failing check is Skills: manifest in sync. Please regenerate and commit the root manifest with:

bun run --cwd packages/cli gen:skills-manifest

This updates the media-use fingerprint from 8f21655c to 2f32518b. Please push the resulting skills-manifest.json change to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants