fix(ports): docker 默认对外8502并修复空DB连接串回退
This commit is contained in:
138
api/main.py
Normal file
138
api/main.py
Normal file
@@ -0,0 +1,138 @@
|
||||
"""
|
||||
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 mounts(8502 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"
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user