Commti prior to change to video tag below / above layering

This commit is contained in:
2026-03-16 16:57:54 +01:00
parent 757d966803
commit e734dbfcac
12 changed files with 416 additions and 154 deletions
+31 -23
View File
@@ -5,6 +5,8 @@ import subprocess
from pathlib import Path
from .errors import RenderError
from .parser import _read_json
from .preprocessor import _resolve_auto_channel
from .models import (
AudioEvent,
CameraEvent,
@@ -179,22 +181,23 @@ def _resolve_video_path(
base_dir = videos_dir
if video_source.output_file:
video_path = base_dir / video_source.output_file
# Check with cache fallback
if project_path:
resolved, _ = resolve_with_cache(video_path, project_path)
if resolved.exists():
return resolved
elif video_path.exists():
return video_path
# Check for WebM variant (preprocessing outputs compressed WebM instead of ProRes)
webm_path = video_path.with_suffix(".mov")
if project_path:
resolved, _ = resolve_with_cache(webm_path, project_path)
if resolved.exists():
return resolved
elif webm_path.exists():
return webm_path
for candidate_dir in [base_dir, base_dir.parent]:
video_path = candidate_dir / video_source.output_file
# Check with cache fallback
if project_path:
resolved, _ = resolve_with_cache(video_path, project_path)
if resolved.exists():
return resolved
elif video_path.exists():
return video_path
# Check for WebM variant (preprocessing outputs compressed WebM instead of ProRes)
webm_path = video_path.with_suffix(".mov")
if project_path:
resolved, _ = resolve_with_cache(webm_path, project_path)
if resolved.exists():
return resolved
elif webm_path.exists():
return webm_path
# Fall back to source_file with cache fallback
source_path = base_dir / video_source.source_file
@@ -272,7 +275,6 @@ def build_ffmpeg_command(plan: RenderPlan, output_path: Path) -> list[str]:
from .cache import resolve_with_cache
# Input: background — resolved via handle in shared_assets/videos.json
import json as _json
bg_handle = plan.config.background
has_background = bool(bg_handle)
bg_idx = None
@@ -282,7 +284,7 @@ def build_ffmpeg_command(plan: RenderPlan, output_path: Path) -> list[str]:
videos_json_bg = shared_assets_dir / "videos.json"
if not videos_json_bg.exists():
raise RenderError(f"shared_assets/videos.json not found (needed for background handle '{bg_handle}')")
bg_videos = _json.loads(videos_json_bg.read_text())
bg_videos = _read_json(videos_json_bg)
if bg_handle not in bg_videos:
raise RenderError(f"Background handle '{bg_handle}' not found in shared_assets/videos.json")
bg_path = shared_assets_dir / bg_videos[bg_handle]["source_file"]
@@ -719,7 +721,8 @@ def build_filter_complex(
)
else:
filters.append(
f"[{bg_idx}:v]scale={width}:{height}:force_original_aspect_ratio=increase,"
f"[{bg_idx}:v]fps={plan.config.fps},"
f"scale={width}:{height}:force_original_aspect_ratio=increase,"
f"crop={width}:{height}[bg]"
)
else:
@@ -742,9 +745,12 @@ def build_filter_complex(
if not plan.narration_pauses:
# Simple case: no pauses, continuous overlay
# fps+setpts normalise the source to a constant frame rate and reset
# the timeline to 0 so the video stays locked to the audio track.
video_label = f"av{i}"
filters.append(
f"[{input_idx}:v]format=yuva444p10le,"
f"[{input_idx}:v]fps={plan.config.fps},setpts=PTS-STARTPTS,"
f"format=yuva444p10le,"
f"scale={zoomed_width}:{zoomed_height}:force_original_aspect_ratio=increase,"
f"crop={cut_width}:{cut_height}:(iw-{cut_width})/2:(ih-{cut_height})/2,"
f"format=rgba[{video_label}]"
@@ -942,9 +948,11 @@ def build_filter_complex(
narration_volume = 1.0
if plan.narration_videos:
_, first_video_source, _ = plan.narration_videos[0]
channel_filter = _build_audio_channel_filter(
first_video_source.use_audio_channels
)
use_channels = first_video_source.use_audio_channels
if use_channels == "auto":
narration_path = _resolve_video_path(videos_dir, first_video_source, shared_assets_dir, project_path)
use_channels = _resolve_auto_channel(narration_path)
channel_filter = _build_audio_channel_filter(use_channels)
narration_volume = first_video_source.volume
# Build volume filter if not 1.0