Files

74 lines
2.8 KiB
Python

"""CLI entry point.
Usage:
python main.py "https://www.youtube.com/watch?v=..." \
--num-clips 3 --aspect-ratio 9:16
"""
import argparse
import json
import sys
# Windows uses 'charmap' by default, which can't encode Unicode characters
# like →. Reconfigure stdout/stderr to UTF-8 so output works on all platforms.
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
if hasattr(sys.stderr, "reconfigure"):
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
from shorts_generator import generate_shorts
def main() -> int:
parser = argparse.ArgumentParser(description="AI YouTube Shorts Generator")
parser.add_argument("url", help="YouTube URL, file:// URL, or local file path")
parser.add_argument(
"--mode",
choices=["api", "local"],
default="api",
help="api (default, MuAPI) or local (remote URL, file://, or local path + faster-whisper + LLM provider + ffmpeg).",
)
parser.add_argument("--num-clips", type=int, default=3, help="How many shorts to render (default: 3)")
parser.add_argument("--aspect-ratio", default="9:16", help="Output aspect ratio (default: 9:16)")
parser.add_argument("--format", default="720", help="Source download resolution: 360 / 480 / 720 / 1080 (default: 720)")
parser.add_argument("--language", default=None, help="Force Whisper language code, e.g. 'en' (default: auto-detect)")
parser.add_argument("--output-json", default=None, help="Write the full result JSON to this path")
args = parser.parse_args()
try:
result = generate_shorts(
youtube_url=args.url,
num_clips=args.num_clips,
aspect_ratio=args.aspect_ratio,
download_format=args.format,
language=args.language,
mode=args.mode,
)
except Exception as e:
print(f"\nFAILED: {e}", file=sys.stderr)
return 1
print("\n" + "=" * 72)
print(f"Mode: {result.get('mode', args.mode)}")
print(f"Source video: {result['source_video_url']}")
print(f"Highlights: {len(result['highlights'])} candidates → kept top {len(result['shorts'])}")
print("=" * 72)
for i, s in enumerate(result["shorts"], 1):
print(f"\n#{i} score={s.get('score')} {s.get('start_time'):.1f}s → {s.get('end_time'):.1f}s")
print(f" title: {s.get('title')}")
print(f" hook: {s.get('hook_sentence')}")
if s.get("clip_url"):
print(f" clip: {s['clip_url']}")
else:
print(f" clip: FAILED ({s.get('error')})")
if args.output_json:
with open(args.output_json, "w") as f:
json.dump(result, f, indent=2)
print(f"\nFull JSON written to {args.output_json}")
return 0
if __name__ == "__main__":
sys.exit(main())