Add render -n command
This commit is contained in:
+73
-7
@@ -186,6 +186,17 @@ Examples:
|
||||
dest="chunk_slides",
|
||||
help="Split render into chunks of N slides each and concatenate (overrides render_chunk_slides in .gnommo.conf)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--chunk-debug",
|
||||
type=int,
|
||||
default=0,
|
||||
dest="chunk_debug_slides",
|
||||
metavar="N",
|
||||
help="Debug: render the video in chunks of N slides each as SEPARATE files "
|
||||
"on disk (suffixed with slide range, e.g. video1_S1_S4.mp4), without "
|
||||
"concatenating — isolates where long-range renders OOM/fail.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--res",
|
||||
type=str,
|
||||
@@ -394,6 +405,7 @@ Examples:
|
||||
args.res,
|
||||
args.force,
|
||||
chunk_slides=args.chunk_slides,
|
||||
chunk_debug_slides=args.chunk_debug_slides,
|
||||
realign=args.realign,
|
||||
)
|
||||
elif action == "grade":
|
||||
@@ -4182,16 +4194,22 @@ def _chunked_render(
|
||||
out_dir: Path,
|
||||
final_output: Path,
|
||||
plan=None,
|
||||
concat: bool = True,
|
||||
) -> int:
|
||||
"""Render in slide-based chunks then concatenate — avoids filter graph OOM."""
|
||||
import math
|
||||
"""Render in slide-based chunks — avoids filter graph OOM on long videos.
|
||||
|
||||
concat=True (default) concatenates the chunks into `final_output` and deletes
|
||||
the parts. concat=False (debug, -n) keeps each chunk as its own inspectable
|
||||
file in `out_dir`, named `{stem}_{Sfirst}_{Slast}{suffix}`, and does not
|
||||
concatenate — for isolating which slide range a long render fails on.
|
||||
"""
|
||||
# Split slide IDs into groups of chunk_size
|
||||
groups = [
|
||||
slide_ids[i : i + chunk_size] for i in range(0, len(slide_ids), chunk_size)
|
||||
]
|
||||
_mode = "concatenate" if concat else "separate files (debug, no concat)"
|
||||
print(
|
||||
f"\n Auto-chunking: {len(slide_ids)} slides → {len(groups)} chunks of ≤{chunk_size}"
|
||||
f"\n Chunking: {len(slide_ids)} slides → {len(groups)} chunks of ≤{chunk_size} [{_mode}]"
|
||||
)
|
||||
|
||||
# Report clips that span a chunk boundary. v2 seeks into them so they continue
|
||||
@@ -4212,15 +4230,22 @@ def _chunked_render(
|
||||
print(" If a seam looks off, verify frame alignment (concat uses -c copy).",
|
||||
file=sys.stderr)
|
||||
|
||||
chunks_dir = out_dir / "chunks"
|
||||
chunks_dir.mkdir(parents=True, exist_ok=True)
|
||||
if concat:
|
||||
chunks_dir = out_dir / "chunks"
|
||||
chunks_dir.mkdir(parents=True, exist_ok=True)
|
||||
else:
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
chunk_paths: list[Path] = []
|
||||
for i, group in enumerate(groups):
|
||||
start = group[0]
|
||||
end = groups[i + 1][0] if i + 1 < len(groups) else None
|
||||
slides_arg = f"{start}:{end}" if end else f"{start}:"
|
||||
chunk_path = chunks_dir / f"chunk_{i+1:03d}_{start}-{end or 'end'}.mp4"
|
||||
if concat:
|
||||
chunk_path = chunks_dir / f"chunk_{i+1:03d}_{start}-{end or 'end'}.mp4"
|
||||
else:
|
||||
# Debug: land next to the final output, named by this chunk's own range.
|
||||
chunk_path = out_dir / f"{final_output.stem}_{start}_{group[-1]}{final_output.suffix}"
|
||||
|
||||
print(f"\n {'='*56}")
|
||||
print(f" Chunk {i+1}/{len(groups)}: {slides_arg} → {chunk_path.name}")
|
||||
@@ -4237,9 +4262,25 @@ def _chunked_render(
|
||||
)
|
||||
if result != 0:
|
||||
print(f"\n Chunk {i+1} failed — aborting.", file=sys.stderr)
|
||||
if not concat:
|
||||
print(
|
||||
f" → the render fails somewhere in {slides_arg} "
|
||||
f"({len(group)} slides). Narrow with a smaller -n.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return result
|
||||
chunk_paths.append(chunk_path)
|
||||
|
||||
# Debug mode: leave the per-chunk files on disk for inspection, no concat.
|
||||
if not concat:
|
||||
if dry_run:
|
||||
print(f"\n [dry-run] Would write {len(groups)} separate chunk file(s) to {out_dir}")
|
||||
return 0
|
||||
print(f"\n Wrote {len(chunk_paths)} chunk file(s) to {out_dir}:")
|
||||
for p in chunk_paths:
|
||||
print(f" {p.name}")
|
||||
return 0
|
||||
|
||||
if dry_run:
|
||||
print(
|
||||
f"\n [dry-run] Would concatenate {len(chunk_paths)} chunks → {final_output}"
|
||||
@@ -4656,6 +4697,7 @@ def cmd_render(
|
||||
res: str = "full",
|
||||
force: bool = False,
|
||||
chunk_slides: int = 0,
|
||||
chunk_debug_slides: int = 0,
|
||||
_output_path_override: Path = None,
|
||||
plan_only: bool = False,
|
||||
realign: bool = False,
|
||||
@@ -4672,6 +4714,7 @@ def cmd_render(
|
||||
res=res,
|
||||
force=force,
|
||||
chunk_slides=chunk_slides,
|
||||
chunk_debug_slides=chunk_debug_slides,
|
||||
_output_path_override=_output_path_override,
|
||||
plan_only=plan_only,
|
||||
realign=realign,
|
||||
@@ -4730,6 +4773,7 @@ def _cmd_render_impl(
|
||||
res: str = "full",
|
||||
force: bool = False,
|
||||
chunk_slides: int = 0,
|
||||
chunk_debug_slides: int = 0,
|
||||
_output_path_override: Path = None,
|
||||
plan_only: bool = False,
|
||||
realign: bool = False,
|
||||
@@ -5153,8 +5197,30 @@ def _cmd_render_impl(
|
||||
# Check if chunked rendering is needed (avoids filter graph OOM on long videos)
|
||||
from .cache import get_render_chunk_size
|
||||
|
||||
_chunk_size = chunk_slides or get_render_chunk_size() or 0
|
||||
_slide_ids = [e.slide_id for e in plan.slide_events]
|
||||
|
||||
# Debug mode (-n N): render each N-slide chunk to its own file on disk and
|
||||
# stop — no concatenation. Lets you see exactly which slide range a long
|
||||
# render dies on, and what chunking does to the memory profile.
|
||||
if chunk_debug_slides > 0 and _output_path_override is None:
|
||||
if slide_range:
|
||||
print(" -n/--chunk-debug cannot be combined with --slides.", file=sys.stderr)
|
||||
return 1
|
||||
return _chunked_render(
|
||||
project_path,
|
||||
verbose,
|
||||
dry_run,
|
||||
res,
|
||||
force,
|
||||
chunk_debug_slides,
|
||||
_slide_ids,
|
||||
out_dir,
|
||||
output_path,
|
||||
plan=plan,
|
||||
concat=False,
|
||||
)
|
||||
|
||||
_chunk_size = chunk_slides or get_render_chunk_size() or 0
|
||||
if _chunk_size > 0 and not slide_range and len(_slide_ids) > _chunk_size:
|
||||
return _chunked_render(
|
||||
project_path,
|
||||
|
||||
Reference in New Issue
Block a user