from __future__ import annotations import argparse import threading from video_pipeline import ConversionConfig, run_conversion_jobs def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="批量视频转 HLS 切片") parser.add_argument("--root", default=".", help="任务根目录") parser.add_argument("--jobs", type=int, default=None, help="并发转码任务数") parser.add_argument("--resolution", default="1280:720", help="输出分辨率") parser.add_argument("--video-bitrate", default="2000k", help="视频码率") parser.add_argument("--audio-bitrate", default="128k", help="音频码率") parser.add_argument("--hls-time", type=int, default=10, help="切片时长") parser.add_argument("--preset", default="p4", help="NVENC preset") parser.add_argument("--flat-output", action="store_true", help="关闭单集子目录模式") return parser def main() -> int: parser = build_parser() args = parser.parse_args() config = ConversionConfig( root_dir=args.root, parallel_jobs=args.jobs or ConversionConfig().parallel_jobs, resolution=args.resolution, video_bitrate=args.video_bitrate, audio_bitrate=args.audio_bitrate, hls_time=max(1, args.hls_time), preset=args.preset, episode_folder_mode=not args.flat_output, ) def on_event(payload: dict) -> None: kind = payload.get("kind") if kind == "log": line = payload.get("line") if line: print(line) summary = run_conversion_jobs(config, event_callback=on_event, stop_event=threading.Event()) print( f"\n完成:成功 {summary.succeeded}/{summary.total},失败 {summary.failed}," f"日志 {summary.log_file}" ) return 0 if summary.failed == 0 else 1 if __name__ == "__main__": raise SystemExit(main())