Fixing some filter paralleism

This commit is contained in:
2026-05-12 08:04:45 +02:00
parent 994a2e0bb6
commit 409d7790c0
6 changed files with 92 additions and 18 deletions
+51 -14
View File
@@ -1256,6 +1256,16 @@ def cmd_validate(project_path: Path, verbose: bool) -> int:
# =============================================================================
def _resolve_process_cache(project_path: Path, config) -> Optional[Path]:
"""Return per-project cache dir on external disk, or None if not configured."""
if not (config and config.process_cache):
return None
p = Path(config.process_cache)
if not p.is_absolute():
p = (project_path / p).resolve()
return p / project_path.name
def cmd_preprocess(
project_path: Path,
verbose: bool,
@@ -1280,13 +1290,24 @@ def cmd_preprocess(
config = parse_project_config(project_path)
# Narration directory — always media/narration/
# Narration directory — source files always in project media/narration/
narration_dir = project_path / "media" / "narration"
narration_dir.mkdir(parents=True, exist_ok=True)
raw_dir = narration_dir / "raw_mov"
compressed_dir = narration_dir / "raw_mp4"
processed_dir = narration_dir / "processed"
# process_cache: write processed outputs to external disk to save laptop space
cache_root = _resolve_process_cache(project_path, config)
if cache_root:
cache_narration_dir = cache_root / "narration"
cache_narration_dir.mkdir(parents=True, exist_ok=True)
(cache_narration_dir / "processed").mkdir(parents=True, exist_ok=True)
print(f" Using process cache: {cache_root}")
else:
cache_narration_dir = None
processed_dir = (cache_narration_dir or narration_dir) / "processed"
processed_dir.mkdir(parents=True, exist_ok=True)
# Resolve intermediate directory
@@ -1362,7 +1383,10 @@ def cmd_preprocess(
output_file = f"{_subdir}/processed/{segment_id}_processed.mov"
else:
output_file = f"processed/{segment_id}_processed.mov"
output_path = narration_dir / output_file
# When process_cache is set, output goes to the cache dir; narration.json
# still records the relative path so stitch (also using cache) can find it.
output_base = cache_narration_dir or narration_dir
output_path = output_base / output_file
if output_path.exists() and not force:
print(f" {segment_id}: output exists, skipping (use --force to reprocess)")
@@ -1420,7 +1444,7 @@ def cmd_preprocess(
def process_segment_task(task):
seg_id, seg_source = task
preprocess_video(
narration_dir,
cache_narration_dir or narration_dir,
seg_id,
seg_source,
verbose=False,
@@ -1439,7 +1463,7 @@ def cmd_preprocess(
seg_id, seg_source = future.result()
completed += 1
print(f" Completed: {seg_id} ({completed}/{len(segments_to_process)})")
output_path = narration_dir / seg_source.output_file
output_path = (cache_narration_dir or narration_dir) / seg_source.output_file
if output_path.exists():
successfully_processed.append((seg_id, seg_source))
else:
@@ -1449,7 +1473,7 @@ def cmd_preprocess(
print(f" Output: {segment_source.output_file}")
print(f" Filters: {len(segment_source.filter)} step(s)")
preprocess_video(
narration_dir,
cache_narration_dir or narration_dir,
segment_id,
segment_source,
verbose,
@@ -1457,7 +1481,7 @@ def cmd_preprocess(
gnommo_scratch,
res=res,
)
output_path = narration_dir / segment_source.output_file
output_path = (cache_narration_dir or narration_dir) / segment_source.output_file
if output_path.exists():
successfully_processed.append((segment_id, segment_source))
@@ -2039,15 +2063,26 @@ def cmd_stitch(
else:
videos_dir = project_path / "media" / "videos"
# When process_cache is set, redirect processed segment reads and combined output
cache_root = _resolve_process_cache(project_path, config)
if cache_root:
narration_dir = cache_root / "narration"
narration_dir.mkdir(parents=True, exist_ok=True)
videos_dir_out = cache_root / "videos"
videos_dir_out.mkdir(parents=True, exist_ok=True)
print(f" Using process cache: {cache_root}")
else:
videos_dir_out = videos_dir
# Use downscaled dirs for non-full res
if res != "full":
cfg = RES_CONFIGS[res]
narration_dir = ensure_downscaled_files_exist(
narration_dir, res, force=False, verbose=verbose
)
videos_dir = videos_dir / cfg[2]
videos_dir.mkdir(parents=True, exist_ok=True)
print(f" Using {res} dirs: {narration_dir}, {videos_dir}")
videos_dir_out = videos_dir_out / cfg[2]
videos_dir_out.mkdir(parents=True, exist_ok=True)
print(f" Using {res} dirs: {narration_dir}, {videos_dir_out}")
# Get segment IDs in sorted order
segment_ids = sorted(narration.keys())
@@ -2062,7 +2097,7 @@ def cmd_stitch(
trim_str = f" ({trim_info})" if trim_info else ""
print(f" - {segment_id}{trim_str}")
stitch_output = videos_dir / "narration_combined.mov"
stitch_output = videos_dir_out / "narration_combined.mov"
if stitch_output.exists() and not force:
print(f"\n Combined narration exists: {stitch_output.name}")
@@ -2085,12 +2120,14 @@ def cmd_stitch(
default_end_trim=config.default_end_trim if config else 0.0,
loudnorm_config=_loudnorm_cfg,
)
# Run import videos again, because at this point narration_combined might have been created.
_import_videos(videos_dir, config, verbose)
# Run import videos again to update duration metadata (skip when using cache
# since narration_combined.mov lives on the external disk, not in videos_dir).
if not cache_root:
_import_videos(videos_dir_out, config, verbose)
# Always update the MAIN videos.json (parent of subdir when using low/tiny res)
# Downscaled dirs only affect file paths, not JSON metadata updates
main_videos_dir = videos_dir.parent if res != "full" else videos_dir
main_videos_dir = videos_dir_out.parent if (res != "full" and not cache_root) else videos_dir
videos_json_path = main_videos_dir / "videos.json"
if True: # Always update JSON regardless of proxy mode
existing_videos: dict = {}