Improving de-shimy trip

This commit is contained in:
2026-07-16 17:18:15 +02:00
parent fa8512ff3d
commit e5bb437768
+47 -10
View File
@@ -3691,6 +3691,32 @@ def _parse_slide_range(slides_arg: str) -> tuple[str, Optional[str]]:
return start_slide, end_slide
def _resolve_pause_duration(
entry: dict, video_id: str, videos_dir: Path, shared_duration: dict[str, float]
) -> Optional[float]:
"""Resolve a clip's duration for auto-setting pause_narration.
Tries, in order: the local videos.json entry's own 'duration', the shared
library's duration (for is_shared clips whose metadata lives elsewhere), then
a direct ffprobe of the source file. Returns None if none succeed.
"""
dur = entry.get("duration") or shared_duration.get(video_id.lower())
if dur:
return float(dur)
source_file = entry.get("source_file")
if source_file:
candidate = videos_dir / source_file
if candidate.exists():
try:
from .preprocessor import get_video_duration
return round(get_video_duration(candidate), 3)
except Exception:
return None
return None
def _project_markers_to_videos(
markers: list[str], videos_json_path: Path, config, project_path: Path = None
) -> None:
@@ -3737,11 +3763,12 @@ def _project_markers_to_videos(
if not projection:
return
# Build a case-insensitive index of shared_assets pause_narration values.
# When a video is marked is_shared but its local entry is missing pause_narration,
# we pull the value from the shared canonical entry so it's never lost when
# the ETL writes back cutout/layer under a lowercase key.
# Build case-insensitive indexes of shared_assets pause_narration and duration.
# When a video is marked is_shared its metadata lives in the shared canonical
# entry, not the local one — so a pause-prefix marker on a shared clip would
# otherwise never get pause_narration set (the local entry has no duration).
_shared_pause: dict[str, float] = {}
_shared_duration: dict[str, float] = {}
for _shared_candidate in [
project_path / "shared_assets" / "videos.json",
project_path.parent / "shared_assets" / "videos.json",
@@ -3754,6 +3781,9 @@ def _project_markers_to_videos(
pn = _v.get("pause_narration")
if pn:
_shared_pause[_k.lower()] = float(pn)
dur = _v.get("duration")
if dur:
_shared_duration[_k.lower()] = float(dur)
except (json.JSONDecodeError, OSError):
pass
break
@@ -3773,12 +3803,19 @@ def _project_markers_to_videos(
video_changed = False
for field, value in fields.items():
if field == "_auto_pause":
# Write pause_narration = duration only when:
# A pause-prefix marker (vftp:, vfbp:, …) means "freeze the
# narration for this clip's whole length", so pause_narration
# must equal the clip's duration. Set it whenever:
# - marker is a pause-prefix (value is True)
# - pause_narration not already set (preserve manual overrides)
# - duration is known (probed by import)
if value and not entry.get("pause_narration") and entry.get("duration"):
entry["pause_narration"] = entry["duration"]
# - a duration can be resolved (local entry, shared library,
# or by probing the file as a last resort)
if value and not entry.get("pause_narration"):
dur = _resolve_pause_duration(
entry, video_id, json_path.parent, _shared_duration
)
if dur:
entry["pause_narration"] = dur
changed = True
video_changed = True
elif entry.get(field) != value:
@@ -3786,8 +3823,8 @@ def _project_markers_to_videos(
changed = True
video_changed = True
# For is_shared entries: inherit pause_narration from shared_assets if
# not already set locally (handles case where explicit pause_narration
# lives on a different-case key in the shared library).
# still not set (handles an explicit pause_narration that lives on a
# different-case key in the shared library).
if entry.get("is_shared") and not entry.get("pause_narration"):
shared_pn = _shared_pause.get(video_id.lower())
if shared_pn: