Files
video-flow/api/main.py

139 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Video Flow API - FastAPI Backend
前后端分离架构的后端服务
端口8000与 Streamlit 8503 共存8502 为历史 runtime/素材目录标识)
"""
import os
import sys
import logging
from pathlib import Path
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
# 确保项目根目录在 path 中
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
import config
from api.routes import projects, editor, assets, compose
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理"""
logger.info("Video Flow API 启动中...")
logger.info(f"项目根目录: {PROJECT_ROOT}")
logger.info(f"输出目录: {config.OUTPUT_DIR}")
logger.info(f"临时目录: {config.TEMP_DIR}")
yield
logger.info("Video Flow API 关闭中...")
# 创建 FastAPI 应用
app = FastAPI(
title="Video Flow API",
description="视频工作流后端 API - 支持项目管理、素材处理、视频编辑与合成",
version="1.0.0",
lifespan=lifespan,
docs_url="/api/docs",
redoc_url="/api/redoc",
openapi_url="/api/openapi.json"
)
# CORS 配置 - 允许 React 前端访问
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:3000", # React dev server
"http://localhost:5173", # Vite dev server
"http://127.0.0.1:3000",
"http://127.0.0.1:5173",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 挂载静态文件目录(用于访问生成的视频/图片)
app.mount("/static/output", StaticFiles(directory=str(config.OUTPUT_DIR)), name="output")
app.mount("/static/temp", StaticFiles(directory=str(config.TEMP_DIR)), name="temp")
app.mount("/static/assets", StaticFiles(directory=str(config.ASSETS_DIR)), name="assets")
# Legacy mounts8502 runtime 产物,宿主机目录通过 docker-compose 挂载到容器内)
try:
app.mount("/static/legacy-temp", StaticFiles(directory="/legacy/temp"), name="legacy-temp")
app.mount("/static/legacy-output", StaticFiles(directory="/legacy/output"), name="legacy-output")
except Exception:
# 本地非 docker 环境可能不存在这些目录
pass
# 注册路由
app.include_router(projects.router, prefix="/api/projects", tags=["Projects"])
app.include_router(editor.router, prefix="/api/editor", tags=["Editor"])
app.include_router(assets.router, prefix="/api/assets", tags=["Assets"])
app.include_router(compose.router, prefix="/api/compose", tags=["Compose"])
@app.get("/api/health")
async def health_check():
"""健康检查"""
return {
"status": "ok",
"service": "video-flow-api",
"version": "1.0.0"
}
@app.get("/api/config")
async def get_config():
"""获取前端所需的配置信息"""
return {
"video_settings": config.VIDEO_SETTINGS,
"available_voices": [
{"id": config.VOLC_TTS_DEFAULT_VOICE, "name": "三通永 (默认)"},
{"id": "zh_female_meilinvyou_saturn_bigtts", "name": "美丽女友"},
],
"available_bgm": _list_bgm_files(),
}
def _list_bgm_files():
"""列出可用的 BGM 文件"""
bgm_dir = config.ASSETS_DIR / "bgm"
if not bgm_dir.exists():
return []
bgm_files = []
for f in bgm_dir.iterdir():
if f.suffix.lower() in ['.mp3', '.mp4', '.m4a', '.wav']:
bgm_files.append({
"id": f.name,
"name": f.stem,
"path": f"/static/assets/bgm/{f.name}"
})
return bgm_files
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"api.main:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info"
)