From 7d23a71947dacf6f81201353c79d5a9d9f600335 Mon Sep 17 00:00:00 2001 From: hbrain Date: Sun, 31 May 2026 17:25:42 +0000 Subject: [PATCH] Adjust long video caption timing to start after 2s and show for 6s --- movmaker.py | 60 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/movmaker.py b/movmaker.py index f0550fa..9210f1a 100755 --- a/movmaker.py +++ b/movmaker.py @@ -60,6 +60,9 @@ CLIP_AUDIO_SIDECHAIN_THRESHOLD = 0.04 CLIP_AUDIO_SIDECHAIN_RATIO = 8.0 CLIP_AUDIO_SIDECHAIN_ATTACK = 5.0 CLIP_AUDIO_SIDECHAIN_RELEASE = 250.0 +CAPTION_LONG_VIDEO_MIN_DURATION = 10.0 +CAPTION_LONG_VIDEO_DELAY = 2.0 +CAPTION_LONG_VIDEO_SHOW = 6.0 ORDER_FILENAME = "order.json" @@ -988,6 +991,7 @@ def build_video( video_intro_duration: float | None = None, intro_visible_lead: float = 0.0, skip_video_fade_out: bool = False, + clip_kinds: list[str] | None = None, ) -> None: """Assemble normalized clips, overlays, and audio into the final MP4.""" output.parent.mkdir(parents=True, exist_ok=True) @@ -1132,17 +1136,26 @@ def build_video( if not caption: continue if n == 1: - start = intro_duration - end = total_duration + base_start = intro_duration + base_end = total_duration elif idx == 0: - start = intro_duration - end = intro_duration + transition_offsets[0] + base_start = intro_duration + base_end = intro_duration + transition_offsets[0] elif idx == n - 1: - start = intro_duration + transition_offsets[idx - 1] + fade - end = total_duration + base_start = intro_duration + transition_offsets[idx - 1] + fade + base_end = total_duration else: - start = intro_duration + transition_offsets[idx - 1] + fade - end = intro_duration + transition_offsets[idx] + base_start = intro_duration + transition_offsets[idx - 1] + fade + base_end = intro_duration + transition_offsets[idx] + + start = base_start + end = base_end + clip_kind = clip_kinds[idx] if clip_kinds and idx < len(clip_kinds) else "" + clip_duration = durations[idx] if idx < len(durations) else 0.0 + if clip_kind == "video" and clip_duration > CAPTION_LONG_VIDEO_MIN_DURATION: + start = base_start + CAPTION_LONG_VIDEO_DELAY + end = min(base_end, start + CAPTION_LONG_VIDEO_SHOW) + if end <= start: continue caption_fade = min(1.0, max(0.0, (end - start) / 2)) @@ -1411,6 +1424,7 @@ def main(argv: list[str] | None = None) -> int: # Use probed normalized duration for accuracy. durations = [ffprobe_duration(out) for out in clips] captions = [data.captions.get(item.path.name, data.captions.get(str(item.path), "")) for item in media] + clip_kinds = [item.kind for item in media] video_audio = data.video_audio or set() clip_audio_paths = [] for item in media: @@ -1451,6 +1465,7 @@ def main(argv: list[str] | None = None) -> int: intro_clip_path = intro_clip intro_clip_duration = intro_item.duration captions = ["", *captions] + clip_kinds = ["image", *clip_kinds] clip_audio_paths = [None, *clip_audio_paths] clip_stamps = ["", *clip_stamps] intro_visible_lead = min(intro_item.duration, INTRO_LOGO_FADE_OFFSET) @@ -1460,10 +1475,37 @@ def main(argv: list[str] | None = None) -> int: clips.append(intro_clip_path) durations.append(intro_clip_duration) captions.append("") + clip_kinds.append("image") clip_audio_paths.append(None) clip_stamps.append("") outro_added = True - build_video(clips, durations, audio, clip_audio_paths, output, data, first_media_date, captions, clip_stamps, fade, audio_fade, audio_fade_in, video_fade, args.intro_logo, intro_logo_alpha, width, height, fps, preset, crf, tmp, video_intro_duration, intro_visible_lead=intro_visible_lead, skip_video_fade_out=outro_added) + build_video( + clips, + durations, + audio, + clip_audio_paths, + output, + data, + first_media_date, + captions, + clip_stamps, + fade, + audio_fade, + audio_fade_in, + video_fade, + args.intro_logo, + intro_logo_alpha, + width, + height, + fps, + preset, + crf, + tmp, + video_intro_duration, + intro_visible_lead=intro_visible_lead, + skip_video_fade_out=outro_added, + clip_kinds=clip_kinds, + ) console(f"Done: {output}") return 0