Removing the narration_combined

This commit is contained in:
2026-07-15 18:57:11 +02:00
parent ce9c35c9b2
commit eb9196e50d
8 changed files with 267 additions and 187 deletions
+47 -35
View File
@@ -637,6 +637,8 @@ def build_render_plan(
audio: Optional[dict[str, AudioDefinition]] = None,
audio_dir: Optional[Path] = None,
slide_range: Optional[tuple[str, Optional[str]]] = None,
narration_schedule: Optional[list] = None,
narration_source: Optional[VideoSource] = None,
) -> tuple[RenderPlan, list[MarkerTiming]]:
"""
Build a complete render plan from manuscript and transcription.
@@ -655,25 +657,52 @@ def build_render_plan(
audio = audio or {}
audio_dir = audio_dir or project_path
# Find the main narration video first (need skip value for timing adjustment)
narration_video_id = config.main_video
if isinstance(narration_video_id, list):
narration_video_id = narration_video_id[0] if narration_video_id else None
if not (narration_video_id and narration_video_id in videos):
raise ValueError(
f"Main video '{narration_video_id}' not specified or not found in videos. "
f"Available: {list(videos.keys())}"
)
narration_video = videos[narration_video_id]
# Align markers to transcription timestamps
marker_timings = align_markers_to_transcription(
manuscript_text, transcription, slides=slides, videos=videos, audio=audio
)
# Apply skip offset: if narration video has skip, subtract it from all timestamps
# This accounts for the fact that the video will start at skip seconds, not 0
narration_skip = narration_video.skip
# Find shared_assets directory
shared_assets_dir = None
if (project_path / "shared_assets").exists():
shared_assets_dir = project_path / "shared_assets"
elif (project_path.parent / "shared_assets").exists():
shared_assets_dir = project_path.parent / "shared_assets"
# Track which files are loaded from external cache
cached_files: set[str] = set()
# --- Narration source ---
# Render-time concat: narration is the concatenation of the scheduled
# segments, so there is no single file to probe — the total duration is the
# sum of the segment durations and skip is already baked into each segment.
if narration_schedule:
narration_video_id = "narration"
narration_video = narration_source or VideoSource(
source_file="", cutout=config.default_slide_type, always_visible=True
)
narration_skip = 0.0
full_duration = sum(seg.duration for seg in narration_schedule)
else:
narration_video_id = config.main_video
if isinstance(narration_video_id, list):
narration_video_id = narration_video_id[0] if narration_video_id else None
if not (narration_video_id and narration_video_id in videos):
raise ValueError(
f"Main video '{narration_video_id}' not specified or not found in videos. "
f"Available: {list(videos.keys())}"
)
narration_video = videos[narration_video_id]
narration_skip = narration_video.skip
video_path, is_cached = _resolve_video_path(
videos_dir, narration_video, shared_assets_dir, project_path
)
if is_cached:
cached_files.add(narration_video_id)
full_duration = get_video_duration(video_path)
# Apply skip offset: if narration starts at `skip` seconds, subtract it from
# all marker timestamps so they line up with the trimmed timeline.
if narration_skip > 0:
for timing in marker_timings:
if timing.timestamp >= 0:
@@ -685,30 +714,12 @@ def build_render_plan(
if timing.timestamp >= 0:
marker_times[timing.marker_id] = timing.timestamp
# Find shared_assets directory
shared_assets_dir = None
if (project_path / "shared_assets").exists():
shared_assets_dir = project_path / "shared_assets"
elif (project_path.parent / "shared_assets").exists():
shared_assets_dir = project_path.parent / "shared_assets"
narration_video = videos[narration_video_id]
cutout = config.cutouts[narration_video.cutout]
# Track which files are loaded from external cache
cached_files: set[str] = set()
narration_videos: list[tuple[str, VideoSource, CutoutDefinition]] = []
video_path, is_cached = _resolve_video_path(
videos_dir, narration_video, shared_assets_dir, project_path
)
if is_cached:
cached_files.add(narration_video_id)
full_duration = get_video_duration(video_path)
# Adjust duration for skip (content starts at skip, so effective duration is less)
effective_duration = full_duration - narration_skip
# Get total duration from first always_visible video
narration_videos.append((narration_video_id, narration_video, cutout))
narration_videos: list[tuple[str, VideoSource, CutoutDefinition]] = [
(narration_video_id, narration_video, cutout)
]
# Resolve slide range to time range
time_offset = 0.0
render_end_time = effective_duration
@@ -925,6 +936,7 @@ def build_render_plan(
input_seek_time=time_offset,
shared_assets_dir=shared_assets_dir,
narration_pauses=narration_pauses,
narration_segments=narration_schedule or [],
outro_events=outro_events,
narration_end_time=narration_end_time,
cached_files=cached_files,