# -*- coding: utf-8 -*- """Flask Web 入口 提供简单的 Web 界面,输入主题后自动生成短视频。 """ import os import uuid import traceback from flask import Flask, render_template, request, jsonify, send_from_directory 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 app = Flask(__name__) OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "output") os.makedirs(OUTPUT_DIR, exist_ok=True) def _probe_duration(path: str) -> float: """获取音频时长(秒)""" from moviepy.editor import AudioFileClip clip = AudioFileClip(path) dur = clip.duration clip.close() return float(dur) def run_pipeline(topic: str, scenes: int = 5, rate: int = 160) -> dict: """完整生成流水线""" 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) script = generate_script(topic, scenes) audio_paths = [] durations = [] for s in script: ap = os.path.join(audio_dir, f"{s['index']}.mp3") text_to_speech(s["text"], ap, rate=rate) audio_paths.append(ap) durations.append(_probe_duration(ap)) srt_path = os.path.join(job_dir, "subtitle.srt") build_srt(script, durations, srt_path) video_path = os.path.join(job_dir, "video.mp4") compose_video(script, audio_paths, durations, video_path) return { "job_id": job_id, "video": f"output/{job_id}/video.mp4", "subtitle": f"output/{job_id}/subtitle.srt", "script": script, } @app.route("/") def index(): return render_template("index.html") @app.route("/api/generate", methods=["POST"]) def api_generate(): data = request.get_json(force=True, silent=True) or {} topic = (data.get("topic") or "").strip() scenes = int(data.get("scenes") or 5) rate = int(data.get("rate") or 160) if not topic: return jsonify({"ok": False, "error": "请填写主题"}), 400 if scenes < 1 or scenes > 8: return jsonify({"ok": False, "error": "场景数需在 1-8 之间"}), 400 try: result = run_pipeline(topic, scenes, rate) return jsonify({"ok": True, **result}) except Exception as e: traceback.print_exc() return jsonify({"ok": False, "error": str(e)}), 500 @app.route("/output/") def serve_output(filename): return send_from_directory(OUTPUT_DIR, filename) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)