# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## 项目概述 美家卡智影 (Meijiaka AI Video) - AI 视频创作平台。一个 AI 驱动的桌面应用,采用 **Tauri + React + FastAPI** 混合架构,用户可以通过 AI 生成脚本、创建数字人视频,自动生成字幕,最终本地合成完整的营销视频。 ### 环境要求 | 组件 | 版本要求 | |------|----------| | Python | **3.13+** (代码使用 `|` 类型注解语法) | | Node.js | 20+ | | Rust | 1.70+ | | Docker | 20+ (可选,用于数据库) | 核心设计理念:**轻量云账号 + 全本地业务数据** - 云端只存储用户认证和使用日志,所有项目/脚本/媒体都存在用户本地。 ## 架构 ### 混合架构 - **FastAPI 后端**: 处理 AI 模型调用、用户认证、API 服务 - **Tauri + React 前端**: 桌面 UI,React 负责渲染,Tauri 提供系统能力 - **Rust 后端**: 通过 Tauri IPC 处理本地操作(FFmpeg 视频处理、文件系统访问) ### 存储策略 核心设计理念:**轻量云账号 + 全本地业务数据** - 云端只存储用户认证和使用日志,所有项目/脚本/媒体都存在用户本地。 - **云端**: PostgreSQL 只存储 2 张表:`users` (用户账户)、`model_usage_logs` (用量统计) - `avatars` 表已废弃:数字人名片元数据现在纯本地存储 `avatars.json` - **本地**: JSON 文件存储项目/脚本/分镜数据、数字人元数据,用户磁盘存储媒体文件,FFmpeg 处理视频合成 - **缓存/队列**: Redis + Async Engine Scheduler 处理异步任务 ### 混合通信模式 | 通信模式 | 使用场景 | 前端调用方式 | |---------|---------|------------| | HTTP → FastAPI | AI 生成、认证、配置管理 | `client.get/post/put/delete()` | | Tauri IPC → Rust | FFmpeg 视频处理、本地文件系统 | `ipc.request()` 或直接 `invoke()` | **通信模块**: - `tauri-app/src/api/client.ts` - HTTP 客户端,自动处理 camelCase/snake_case 转换 - `tauri-app/src/api/ipc.ts` - IPC 客户端 - `tauri-app/src/api/modules/localStorage.ts` - 本地项目存储(走 IPC) - `tauri-app/src/api/modules/videoComposite.ts` - 视频合成(走 IPC) ### AI Provider 架构 后端 AI 模块采用多 Provider 设计: - `app/ai/model_router.py` - 模型路由器,支持自动降级 - `app/ai/providers/base.py` - 抽象基类 - `app/ai/providers/*` - 具体实现(OpenAI、火山引擎、KlingAI 等) - `app/ai/prompts/` - 提示词模板文件 支持的 AI 平台:火山方舟(推荐)、OpenAI、百度文心一言、阿里云通义千问、KlingAI(数字人视频生成)。 模型配置文件:`python-api/config/ai_models.yaml`(支持热重载) ### Token 管理 外部 API 认证 Token 使用 `app/core/token_manager.py` 统一管理: - Token 缓存(避免重复生成) - 自动刷新(Token 即将过期时自动刷新) - 并发安全(双重检查锁定) - 支持 JWT、OAuth2 等多种策略 ### 数据流 1. **脚本生成**: 用户输入 → FastAPI AI 代理 → 标准化输出 → 前端保存到本地 JSON 2. **数字人视频**: 后端调用 KlingAI API → 返回视频 URL → 前端下载并本地存储 3. **视频合成**: 前端 → Tauri IPC → Rust 后端 → FFmpeg → 渲染最终视频文件 ### 本地存储结构(用户机器) ``` ~/Documents/Meijiaka/ ├── config.json # 全局应用配置 ├── projects/ │ └── {project_id}/ │ ├── meta.json # 项目元数据 │ ├── segments.json # 脚本/分镜数据 │ └── assets/ # 媒体文件 ├── avatars/ │ └── {avatar_id}/ │ ├── meta.json # 数字人名片配置 │ └── source.mp4 # 源视频 └── cache/ # 临时文件 ``` ## 目录结构 ``` ai-meijiaka/ ├── python-api/ # FastAPI 后端服务 │ ├── app/ │ │ ├── api/v1/ # REST API 端点 │ │ ├── ai/ # AI 模型路由和 Provider │ │ ├── ai/prompts/ # 提示词模板文件 │ │ ├── core/ # 安全、配置、异常处理 │ │ ├── db/ # 数据库配置 │ │ ├── models/ # SQLAlchemy 数据模型 │ │ ├── schemas/ # Pydantic 验证模型 │ │ ├── services/ # 业务逻辑和 AI 服务代理 │ │ ├── scheduler/ # Async Engine 统一异步调度器 │ │ ├── config.py # 配置管理 │ │ └── main.py # 应用入口 │ ├── config/ # AI 模型配置(YAML) │ ├── tests/ # pytest 测试套件 │ ├── scripts/ # 管理和测试脚本 │ └── docker-compose.yml # Docker 服务编排 │ ├── tauri-app/ # Tauri 桌面应用 │ ├── src/ # React 前端源码 │ │ ├── api/ # API 客户端和类型 │ │ │ ├── adapters/ # 前后端字段差异适配 │ │ │ ├── generated/ # OpenAPI 自动生成类型 │ │ │ └── modules/ # API 模块封装 │ │ ├── components/ # 可复用 React 组件 │ │ ├── pages/ # 页面组件(路由) │ │ ├── store/ # Zustand 全局状态管理 │ │ ├── hooks/ # 自定义 React Hooks │ │ └── utils/ # 前端工具函数 │ ├── src-tauri/ # Rust 后端 │ │ ├── src/ │ │ │ ├── lib.rs # Tauri 应用入口,命令注册 │ │ │ ├── commands/ # 按领域拆分的命令模块 │ │ │ │ ├── asset.rs # 资源文件操作 │ │ │ │ ├── auth_state.rs # 认证状态管理 │ │ │ │ ├── avatar.rs # 数字人头像管理 │ │ │ │ ├── product.rs # 产品相关 │ │ │ │ └── project.rs # 项目存储操作 │ │ │ ├── storage/ # 存储引擎分层 │ │ │ │ ├── mod.rs # 模块导出 │ │ │ │ ├── paths.rs # 路径计算 │ │ │ │ ├── engine.rs # 核心存储引擎(原子写+文件锁) │ │ │ │ ├── auth.rs # 认证存储 │ │ │ │ ├── project.rs # 项目存储 │ │ │ │ ├── avatar.rs # 头像存储 │ │ │ │ └── cache.rs # 缓存存储 │ │ │ ├── ffmpeg_cmd.rs # FFmpeg 命令封装 │ │ │ ├── video_processing.rs # 视频合成逻辑 │ │ │ ├── api_proxy.rs # Python API 代理 │ │ │ ├── avatar_cache.rs # 头像视频缓存管理 │ │ │ └── utils.rs # 通用工具函数 │ │ ├── binaries/ # 嵌入的 FFmpeg 可执行文件 │ │ └── Cargo.toml # Rust 依赖配置 │ └── package.json # NPM 依赖和脚本 │ └── docs/ # 开发文档 ``` ## 常用命令 ### 后端 (python-api) 项目使用 `uv` 进行依赖管理,并提供了 `Makefile` 封装常用命令: ```bash cd python-api # 使用 uv 和 Makefile(推荐) make dev # 安装开发依赖并配置 pre-commit make docker-run # 使用 Docker Compose 启动所有服务(db, redis, api, scheduler) make run # 启动 FastAPI 开发服务器 make scheduler # 启动 Async Engine Scheduler make lint # 运行代码检查 (ruff + mypy) make format # 格式化代码 make test # 运行所有测试 make security # 运行安全扫描 (bandit + pip-audit) # 手动方式 # 安装依赖 python -m venv venv && source venv/bin/activate pip install -e ".[dev]" # 启动 PostgreSQL + Redis(必需) docker-compose up -d db redis # 启动 FastAPI 开发服务器 uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 # 启动 Async Engine Scheduler(另开终端) python -m app.scheduler.main # 代码质量 black app/ # 格式化代码(行宽 100) ruff check app/ # 代码检查 mypy app/ # 严格类型检查 bandit -c pyproject.toml -r app/ # 安全扫描 pip-audit # 依赖漏洞检测 python scripts/check_config_architecture.py # 检查配置架构一致性 # 导出 OpenAPI 文档到前端 python3 -c " import logging logging.disable(logging.WARNING) from app.main import app import json print(json.dumps(app.openapi(), indent=2, ensure_ascii=False)) " > ../tauri-app/src/api/generated/openapi.json # 测试 pytest # 运行所有测试 pytest tests/test_script.py -v # 运行单个测试文件 pytest --cov=app # 覆盖率报告 # Docker docker-compose up -d # 启动所有服务(db, redis, api, scheduler) # 端口占用检查 lsof -i :8080 # 检查 8080 端口占用 ``` **可用 Makefile 命令:** | 命令 | 用途 | |------|------| | `make help` | 显示帮助信息 | | `make install` | 安装生产依赖(使用 lock 文件)| | `make dev` | 安装开发依赖并配置 pre-commit | | `make update-lock` | 更新 requirements.lock | | `make lint` | 运行代码检查 (ruff + mypy) | | `make format` | 格式化代码 (black + ruff) | | `make format-check` | 检查代码格式(不修改)| | `make test` | 运行测试 | | `make test-cov` | 运行测试并生成覆盖率报告 | | `make security` | 运行安全扫描 | | `make run` | 启动开发服务器 | | `make scheduler` | 启动 Async Engine Scheduler | | `make docker-run` | Docker Compose 启动全部服务 | | `make docker-down` | 停止 Docker 服务 | | `make clean` | 清理缓存文件 | | `make ci` | 运行所有 CI 检查 | ### 前端 (tauri-app) ```bash cd tauri-app # 安装依赖 npm install # 开发 npm run dev # 仅启动 Vite(不打开 Tauri 窗口) npm run tauri dev # 完整 Tauri 桌面开发模式 # 构建 npm run build # 前端生产构建 npm run tauri build # 打包桌面应用(.dmg/.exe/.AppImage) # 代码质量 npm run lint # ESLint 检查 JS/TS npm run lint:fix # ESLint 自动修复 npm run format # Prettier 格式化代码 npm run stylelint # CSS 检查 # 测试 npm run test # 运行 Vitest npm run test:coverage # 覆盖率报告 npm run test:ui # 打开 Vitest UI # 类型生成 npm run gen:api # 从 OpenAPI schema 生成 TypeScript 类型 ``` ### 数据库迁移 项目使用 Alembic 进行数据库迁移: ```bash cd python-api # 生成新迁移(修改模型后) alembic revision --autogenerate -m "description" # 应用迁移 alembic upgrade head # 回滚迁移 alembic downgrade -1 ``` ### 开发提示 - **Tauri 调试**: 使用 `npm run tauri dev` 时,Rust 后端日志在终端输出,前端日志在浏览器控制台 - **本地项目路径**: 项目数据保存在 `~/Documents/Meijiaka/projects/{project_id}/` - **配置修改**: AI 模型配置 `python-api/config/ai_models.yaml` 支持热重载,无需重启服务 - **类型同步**: 修改后端 API 后,记得重新导出 OpenAPI 并运行 `npm run gen:api` - **Async Engine Scheduler**: 系统使用 Slot-Based Scheduler 统一调度所有第三方异步任务: - `video` - 数字人视频生成(18 slots) - `avatar_clone` - 形象克隆(2 slots) - `image` - 图片生成(9 slots) - `subtitle` - 字幕生成(5 slots) - `copy` - 文案提取(5 slots) - **任务状态**: 任务状态唯一真相源为后端 Redis,`taskStore` 不持久化,启动时从后端 `GET /tasks` 查询 - **项目数据**: 项目元数据和分镜数据通过 IPC 显式写入本地文件,不通过 Zustand persist 持久化 - **字幕渲染**: 使用 `assjs` 库进行 ASS/SSA 字幕预览渲染,WASM 和 Worker 文件通过 Vite 插件复制到 `public/` 目录,修改资源路径后需要检查插件配置 ## 开发规范 ### 后端 (Python) - **格式化**: Black (行宽: 100) - **检查**: Ruff - **类型**: MyPy (strict 模式) - **架构**: API → Service → CRUD → Model,禁止跨层调用 - **数据库**: 始终使用异步 SQLAlchemy,事务在 API 层控制 - **AI 集成**: 无论使用什么提供者,输出 Schema 必须保持一致,在 Service 层标准化 - **提示词**: 所有提示词放在 `app/ai/prompts/` 单独文件,不硬编码 - **配置管理**: 所有配置通过 `from app.config import get_settings` 读取,禁止直接使用 `os.getenv()`,所有配置项必须在 `Settings` 类中定义 ### 配置管理强制规范 **架构层级:** ``` .env (Layer 1) ──→ Settings (Layer 2) ──→ 服务层 (Layer 3) ↑ 唯一配置出口 ``` **强制规则:** - **所有服务**必须使用 `from app.config import get_settings` 读取配置 - **禁止**在服务层、API 层直接使用 `os.getenv()` 或 `os.environ.get()` - **所有配置项**必须在 `app/config.py` 的 `Settings` 类中定义 - **敏感信息**(API Keys、Secrets)必须通过环境变量注入 - **业务默认值**可以硬编码在 `Settings` 中 **添加新配置流程:** 1. 在 `app/config.py` 的 `Settings` 类中添加字段定义 2. 使用 `Field(default=..., description="...")` 提供默认值和说明 3. 敏感信息使用 `str | None = None` 类型 4. 更新 `.env.example` 文档 ### Rust (Tauri 后端) - **格式化**: `rustfmt`(默认配置) - **检查**: `cargo clippy`(零警告) - **模块组织**: 命令按领域拆分到 `src/commands/{domain}.rs`,在 `lib.rs` 中注册 - **存储分层**: 存储逻辑按领域拆分到 `src/storage/{domain}.rs` - **命令参数**: Tauri IPC 命令必须使用 Args 结构体接收参数: ```rust #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct SaveProjectMetaArgs { pub project_id: String, pub data: serde_json::Value, } ``` - **禁止**: 命令函数直接使用 camelCase 参数名(会产生 `non_snake_case` 警告) ### 本地数据存储规范(Tauri/Rust) **分层架构:** ``` Layer 1: 页面组件(Pages/Components) — 只操作 Store,禁止直接调用 IPC save Layer 2: Zustand Store(内存状态) — Immer 不可变更新 Layer 3: PersistManager(持久化协调) — debounce 批量、flush 强制、错误上报 Layer 4: API 模块(localStorageApi 等) — 类型安全的 IPC 调用封装 Layer 5: Rust StorageEngine(文件系统) — sanitize + atomic_write + file_lock ``` **强制规范:** 1. **禁止页面组件直接调用 `localProjectApi.saveXxx()`** — 必须通过 Store → PersistManager 2. **禁止 Rust 命令函数直接 `fs::write`** — 必须通过 `StorageEngine::atomic_write_json` 3. **所有 ID 参数必须 `sanitize_id`** — 路径参数白名单校验(`[a-zA-Z0-9_-]+`) 4. **所有 JSON 写操作必须原子化** — 临时文件 + `fs::rename` 5. **RMW 操作必须加锁** — `with_file_lock` 或 Mutex **StorageEngine 核心能力:** - `sanitize_id(id)` — ID 白名单校验,防御路径遍历 - `sanitize_filename(name)` — 提取纯文件名,拒绝目录组件 - `atomic_write_json(path, value)` — 先写 `.tmp` 再 rename,防崩溃截断 - `with_file_lock(path, f)` — 文件锁保护 RMW 操作 - `read_json(path)` — 安全读取,文件不存在返回 `None`,损坏返回 `Err` ### 前端 (TypeScript/React) - **类型**: 严格 TypeScript 模式 - **组件**: 函数组件 + Hooks - **状态管理**: Zustand 管理全局状态,Immer 处理不可变更新 - **数据获取**: SWR 缓存,自动 localStorage 降级 - **API 客户端**: 从后端 OpenAPI schema 自动生成类型 - **命名风格**: camelCase(自动与后端 snake_case 转换) - **本地存储**: 项目数据通过 Tauri IPC 保存到 `~/Documents/Meijiaka/projects/` ### 提交规范 ``` feat: 新功能 fix: 修复 docs: 文档 refactor: 重构 test: 测试 chore: 构建/工具 ``` ## 环境配置 ### 后端 (.env) ```bash # 数据库 DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/meijiaka REDIS_URL=redis://localhost:6379/0 # JWT 认证 SECRET_KEY=your-secret-key-here ACCESS_TOKEN_EXPIRE_MINUTES=10080 # AI 服务凭证 VOLCENGINE_API_KEY=your-volcengine-key VOLCENGINE_CAPTION_APPID=your-caption-appid VOLCENGINE_CAPTION_TOKEN=your-caption-token OPENAI_API_KEY=sk-your-openai-key KLINGAI_ACCESS_KEY=your-kling-access-key KLINGAI_SECRET_KEY=your-kling-secret-key # 七牛云存储(数字人视频持久化) QINIU_ACCESS_KEY=your-qiniu-access-key QINIU_SECRET_KEY=your-qiniu-secret-key QINIU_VIDEO_BUCKET=media-bucket QINIU_IMAGE_BUCKET=image-bucket # CORS 配置 CORS_ORIGINS=http://localhost:1420,http://127.0.0.1:1420,http://localhost:8080 ``` ## 服务地址 - API: http://localhost:8080/api/v1 - 文档: http://localhost:8080/docs - Vite 开发服务器: http://localhost:1420 ## 关键开发文件 | 文件 | 用途 | |------|------| | `python-api/app/main.py` | FastAPI 应用入口 | | `python-api/app/api/v1/*.py` | API 端点定义 | | `python-api/app/ai/model_router.py` | AI 模型路由和降级 | | `python-api/app/services/*.py` | 业务逻辑和 AI 响应标准化 | | `python-api/config/ai_models.yaml` | AI 模型配置 | | `tauri-app/src/App.tsx` | 主 React 组件 | | `tauri-app/src/api/client.ts` | 智能路由的 API 客户端 | | `tauri-app/src/store/projectStore.ts` | 项目状态管理 | | `tauri-app/src-tauri/src/lib.rs` | Rust 命令注册 | | `tauri-app/src-tauri/src/commands/project.rs` | 项目存储 IPC 命令 | | `tauri-app/src-tauri/src/storage/engine.rs` | 核心存储引擎(原子写+校验)| | `tauri-app/src-tauri/src/video_processing.rs` | FFmpeg 视频合成 | | `tauri-app/src-tauri/src/avatar_cache.rs` | 头像视频缓存管理 | | `python-api/app/core/token_manager.py` | API Token 缓存与自动刷新 | | `python-api/app/config.py` | Pydantic Settings 配置管理 | | `tauri-app/src/pages/VideoCreation/SubtitleBurning.tsx` | 字幕压制页面(ASS 字幕渲染) | | `tauri-app/src/hooks/useAssJsRenderer.ts` | assjs 字幕渲染 Hook | | `tauri-app/src/utils/assGenerator.ts` | ASS 字幕文件生成工具 | ## 额外开发文档 项目 `docs/` 目录包含详细的深度开发文档: | 文档 | 主题 | |------|------| | `docs/video-generation-flow.md` | 完整视频生成流程说明 | | `docs/kling-api-dev.md` | KlingAI 数字人视频 API 对接开发文档 | | `docs/app-update-system.md` | 应用自动更新系统设计 | | `docs/anytocopy-integration.md` | 版权素材集成说明 | | `docs/anytocopy-api.md` | 版权素材 API 文档 | | `docs/volcengine-video-caption-api.md` | 火山引擎字幕 API 对接 | | `docs/qiniu-kodo-python-sdk-guide.md` | 七牛云存储 SDK 集成指南 | | `docs/database-design.md` | 数据库设计文档 | | `docs/unified-async-scheduler.md` | 统一异步调度器设计 | | `docs/semantic-refactoring-plan.md` | 后端语义重构计划 | | `docs/migrate-avatars-to-local.md` | 头像数据迁移到本地说明 | ## 统一术语表(语义治理) 后端代码已完成语义治理重构,所有开发必须遵守统一术语表,禁止使用废弃别名。 整个后端划分为 6 个语义层级,每一层只使用属于该层的术语: ``` Layer 6: Presentation (API Schema / 前端适配层) → Segment, Human, Job, Script Layer 5: Application (API 路由) → Segment, Human, Job, Project Layer 4: Orchestration (Scheduler / SlotManager) → Job, JobRecord, Slot, Handler Layer 3: Domain (Service / 业务逻辑) → Segment, Human, VideoComposition, Caption Layer 2: Adapter (Provider Client) → KlingJob, KlingElement, VolcJob, ProviderTaskId Layer 1: Infrastructure (DB / Redis / HTTP) → 底层技术术语 ``` ### 术语对照表 | 业务概念 | 官方术语 | 使用层级 | 禁止使用的别名 | |---------|---------|---------|--------------| | 视频分镜 | `Segment` | Layer 3-6 | `shot`, `scene_desc` | | 数字人形象 | `Human` / `Avatar` | Layer 3-6(DB 用 `avatar`,API 用 `human_id`) | `element`, `character` | | 调度器工作单元 | `Job` | Layer 4 | `task` | | 供应商侧任务 | `ProviderJob` | Layer 2 | `kling_task`, `volc_task` | | 供应商任务 ID | `provider_task_id` | Layer 2-4 | `kling_task_id`, `video_task_id`, `image_task_id` | | 分镜状态 | `SegmentStatus` | Layer 3-4 | 裸字符串 | | 调度器状态 | `JobStatus` | Layer 4 | 裸字符串 | | 形象克隆状态 | `AvatarCloneStatus` | Layer 3 | 裸字符串 | | Kling 原始状态 | `KlingTaskStatus` | **Layer 2 仅限** | 泄漏到 Layer 3+ | ### 分层禁令 1. **API 层 (`app/api/v1/`)**:禁止出现 `element_id`, `kling_task_id`, `shot_type`, `omni` 2. **Scheduler 层 (`app/scheduler/`)**:禁止出现 `task_id`(应为 `job_id`),禁止构造供应商 prompt 语法 3. **Service 层 (`app/services/`)**:禁止出现 `<<>>` 等供应商专用语法 4. **Provider 层 (`app/ai/providers/`)**:允许使用 `element_id`, `kling_task_id`, `KlingTaskStatus` ### 类型禁令 - 跨层传递的接口禁止裸用 `dict[str, Any]`。`params`、`result`、`changes` 等字段必须使用 Pydantic 模型或 TypedDict - 状态字段禁止使用裸字符串,必须使用对应的 `StrEnum` - CRUD 层 `obj_in` 禁止裸字典,必须使用 `CreateSchema` / `UpdateSchema`