fix(pipeline): probe duration via cv2 (no ffprobe dep); wire MASTER_MAX_W; fps-sync note
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+19
-12
@@ -1,6 +1,6 @@
|
||||
"""Thin runner: ffprobe the source, then execute the frame -> loop -> transcode
|
||||
stages with tools.pipeline.ffmpeg_ops. The pure arg builders are unit-tested;
|
||||
this glue is covered by the opt-in integration test."""
|
||||
"""Thin runner: probe the source duration, then execute the frame -> loop ->
|
||||
transcode stages with tools.pipeline.ffmpeg_ops. The pure arg builders are
|
||||
unit-tested; this glue is covered by the opt-in integration test."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -22,13 +22,17 @@ def resolve_ffmpeg() -> str:
|
||||
return imageio_ffmpeg.get_ffmpeg_exe()
|
||||
|
||||
|
||||
def probe_duration(src, *, ff: str = "ffprobe") -> float:
|
||||
out = subprocess.run(
|
||||
[ff, "-v", "quiet", "-show_entries", "format=duration",
|
||||
"-of", "csv=p=0", str(src)],
|
||||
capture_output=True, text=True, check=True,
|
||||
).stdout.strip()
|
||||
return float(out)
|
||||
def probe_duration(src) -> float:
|
||||
"""Clip duration in seconds via cv2 (frame_count / fps) — avoids a system
|
||||
ffprobe dependency (imageio-ffmpeg ships ffmpeg only; the Pi has no ffprobe)."""
|
||||
import cv2
|
||||
cap = cv2.VideoCapture(str(src))
|
||||
fps = cap.get(cv2.CAP_PROP_FPS) or 0.0
|
||||
frames = cap.get(cv2.CAP_PROP_FRAME_COUNT) or 0.0
|
||||
cap.release()
|
||||
if fps <= 0:
|
||||
raise ValueError(f"could not read fps from {src}")
|
||||
return frames / fps
|
||||
|
||||
|
||||
def _run(args: list[str]) -> None:
|
||||
@@ -36,10 +40,13 @@ def _run(args: list[str]) -> None:
|
||||
|
||||
|
||||
def process_clip(src, out_dir, *, start: float = 0.0, duration: float | None = None,
|
||||
overlap: float = 1.0, master_w: int = 3840, master_h: int = 2160,
|
||||
overlap: float = 1.0, master_w: int = MASTER_MAX_W, master_h: int = 2160,
|
||||
ff: str | None = None) -> dict:
|
||||
"""Run stages 2–4 for one clip; return {'master','proxy','loop','mezzanine'} paths.
|
||||
`duration` defaults to the full source length (minus the trim start)."""
|
||||
`duration` defaults to the full source length (minus the trim start).
|
||||
Note: `crossfade_loop_args` uses a fixed fps only to satisfy xfade's
|
||||
constant-frame-rate requirement; the final output fps is set by `transcode_args`
|
||||
(both default 30 — keep in sync if overridden)."""
|
||||
ff = ff or resolve_ffmpeg()
|
||||
src = Path(src)
|
||||
out_dir = Path(out_dir)
|
||||
|
||||
Reference in New Issue
Block a user