18 KiB
18 KiB
AGENTS.md — 美家卡智影
本文档面向 AI Coding Agent。项目主要使用中文进行注释和界面文案,文档亦以中文撰写。
项目概述
美家卡智影是一款面向桌面端的 AI 视频创作应用,采用"Python 后端 API + Tauri 桌面前端"的混合架构。
- 产品标识:
cn.meijiaka.ai-video/cn.meijiaka.ai-zy - 版本:
1.8.1 - 核心功能: AI 脚本生成、AI 配音合成(TTS)、声音复刻、视频生成(Vidu)、视频字幕生成、压制成片(FFmpeg)、项目本地持久化
技术栈总览
| 层级 | 技术 |
|---|---|
| 后端框架 | FastAPI (Python 3.13, 异步) |
| 数据库 | PostgreSQL 15+ + SQLAlchemy 2.0 (asyncpg) |
| 缓存/队列 | Redis 7.x |
| 异步调度 | 自研 Async Engine(Slot Scheduler) |
| 桌面壳 | Tauri v2 (Rust) |
| 前端框架 | React 19 + TypeScript |
| 前端构建 | Vite 7 |
| 状态管理 | Zustand 5 + Immer 11 |
| 路由 | react-router-dom |
| 数据请求 | 自研智能路由客户端 + SWR |
| 测试(后端) | pytest + pytest-asyncio |
| 测试(前端) | Vitest 4 + jsdom + @testing-library/react |
| 部署 | Docker + Docker Compose + Nginx |
仓库结构
本仓库为 Monorepo,包含两个主要子项目:
.
├── python-api/ # Python 后端 API
├── tauri-app/ # Tauri 桌面前端
├── docs/ # 项目文档(架构设计、API 对接指南等)
├── scripts/ # 辅助脚本
├── .gitlab-ci.yml # GitLab CI/CD 配置
└── AGENTS.md # 本文档
python-api/ 目录结构
python-api/
├── app/ # 主应用代码
│ ├── api/v1/ # API 路由(按领域拆分:auth, script, voice, vidu, caption, tasks, upload, materials, system)
│ ├── core/ # 核心工具(配置加载、安全、异常、Redis 客户端、健康检查)
│ ├── db/ # 数据库配置与会话管理
│ ├── models/ # SQLAlchemy ORM 模型(BaseModel 提供 UUID 主键 + 时间戳)
│ ├── schemas/ # Pydantic Schema(请求/响应校验)
│ ├── services/ # 业务逻辑层
│ ├── scheduler/ # Async Engine 异步任务调度(Slot Manager + Task Registry + Handlers)
│ ├── ai/ # AI 模型封装(providers: volcengine, vidu, generic_llm)
│ ├── crud/ # 数据库 CRUD 封装
│ ├── config.py # Pydantic Settings 配置管理
│ └── main.py # FastAPI 应用入口(含 lifespan 管理)
├── config/ # 运行时配置文件(platform-config.yaml, materials.json)
├── alembic/ # 数据库迁移脚本
├── nginx/ # Nginx 反向代理配置(含 acme.sh SSL 证书脚本)
├── Dockerfile # 多阶段构建镜像(builder + production)
├── docker-compose.prod.yml # 生产环境编排
├── docker-compose.test.yml # 测试环境编排
├── pyproject.toml # Python 依赖与工具配置(black, ruff, mypy, pytest, bandit)
├── requirements.lock # 锁定依赖(uv pip compile 生成)
├── uv.lock # uv 锁定文件
├── Makefile # 常用开发命令
└── .pre-commit-config.yaml # Git 钩子配置
tauri-app/ 目录结构
tauri-app/
├── src/ # React 前端源码
│ ├── api/ # API 客户端与模块
│ │ ├── client.ts # 智能路由客户端(HTTP / IPC 自动选择,camelCase ↔ snake_case 自动转换)
│ │ ├── generated/ # OpenAPI 生成的 TypeScript 类型
│ │ └── modules/ # 按领域拆分的 API 模块
│ ├── components/ # 可复用组件(PascalCase 文件夹)
│ ├── pages/ # 页面级组件(PascalCase 文件夹)
│ ├── store/ # Zustand 状态管理(含 __tests__)
│ ├── hooks/ # 自定义 React Hooks
│ ├── utils/ # 工具函数
│ ├── styles/ # CSS 变量与全局样式
│ └── __tests__/setup.ts # Vitest 全局 setup(mock localStorage / Tauri API)
├── src-tauri/ # Rust 后端源码
│ ├── src/
│ │ ├── main.rs # 程序入口
│ │ ├── lib.rs # Tauri Builder、Command 定义、公共类型
│ │ ├── ffmpeg_cmd.rs # FFmpeg 命令封装
│ │ ├── video_processing.rs # 压制成片业务逻辑
│ │ ├── api_proxy.rs # Python API 代理
│ │ ├── auth.rs # 认证命令
│ │ ├── avatar_cache.rs # 头像缓存
│ │ ├── storage/ # 本地存储引擎(项目、认证、配置、头像等)
│ │ ├── commands/ # Tauri IPC 命令(按领域拆分)
│ │ └── utils.rs # 通用工具
│ ├── Cargo.toml # Rust 依赖
│ ├── tauri.conf.json # Tauri 应用配置(窗口、CSP、打包、sidecar)
│ └── binaries/ # FFmpeg / ffprobe sidecar 二进制
├── package.json # Node 依赖与脚本
├── vite.config.ts # Vite 配置(端口 1420)
├── vitest.config.ts # 测试配置
├── tsconfig.json # TypeScript 主配置(strict: true)
├── eslint.config.js # ESLint 配置
├── .prettierrc # Prettier 配置
└── .stylelintrc.json # Stylelint 配置
运行时架构
采用混合通信架构:
- 纯数据 API(脚本、TTS、字幕、视频生成、任务查询等)→ 前端通过 HTTP 直连 Python 后端。
- 脚本/TTS/字幕/视频生成统一走异步任务调度(
POST /tasks/{task_type}+ 轮询/tasks/{task_id}),由 Scheduler 独立进程消费。
- 脚本/TTS/字幕/视频生成统一走异步任务调度(
- 需要本地系统能力(FFmpeg 压制成片、文件系统读写、项目本地持久化、认证状态存储)→ 走 Tauri IPC → Rust 层 处理。
新增纯数据 API 时,无需修改 Rust 代码,直接在
tauri-app/src/api/modules/下使用client.post/get调用即可。只有涉及本地系统能力的 API 才需要在 Rust 层新增#[tauri::command]。
服务拓扑(生产/测试环境)
┌─────────────┐ HTTP ┌─────────────────┐
│ Tauri │ ────────────▶ │ Nginx (SSL) │
│ 桌面端 │ │ 反向代理 │
└─────────────┘ └────────┬────────┘
│ │
│ IPC (Rust) │
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ FFmpeg │ │ FastAPI (8000) │
│ Sidecar │ │ - API 路由 │
│ 本地文件系统 │ │ - 业务逻辑 │
└─────────────┘ └────────┬────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌────────┐ ┌─────────┐ ┌──────────┐
│PostgreSQL│ │ Redis │ │ AI 服务商 │
└────────┘ └─────────┘ └──────────┘
│
▼
┌───────────────┐
│ Async Engine │
│ Scheduler │
└───────────────┘
构建与开发命令
后端(python-api/)
cd python-api
# 安装开发依赖(使用 uv)
make dev
# 启动开发服务器
make run # uvicorn --reload --port 8000
# 启动异步调度器(另开终端)
make scheduler # python -m app.scheduler.main
# 代码质量
make lint # ruff check + mypy
make format # black + ruff --fix
make format-check # 检查格式(不修改)
make lint-semantic # 语义层禁词检查(防止供应商术语泄漏)
# 测试
make test # pytest -v
make test-cov # pytest + 覆盖率报告
# 安全扫描
make security # bandit + pip-audit
# CI 全量检查
make ci # format-check + lint + lint-semantic + test + security
# Docker 操作
make docker-run # 启动 api + scheduler(共享外部 db/redis)
make docker-rebuild # 强制重建
make docker-stop # 停止(保留 db/redis)
make docker-logs # 查看日志
# 数据库迁移
alembic revision --autogenerate -m "描述"
alembic upgrade head
前端(tauri-app/)
cd tauri-app
# 前端开发服务器(Vite,端口 1420)
npm run dev
# 生产构建(tsc + vite build)
npm run build
# Tauri 开发(启动 Rust + 前端)
npm run tauri dev
# Tauri 生产打包
npm run tauri build
# 测试
npm run test # Vitest
npm run test:ui # Vitest UI 模式
npm run test:coverage # 覆盖率
# 代码质量
npm run lint # ESLint
npm run lint:fix # ESLint --fix
npm run format # Prettier
npm run format:check # Prettier --check
npm run stylelint # Stylelint
npm run stylelint:fix # Stylelint --fix
# OpenAPI 类型生成
npm run gen:api # 根据 openapi.json 生成 TypeScript 类型
代码风格与约定
命名规范
| 类型 | 规范 | 示例 |
|---|---|---|
| 组件/页面文件夹 | PascalCase | VideoCreation/, ErrorBoundary/ |
| Store/Hooks/API 文件 | camelCase | authStore.ts, useProjectData.ts |
| 类型/接口 | PascalCase | ApiResponse<T> |
| Python 模块/函数 | snake_case | script_handler.py, get_settings() |
| Python 类 | PascalCase | AsyncEngine, BaseModel |
| 常量 | UPPER_SNAKE_CASE | PYTHON_API_BASE_URL |
注释语言
- 项目内统一使用中文注释。
- 关键架构决策需在代码中以多行注释说明(参考
python-api/app/scheduler/engine.py和tauri-app/src/api/client.ts顶部注释)。
Python 代码质量
- 格式化: black (line-length: 100)
- 检查: ruff (select: E, F, I, N, W, UP, B, C4, SIM)
- 类型检查: mypy(对
app.schemas.*,app.crud.*,app.scheduler.handlers.*启用严格模式) - 安全扫描: bandit + pip-audit
- 依赖管理: uv(
requirements.lock必须与实际依赖同步,pre-commit 会检查)
TypeScript 配置
strict: true已开启。noUnusedLocals: true、noUnusedParameters: true已开启。jsx: "react-jsx",无需手动引入React。- 路径别名
@/映射到./src。
状态管理约定(前端)
- 使用 Zustand + Immer 进行不可变更新。
projectStore使用自定义persist存储,将项目数据通过 Tauri IPC 持久化到本地文件系统(app_config_dir/current_project.json),而不是 localStorage。- 其他 Store(如
authStore、settingsStore)使用localStorage做持久化。
API 开发流程
- 判断是否需要本地能力(FFmpeg、文件系统、系统调用)。
- 不需要 → 直接在
tauri-app/src/api/modules/使用client.get/post/put/delete调用 Python HTTP API。 - 需要 → 将 endpoint 加入
tauri-app/src/api/client.ts的 IPC 处理逻辑,并在tauri-app/src-tauri/src/commands/或lib.rs中实现对应的#[tauri::command]处理器。
语义层防护网(后端)
Makefile 中 lint-semantic 目标会检查以下规则:
- API 层禁止使用
element_id作为字段/参数名(应使用provider_element_id)。 - Scheduler 层统一使用
task命名(TaskRegistry、task_id、task:Redis key 前缀),禁止混用job。
测试说明
后端测试
- 框架: pytest + pytest-asyncio(asyncio_mode: auto)
- 覆盖率: pytest-cov
- 当前状态: 后端尚无正式的
tests/目录,测试用例待补充。
前端测试
- 框架: Vitest(globals: true,environment:
jsdom) - 组件测试:
@testing-library/react+@testing-library/jest-dom - 文件位置:
- 全局 setup:
src/__tests__/setup.ts - Store 测试:
src/store/__tests__/*.test.tsx - 组件/页面测试: 建议放在被测文件同目录或
__tests__子目录中
- 全局 setup:
- Mock 策略:
setup.ts中已全局 mocklocalStorage、@tauri-apps/api/core的invoke方法、window.__TAURI_INTERNALS__。每个测试后自动调用vi.clearAllMocks()。
安全与部署
后端安全
- JWT 认证:
SECRET_KEY生产环境必须设置为强随机字符串(至少 32 位),否则应用启动时会抛出ValueError。 - CORS: 生产环境若包含
localhost会触发RuntimeWarning。 - 依赖安全:
aiohttp>=3.13.4和orjson>=3.11.0为强制最低版本(修复 CVE)。 - 输入验证: 所有 API 入参通过 Pydantic Schema 校验。
- 数据库: 使用参数化查询(SQLAlchemy ORM),无直接 SQL 拼接。
前端安全
- CSP:
tauri.conf.json中已配置 Content Security Policy。 - Asset Protocol: 已启用,范围限定在
$APPLOCALDATA/**、$APPDATA/**、$APPCONFIG/**。
部署流程
测试环境(GitLab CI)
.gitlab-ci.yml 定义了 deploy-backend 任务:
- 在部署服务器拉取代码(
master分支触发)。 - 构建 api + scheduler 镜像(
docker-compose.test.yml)。 - 启动服务,健康检查
curl http://localhost:8081/health。 - 清理 7 天前的旧镜像。
生产环境
- 从环境变量或密钥管理注入配置。
docker compose -f docker-compose.prod.yml up -d --build- 外部提供 PostgreSQL 和 Redis(云数据库或自建集群)。
- Nginx 反向代理 + acme.sh SSL 证书。
外部二进制与 Sidecar
- FFmpeg / ffprobe 作为 sidecar 打包到 Tauri 应用(
bundle.externalBin)。 - Rust 层通过
tauri_plugin_shell的sidecar("ffmpeg")调用。 - 合成过程中解析 FFmpeg stderr 中的
time=字段,通过 Tauri Event 向前端发送进度。
环境变量(后端)
关键配置项见 python-api/.env.example:
| 变量 | 说明 | 默认值 |
|---|---|---|
DATABASE_URL |
PostgreSQL 连接字符串 | postgresql+asyncpg://postgres:postgres@localhost:5432/meijiaka_zy |
REDIS_HOST / REDIS_PORT / REDIS_DB |
Redis 连接信息 | localhost:6379:0 |
SECRET_KEY |
JWT 签名密钥 | 必须修改 |
CORS_ORIGINS |
允许的跨域来源 | http://localhost:1420,... |
VOLCENGINE_API_KEY |
火山方舟 API Key | - |
VIDU_API_KEY |
Vidu API Key | - |
QINIU_ACCESS_KEY / QINIU_SECRET_KEY |
七牛云存储密钥 | - |
APP_BASE_URL |
应用公网地址(第三方回调用) | 按 ENV 自动推断 |
配置变更策略
Python 的模块导入机制决定了运行时热替换配置是反模式,FastAPI/Pydantic 官方不推荐。测试与生产环境统一遵循以下策略:
| 场景 | 做法 | 说明 |
|---|---|---|
| 数值/业务规则配置 | 代码常量 | 如 SMS 验证码位数、过期时间等,不走 .env,防止运维随意修改 |
| 环境配置(密钥、URL 等) | .env 文件 |
变更后统一走 Docker 滚动重启,所有环境均不支持热重载 |
| 更新方式 | docker compose up -d --build |
测试/生产完全一致:docker-compose.test.yml 与 docker-compose.prod.yml 保持相同的重启策略 |
注意:reload_settings() 仅作为代码级工具保留(内部调试直接 import 调用),HTTP 接口已删除,测试与生产环境统一走 Docker 滚动重启更新配置。
数据库与迁移
- ORM: SQLAlchemy 2.0(异步,asyncpg 驱动)
- 迁移工具: Alembic
- 基础模型:
app.models.base.BaseModel提供 UUID 主键、created_at、updated_at - 当前模型:
User(用户/设备认证) - 迁移注意: Alembic 使用同步连接(psycopg2),会自动将
+asyncpg替换掉。
异步任务调度(Async Engine)
后端采用自研的统一异步任务调度引擎,核心概念:
- TaskRegistry: 基于 Redis 的任务注册表,维护 running / pending / finished 状态。
- SlotManager: 基于 Redis 的并发槽位管理,按 task_type 限制最大并发数,统一使用
acquire_ctx上下文管理器。 - AsyncHandler: 各领域的异步任务处理器(
script/tts/subtitle/video)。 - Engine Tick: 定时轮询所有 running 任务,批量查询状态、批量更新。
调度器需单独启动:make scheduler 或 python -m app.scheduler.main。
给 Agent 的快速检查清单
在修改代码前,建议确认以下事项:
- 新增 API 是否需要 Rust 层? 不需要则只改前端
src/api/modules/和后端app/api/v1/。 - 修改 Store 后是否影响持久化?
projectStore的partialize字段决定哪些状态会被保存到本地文件。 - 新增组件是否遵循 PascalCase 文件夹约定?
- 后端代码是否触发语义层禁词? 运行
make lint-semantic。 - 依赖变更后是否更新了 lock 文件? 运行
uv pip compile pyproject.toml -o requirements.lock。 - 测试是否通过? 前端运行
npm run test,后端运行make test。 - Tauri 配置变更后是否需要重新
tauri dev? 是的,tauri.conf.json或Cargo.toml变更后需重启 Tauri 进程。 - 修改 pyproject.toml 后 pre-commit 是否通过?
requirements.lock必须与 pyproject.toml 同步。