Bugfixes
This commit is contained in:
+4
-3
@@ -911,14 +911,15 @@ def cmd_stitch(
|
|||||||
narration,
|
narration,
|
||||||
stitch_output,
|
stitch_output,
|
||||||
verbose=verbose,
|
verbose=verbose,
|
||||||
|
default_end_trim=config.default_end_trim if config else 0.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Run import videos again, because at this point narration_combined might have been created.
|
# Run import videos again, because at this point narration_combined might have been created.
|
||||||
_import_videos(videos_dir, config, verbose)
|
_import_videos(videos_dir, config, verbose)
|
||||||
|
|
||||||
# Always update the MAIN videos.json (parent directory when in proxy mode)
|
# Always update the MAIN videos.json (parent of subdir when using low/tiny res)
|
||||||
# Proxy mode only affects file paths, not JSON metadata updates
|
# Downscaled dirs only affect file paths, not JSON metadata updates
|
||||||
main_videos_dir = videos_dir.parent if proxy else videos_dir
|
main_videos_dir = videos_dir.parent if res != "full" else videos_dir
|
||||||
videos_json_path = main_videos_dir / "videos.json"
|
videos_json_path = main_videos_dir / "videos.json"
|
||||||
if True: # Always update JSON regardless of proxy mode
|
if True: # Always update JSON regardless of proxy mode
|
||||||
existing_videos: dict = {}
|
existing_videos: dict = {}
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ class ProjectConfig:
|
|||||||
gnommo_scratch: Optional[
|
gnommo_scratch: Optional[
|
||||||
str
|
str
|
||||||
] = None # directory for intermediate files (e.g., external SSD)
|
] = None # directory for intermediate files (e.g., external SSD)
|
||||||
|
default_begin: float = 0.0 # Trim this many seconds from the start of each segment (if no explicit begin/skip)
|
||||||
|
default_end_trim: float = 0.0 # Trim this many seconds from the end of each segment (if no explicit end/take)
|
||||||
# Outro sequence - plays after narration ends (not marker-triggered)
|
# Outro sequence - plays after narration ends (not marker-triggered)
|
||||||
outro: list[str] = field(
|
outro: list[str] = field(
|
||||||
default_factory=list
|
default_factory=list
|
||||||
|
|||||||
+6
-2
@@ -199,6 +199,8 @@ def parse_project_config(project_path: Path) -> ProjectConfig:
|
|||||||
audio_source=data.get("audio_source"),
|
audio_source=data.get("audio_source"),
|
||||||
main_video=data.get("main_video"),
|
main_video=data.get("main_video"),
|
||||||
gnommo_scratch=data.get("gnommo_scratch"),
|
gnommo_scratch=data.get("gnommo_scratch"),
|
||||||
|
default_begin=float(data.get("default_begin", 0.0)),
|
||||||
|
default_end_trim=float(data.get("default_end_trim", 0.0)),
|
||||||
outro=data.get("outro", []),
|
outro=data.get("outro", []),
|
||||||
description=data.get("description", ""),
|
description=data.get("description", ""),
|
||||||
footer=data.get("footer", ""),
|
footer=data.get("footer", ""),
|
||||||
@@ -518,10 +520,12 @@ def parse_narration(
|
|||||||
filter_list = filter_value
|
filter_list = filter_value
|
||||||
|
|
||||||
# Handle skip/take - can use begin/end as user-friendly alternatives
|
# Handle skip/take - can use begin/end as user-friendly alternatives
|
||||||
skip = segment_data.get("skip", 0.0)
|
# Fall back to project-level defaults if no explicit value is set
|
||||||
|
default_begin = config.default_begin if config else 0.0
|
||||||
|
skip = segment_data.get("skip", default_begin)
|
||||||
take = segment_data.get("take")
|
take = segment_data.get("take")
|
||||||
|
|
||||||
# Convert begin/end to skip/take if provided
|
# Explicit begin/end always override defaults
|
||||||
if "begin" in segment_data and segment_data["begin"]:
|
if "begin" in segment_data and segment_data["begin"]:
|
||||||
skip = parse_timestamp(segment_data["begin"])
|
skip = parse_timestamp(segment_data["begin"])
|
||||||
if "end" in segment_data and segment_data["end"]:
|
if "end" in segment_data and segment_data["end"]:
|
||||||
|
|||||||
@@ -1951,6 +1951,7 @@ def stitch_narration_segments(
|
|||||||
videos: dict[str, VideoSource],
|
videos: dict[str, VideoSource],
|
||||||
output_path: Path,
|
output_path: Path,
|
||||||
verbose: bool = False,
|
verbose: bool = False,
|
||||||
|
default_end_trim: float = 0.0,
|
||||||
) -> Path:
|
) -> Path:
|
||||||
"""
|
"""
|
||||||
Stitch multiple narration video segments into a single file.
|
Stitch multiple narration video segments into a single file.
|
||||||
@@ -1965,6 +1966,7 @@ def stitch_narration_segments(
|
|||||||
videos: Dict of video ID -> VideoSource from videos.json
|
videos: Dict of video ID -> VideoSource from videos.json
|
||||||
output_path: Path for the concatenated output file
|
output_path: Path for the concatenated output file
|
||||||
verbose: Enable verbose output
|
verbose: Enable verbose output
|
||||||
|
default_end_trim: Seconds to trim from the end when no explicit end/take is set
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path to the stitched video file.
|
Path to the stitched video file.
|
||||||
@@ -2003,6 +2005,10 @@ def stitch_narration_segments(
|
|||||||
skip = video_source.skip or 0.0
|
skip = video_source.skip or 0.0
|
||||||
take = video_source.take
|
take = video_source.take
|
||||||
|
|
||||||
|
# Apply default end trim if no explicit take/end was set
|
||||||
|
if take is None and default_end_trim > 0:
|
||||||
|
take = max(0.0, full_duration - skip - default_end_trim)
|
||||||
|
|
||||||
# Calculate effective duration
|
# Calculate effective duration
|
||||||
if take is not None:
|
if take is not None:
|
||||||
effective_duration = min(take, full_duration - skip)
|
effective_duration = min(take, full_duration - skip)
|
||||||
|
|||||||
@@ -269,6 +269,8 @@ def build_ffmpeg_command(plan: RenderPlan, output_path: Path) -> list[str]:
|
|||||||
always_visible_inputs.append(input_idx)
|
always_visible_inputs.append(input_idx)
|
||||||
input_idx += 1
|
input_idx += 1
|
||||||
|
|
||||||
|
from .cache import resolve_with_cache
|
||||||
|
|
||||||
# Input: background — resolved via handle in shared_assets/videos.json
|
# Input: background — resolved via handle in shared_assets/videos.json
|
||||||
import json as _json
|
import json as _json
|
||||||
bg_handle = plan.config.background
|
bg_handle = plan.config.background
|
||||||
|
|||||||
Reference in New Issue
Block a user