Files

94 lines
2.6 KiB
Python

# -*- 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/<path:filename>")
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)