Improving de-shimy trip
This commit is contained in:
+47
-10
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user