Improvements
This commit is contained in:
+47
-10
@@ -1259,6 +1259,27 @@ def _generate_slides_json(directory: Path, verbose: bool) -> None:
|
|||||||
print(f" [{slide_id}]")
|
print(f" [{slide_id}]")
|
||||||
|
|
||||||
|
|
||||||
|
# Every user-tweakable video parameter with its default value. Written into
|
||||||
|
# each new videos.json entry (and backfilled onto existing ones) so nothing is
|
||||||
|
# an invisible optional. Auto-managed fields (output_file, duration, has_audio,
|
||||||
|
# is_shared, attribution) are intentionally omitted — they're set by the tool.
|
||||||
|
# end_on defaults to null = "use the marker-type default" (video → next_slide,
|
||||||
|
# narration → play to end); set it to "next_slide", "end", or "take" explicitly.
|
||||||
|
_VIDEO_DEFAULTS = {
|
||||||
|
"cutout": "square", # named zone from project.json cutouts
|
||||||
|
"layer": "above", # above | mid | below (relative to slides/narrator)
|
||||||
|
"filter": [], # preprocessing filter chain (empty = none)
|
||||||
|
"take": None, # max seconds to play (null = to next slide/end)
|
||||||
|
"skip": 0.0, # seconds to skip at the start
|
||||||
|
"zoom": 1.0, # scale within the cutout
|
||||||
|
"volume": 1.0, # audio volume multiplier
|
||||||
|
"use_audio_channels": "both", # both | left | right
|
||||||
|
"always_visible": False, # always on screen (like the talking head)
|
||||||
|
"pause_narration": 0.0, # seconds to freeze narration for a cutscene
|
||||||
|
"end_on": None, # null | next_slide | end | take
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _import_videos(videos_dir: Path, config, verbose: bool) -> None:
|
def _import_videos(videos_dir: Path, config, verbose: bool) -> None:
|
||||||
"""Import video files into videos.json.
|
"""Import video files into videos.json.
|
||||||
|
|
||||||
@@ -1336,25 +1357,41 @@ def _import_videos(videos_dir: Path, config, verbose: bool) -> None:
|
|||||||
print(f" Skipping {video_id} (already exists)")
|
print(f" Skipping {video_id} (already exists)")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Build the video entry
|
# Build the video entry with every tweakable parameter spelled out at
|
||||||
video_entry = {
|
# its default, so nothing is an invisible optional (that's what makes
|
||||||
"source_file": video_file.name,
|
# end_on/layer/take/… easy to miss). Auto-managed fields (duration,
|
||||||
"output_file": video_file.name,
|
# has_audio) are filled in later by the metadata probe.
|
||||||
"cutout": "square",
|
video_entry = {"source_file": video_file.name, **_VIDEO_DEFAULTS}
|
||||||
"filter": [],
|
|
||||||
}
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f" Added: {video_id}")
|
print(f" Added: {video_id}")
|
||||||
|
|
||||||
existing_videos[video_id] = video_entry
|
existing_videos[video_id] = video_entry
|
||||||
added_count += 1
|
added_count += 1
|
||||||
|
|
||||||
if added_count > 0 or removed_count > 0:
|
# Backfill missing defaults onto existing (non-shared) entries so every knob
|
||||||
|
# is visible there too. setdefault only adds absent keys — user-set values
|
||||||
|
# and the ETL-projected cutout/layer are never overwritten.
|
||||||
|
backfilled = 0
|
||||||
|
for vid_id, entry in existing_videos.items():
|
||||||
|
if not isinstance(entry, dict) or entry.get("is_shared"):
|
||||||
|
continue
|
||||||
|
before = len(entry)
|
||||||
|
for k, v in _VIDEO_DEFAULTS.items():
|
||||||
|
entry.setdefault(k, list(v) if isinstance(v, list) else v)
|
||||||
|
if len(entry) != before:
|
||||||
|
backfilled += 1
|
||||||
|
|
||||||
|
if added_count > 0 or removed_count > 0 or backfilled > 0:
|
||||||
# Write updated videos.json
|
# Write updated videos.json
|
||||||
with open(videos_json_path, "w", encoding="utf-8") as f:
|
with open(videos_json_path, "w", encoding="utf-8") as f:
|
||||||
json.dump(existing_videos, f, indent=2)
|
json.dump(existing_videos, f, indent=2)
|
||||||
if added_count > 0:
|
bits = []
|
||||||
print(f" Updated {videos_json_path.name} (+{added_count} videos)")
|
if added_count:
|
||||||
|
bits.append(f"+{added_count} new")
|
||||||
|
if backfilled:
|
||||||
|
bits.append(f"{backfilled} backfilled with defaults")
|
||||||
|
if bits:
|
||||||
|
print(f" Updated {videos_json_path.name} ({', '.join(bits)})")
|
||||||
else:
|
else:
|
||||||
print(f" No new videos to add")
|
print(f" No new videos to add")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user