| #!/usr/bin/env python3 |
| """Batch front-end for videoclean.""" |
| from __future__ import annotations |
|
|
| import argparse |
| import shutil |
| import subprocess |
| import sys |
| from pathlib import Path |
|
|
| VIDEO_EXTENSIONS = {".mp4", ".mkv", ".mov", ".m4v", ".avi", ".webm"} |
|
|
|
|
| def main() -> int: |
| parser = argparse.ArgumentParser(description="Batch-clean videos with videoclean") |
| parser.add_argument("source", help="Video file or directory") |
| parser.add_argument("-o", "--output", help="Output directory") |
| parser.add_argument("--clean", action="store_true", help="Compatibility flag; cleaning is the default") |
| parser.add_argument("--no-clean", "--copy", action="store_true", help="Copy files without cleaning") |
| parser.add_argument("-y", "--yes", action="store_true", help="Run without confirmation") |
| parser.add_argument("--detect-mode", choices=["auto", "fast", "balanced", "sensitive"], default="auto") |
| parser.add_argument("--inpaint-method", choices=["telea", "ns"], default="telea") |
| parser.add_argument("--inpaint-radius", type=float, default=3.0) |
| parser.add_argument("--inpaint-dilate", type=int, default=0) |
| args = parser.parse_args() |
|
|
| source = Path(args.source).expanduser().resolve() |
| if source.is_file(): |
| videos = [source] |
| elif source.is_dir(): |
| videos = sorted(path for path in source.iterdir() if path.suffix.lower() in VIDEO_EXTENSIONS) |
| else: |
| parser.error(f"source does not exist: {source}") |
| if not videos: |
| parser.error(f"no videos found in {source}") |
|
|
| output = Path(args.output).expanduser().resolve() if args.output else source.parent / f"{source.stem}_processed" |
| output.mkdir(parents=True, exist_ok=True) |
| python = Path(__file__).resolve().parent / ".venv" / "bin" / "python" |
| if not python.exists(): |
| python = Path(sys.executable) |
|
|
| for video in videos: |
| destination = output / f"{video.stem}.mp4" |
| if args.no_clean: |
| shutil.copy2(video, destination) |
| continue |
| command = [ |
| str(python), "-m", "videoclean.cli", "clean", str(video), |
| "-o", str(output), "--detect-mode", args.detect_mode, |
| "--inpaint-method", args.inpaint_method, |
| "--inpaint-radius", str(args.inpaint_radius), |
| "--inpaint-dilate", str(args.inpaint_dilate), |
| ] |
| result = subprocess.run(command) |
| if result.returncode: |
| return result.returncode |
| generated = output / f"{video.stem}_clean.mp4" |
| if generated.exists() and generated != destination: |
| generated.replace(destination) |
| return 0 |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|