Repository navigation
Faster blended stitch, clip sound matched to the narration, and the score's choice during clips - #14
Merged
Merged
Conversation
A blended stitch re-encoded the whole video to draw its dissolves. At 1080p on the medium preset that was most of a render: 12 minutes of a half-hour job for a 14-minute video with 53 shots. Every shot is encoded with encode_args, so between two keyframes it can be copied and remuxed beside freshly encoded frames. plan_partial_stitch lays the picture out as copied stretches and, for each blend, a re-encode from the outgoing shot's last keyframe before the blend to the incoming shot's first after it (a short shot with no keyframe clear of both blends joins them into one encode, chunked like the full stitch). Each blend is anchored to the timeline, since the copied stretches are whole frames and the timeline is not; left alone the error added up to 25 frames over 38 blends. The sound is built for the whole video in one pass, exactly as before, and muxed back in, so it is never cut at an AAC packet boundary. The copied pieces are written on the 90 kHz timescale every encode uses: on 1/15360, ffmpeg 6's concat laid them out a minute apart. Checked against the full stitch on ffmpeg 6.1 and 7.1.1, 45 shots and 38 blends: same frame count, min 36 dB (the encode generations), and the sound on the planned timeline to the sample, where the full stitch ran 20 ms late. At 1080p medium, 12 shots and 10 blends: 38 s -> 22 s, of which 16 s is the blends, a cost that follows the number of blends rather than the length of the video. If the partial stitch fails, the full one runs, and then the cuts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WJkfhgbVRktPf2Lg6XXfNs
…uring clips Clips played their sound at whatever level the footage had, so one interview was a whisper and the next drowned the voice. Each clip is now measured (EBU R128, over the part that plays) against the narration, measured once per render, and given one static gain to match it: the clip's own dynamics kept, a limiter at -1 dBFS only when it is raised, and a +24 dB ceiling so near-silence doesn't become loud hiss. Measured on ffmpeg 6.1 and 7.1: a clip at -18.4 LUFS lands at -31.4 against narration at -31.3. Two optional spec fields (S5), so existing specs are unchanged: - visual.volume_db, -30..20: a clip's level moved from that match. The clip player has a slider for it. - audio_tracks[].during_clips: absent keeps today's behaviour (a ducked track dips under clips as under the voice); "mute" fades the track out around each clip and back after; "play" keeps it at its level through clips, ducked under the voice alone by compressing it against a key with the clips taken out. The soundtrack panel has a select for it. The assistant's prompt names both fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WJkfhgbVRktPf2Lg6XXfNs
davior
marked this pull request as ready for review
October 23, 2026 04:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes, one commit each.
1. Encode the picture again only around each blend
A blended stitch used to re-encode the whole video just to draw its dissolves. At 1080p on the
mediumpreset ("standard" quality), that took about 12 minutes of a half-hour render for a 14-minute video with 53 shots.Every shot is encoded with the same
encode_args, so the stretch between two of its keyframes can be copied untouched and remuxed next to freshly encoded frames.plan_partial_stitchsplits the picture into copied stretches plus one re-encode per blend. Each re-encode runs from the outgoing shot's last keyframe before the blend to the incoming shot's first keyframe after it. A short shot with no keyframe clear of both its blends merges them into one encode, chunked the same way as the full stitch.Testing
medium, 12 shots, 10 blends: 38 s down to 22 s. 16 s of that is the blend encodes, which scale with the number of blends, not the video's length.2. Clip sound matched to the narration, and what the score does during clips
Clips used to play their sound at whatever level the footage had. Now each one is measured (EBU R128, over the part that plays) against the narration, which is measured once per render, and gets one fixed gain to match it.
Two optional spec fields (S5 in the plan), so existing specs are unchanged and stay
"0.2":visual.volume_db(−30 to 20): moves a clip's level from the match. The clip player has a slider for it.audio_tracks[].during_clips: left unset, nothing changes (a ducked track dips under clips as it does under the voice)."mute"fades the track out around each clip and back in after."play"keeps it at its level through clips and ducks it under the voice only, by compressing it against a key with the clips taken out. The Soundtrack panel has a dropdown for it.Measured on 6.1 and 7.1, with music under a test voice and one clip:
muteplayThe assistant's prompt names both new fields.
Checks
pytest -q: 691 passed on 6.1. The render tests, including one with a clip that plays its sound, also pass against 7.1.1.npm run buildand Prettier all clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01WJkfhgbVRktPf2Lg6XXfNs