72 lines
2.1 KiB
Python
72 lines
2.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""命令行入口
|
||
|
||
用法:
|
||
python cli.py --topic "人工智能的未来" --scenes 5 --rate 160
|
||
"""
|
||
|
||
import argparse
|
||
import os
|
||
import sys
|
||
import uuid
|
||
|
||
from core.script_gen import generate_script
|
||
from core.tts import text_to_speech
|
||
from core.subtitle import build_srt
|
||
from core.video import compose_video
|
||
|
||
OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output")
|
||
|
||
|
||
def _probe_duration(path: str) -> float:
|
||
from moviepy.editor import AudioFileClip
|
||
clip = AudioFileClip(path)
|
||
dur = clip.duration
|
||
clip.close()
|
||
return float(dur)
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="AI 全自动短视频生成器")
|
||
parser.add_argument("--topic", required=True, help="视频主题")
|
||
parser.add_argument("--scenes", type=int, default=5, help="场景数量(1-8)")
|
||
parser.add_argument("--rate", type=int, default=160, help="配音语速")
|
||
args = parser.parse_args()
|
||
|
||
if args.scenes < 1 or args.scenes > 8:
|
||
print("场景数需在 1-8 之间")
|
||
sys.exit(1)
|
||
|
||
job_id = uuid.uuid4().hex[:8]
|
||
job_dir = os.path.join(OUTPUT_DIR, job_id)
|
||
audio_dir = os.path.join(job_dir, "audio")
|
||
os.makedirs(audio_dir, exist_ok=True)
|
||
|
||
print(f"[1/4] 生成脚本...")
|
||
script = generate_script(args.topic, args.scenes)
|
||
for s in script:
|
||
print(f" {s['index']}. {s['text']}")
|
||
|
||
print(f"[2/4] 合成语音...")
|
||
audio_paths, durations = [], []
|
||
for s in script:
|
||
ap = os.path.join(audio_dir, f"{s['index']}.mp3")
|
||
text_to_speech(s["text"], ap, rate=args.rate)
|
||
audio_paths.append(ap)
|
||
durations.append(_probe_duration(ap))
|
||
print(f" {ap} ({durations[-1]:.2f}s)")
|
||
|
||
print(f"[3/4] 生成字幕...")
|
||
srt_path = os.path.join(job_dir, "subtitle.srt")
|
||
build_srt(script, durations, srt_path)
|
||
print(f" {srt_path}")
|
||
|
||
print(f"[4/4] 合成视频...")
|
||
video_path = os.path.join(job_dir, "video.mp4")
|
||
compose_video(script, audio_paths, durations, video_path)
|
||
print(f"\n✅ 完成:{video_path}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|