Spaces:
Sleeping
Sleeping
File size: 1,900 Bytes
b08c203 3447b95 b08c203 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
from fastapi import FastAPI, UploadFile, Form
from fastapi.responses import FileResponse
import uuid
import os
import subprocess
app = FastAPI()
# Overlay 和字体资源路径(固定)
FONT_PATH = "/app/assets/fonts/FonderLTHTCH.ttf"
OVERLAY_PATH = "/app/assets/overlays/dust_particles-1.mp4"
@app.post("/render")
async def render_video(
image: UploadFile,
audio: UploadFile,
fps: int = Form(...),
filter_complex: str = Form(...),
preset: str = Form(...),
filename: str = Form(...),
video_path: str = Form(...),
shortest: bool = Form(True),
):
# 文件处理
image_ext = image.filename.split(".")[-1]
audio_ext = audio.filename.split(".")[-1]
image_path = f"/tmp/{uuid.uuid4()}.{image_ext}"
audio_path = f"/tmp/{uuid.uuid4()}.{audio_ext}"
output_path = f"{video_path.rstrip('/')}/{filename}.mp4"
# 保存上传的 image 和 audio
with open(image_path, "wb") as f:
f.write(await image.read())
with open(audio_path, "wb") as f:
f.write(await audio.read())
# 构造 FFmpeg 命令
cmd = [
"ffmpeg", "-y", "-nostdin", "-hide_banner", "-loglevel", "error",
"-loop", "1", "-framerate", str(fps), "-i", image_path,
"-i", OVERLAY_PATH,
"-i", audio_path,
"-filter_complex", filter_complex,
"-map", "[v]", "-map", "2:a",
"-c:v", "libx264", "-preset", preset, "-pix_fmt", "yuv420p",
"-c:a", "aac", "-b:a", "192k",
"-movflags", "+faststart",
"-metadata", f"title={filename}"
]
if shortest:
cmd.append("-shortest")
cmd.append(output_path)
# 确保目标路径存在(仅用于 Space /tmp 测试)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# 执行 FFmpeg
subprocess.run(cmd, check=True)
return FileResponse(output_path, media_type="video/mp4", filename=f"{filename}.mp4") |