Files
meijiaka-zy/python-api/app/main.py
T
小鱼开发 588c2236e6 feat: 封面制作优化 + 素材配置远程化
- 背景图配置改为从七牛云 CDN 远程拉取,支持不发版新增图片
- 删除本地 public/bg/ 图片副本,减小包体积
- 封面制作:'换一组'按钮移至标签右侧、优化按钮样式、删除冗余提示
- 封面制作/视频合成右侧预览区分别添加'封面预览'/'视频预览'标题
- 素材匹配服务支持远程 fetch materials.json + reload API
2026-04-30 15:32:10 +08:00

190 lines
5.3 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.
"""
FastAPI 应用入口
================
"""
import logging
import sys
from contextlib import asynccontextmanager
from datetime import datetime
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from app.api.v1.router import api_router
from app.config import get_settings
from app.db.session import close_db, init_db
from app.schemas.common import ApiResponse
settings = get_settings()
# 配置日志 - 同时输出到控制台和文件
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
log_level = getattr(logging, settings.LOG_LEVEL)
# 创建日志目录(在用户文档目录下)
log_dir = Path.home() / "Documents" / "Meijiaka-zy" / "logs"
log_dir.mkdir(parents=True, exist_ok=True)
# 日志文件名按日期
log_file = log_dir / f"api_{datetime.now().strftime('%Y%m%d')}.log"
# 配置根日志记录器
logging.basicConfig(
level=log_level,
format=log_format,
handlers=[
logging.StreamHandler(sys.stdout), # 控制台输出
logging.FileHandler(log_file, encoding="utf-8", mode="a"), # 文件输出
],
)
logger = logging.getLogger(__name__)
logger.info(f"日志文件位置: {log_file}")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
应用生命周期管理
- 启动时:初始化数据库、加载模型配置
- 关闭时:清理资源
"""
logger.info(f"Starting {settings.APP_NAME} v{settings.APP_VERSION}")
# 开发和测试环境自动创建表
if settings.DEBUG and settings.ENV in ("development", "staging"):
logger.info("Initializing database tables...")
try:
# 确保所有模型已注册到 metadata
from app.models import User # noqa: F401
await init_db()
logger.info("Database tables initialized")
except Exception as e:
logger.warning(f"Database initialization skipped: {e}")
# 加载 AI 模型配置(从 YAML 文件)
try:
from app.core.config_loader import get_config_loader
config_loader = get_config_loader()
platforms_count = len(config_loader.get_all_platforms())
models_count = len(config_loader.get_enabled_models())
logger.info(f"Loaded {platforms_count} platforms, {models_count} models from config file")
except Exception as e:
logger.warning(f"Failed to load models from config: {e}")
# 加载空镜素材配置(优先远程 CDN,fallback 本地 JSON
try:
from app.services.material_service import load_config
load_config()
logger.info("Loaded material config")
except Exception as e:
logger.warning(f"Failed to load material config: {e}")
yield
# 关闭时清理
logger.info("Shutting down...")
await close_db()
logger.info("Cleanup complete")
def create_app() -> FastAPI:
"""创建 FastAPI 应用实例"""
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
description="美家卡智影 - AI 视频创作后端 API",
docs_url="/docs" if settings.DEBUG else None,
redoc_url="/redoc" if settings.DEBUG else None,
lifespan=lifespan,
)
# CORS 配置
# 开发环境下允许所有来源,避免跨域问题
allow_origins = ["*"] if settings.DEBUG else settings.cors_origins_list
app.add_middleware(
CORSMiddleware,
allow_origins=allow_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(api_router, prefix="/api/v1")
# 全局异常处理(统一返回 ApiResponse 格式)
@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
"""全局异常捕获"""
logger.exception("Unhandled exception")
return JSONResponse(
status_code=500,
content={
"code": 500,
"message": "服务器内部错误",
"data": None,
"detail": {"error": str(exc)} if settings.DEBUG else None,
},
)
# 健康检查
@app.get("/health", tags=["System"])
async def health_check():
"""服务健康检查"""
return ApiResponse(
code=200,
data={
"status": "healthy",
"version": settings.APP_VERSION,
"environment": settings.ENV,
},
message="服务运行正常",
)
# 根路由
@app.get("/", tags=["System"])
async def root():
"""API 根路径"""
return ApiResponse(
code=200,
data={
"name": settings.APP_NAME,
"version": settings.APP_VERSION,
"docs": "/docs" if settings.DEBUG else None,
},
message="美家卡智影 API 服务",
)
return app
# 创建应用实例
app = create_app()
def main():
"""入口函数(用于命令行启动)"""
uvicorn.run(
"app.main:app",
host=settings.HOST,
port=settings.PORT,
workers=settings.WORKERS if not settings.DEBUG else 1,
reload=settings.DEBUG,
log_level=settings.LOG_LEVEL.lower(),
)
if __name__ == "__main__":
main()
# test