27 KiB
27 KiB
AI 短视频创作平台 — 工程骨架方案
本方案由 WorkBuddy 产出,交付给 Trae 执行。 定位:toC 产品,Python 后端 + React 前端,独立部署。
一、技术栈总览
| 层 | 技术 | 版本 | 角色 |
|---|---|---|---|
| 前端框架 | React | 19.x | UI 层 |
| 构建工具 | Vite | 6.x | 开发/打包 |
| 语言 | TypeScript | 5.x | 前端类型安全 |
| UI 组件 | shadcn/ui | latest | 原子组件库 |
| 样式 | Tailwind CSS | 4.x | 原子化样式 |
| 拖拽 | @dnd-kit | latest | 时间轴/素材拖拽 |
| 画布 | react-konva | latest | 预览画布/文字贴纸 |
| 状态管理 | zustand | 5.x | 编辑器状态 + 撤销重做 |
| 数据请求 | @tanstack/react-query | 5.x | 服务端状态/缓存 |
| 动画 | framer-motion | 11.x | 过渡动效 |
| 路由 | react-router | 7.x | 页面路由 |
| 表单 | react-hook-form + zod | latest | 表单校验 |
| 后端框架 | FastAPI | 0.115+ | REST API + WebSocket |
| ASGI 服务器 | uvicorn | latest | 生产级运行 |
| 数据库 | PostgreSQL + Redis | 16 / 7 | 持久化 + 缓存/队列 |
| ORM | SQLAlchemy 2.0 | 2.x | 数据库映射 |
| 任务队列 | Celery + Redis | 5.x | AI 异步生成 |
| 文件存储 | MinIO / S3 | — | 视频/素材存储 |
| AI 集成 | OpenAI SDK / 本地模型 | — | 脚本生成/视频处理 |
二、目录结构
ai-video-platform/
├── frontend/ # React 前端
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── tailwind.config.ts
│ ├── components.json # shadcn/ui 配置
│ ├── public/
│ │ └── favicon.svg
│ └── src/
│ ├── main.tsx # 入口
│ ├── App.tsx # 根组件 + 路由
│ ├── index.css # Tailwind 入口
│ ├── lib/
│ │ └── utils.ts # cn() 工具函数
│ ├── components/
│ │ ├── ui/ # shadcn/ui 组件(自动生成)
│ │ │ ├── button.tsx
│ │ │ ├── card.tsx
│ │ │ ├── dialog.tsx
│ │ │ ├── slider.tsx
│ │ │ ├── tabs.tsx
│ │ │ ├── dropdown-menu.tsx
│ │ │ ├─�� input.tsx
│ │ │ ├── textarea.tsx
│ │ │ ├── select.tsx
│ │ │ ├── toast.tsx
│ │ │ ├── tooltip.tsx
│ │ │ ├── sheet.tsx # 侧边栏
│ │ │ └── skeleton.tsx # 加载骨架
│ │ ├── layout/
│ │ │ ├── AppShell.tsx # 整体布局壳
│ │ │ ├── Sidebar.tsx # 左侧导航
│ │ │ └── Header.tsx # 顶部栏
│ │ ├── editor/ # 🔥 视频编辑器核心
│ │ │ ├── Timeline/
│ │ │ │ ├── Timeline.tsx # 时间轴容器
│ │ │ │ ├── Track.tsx # 单条轨道
│ �� │ │ ├── TrackItem.tsx # 轨道上的片段
│ │ │ │ ├── TimelineRuler.tsx # 时间标尺
│ │ │ │ └── TimelineControls.tsx # 缩放/播放控制
│ │ │ ├── Canvas/
│ │ │ │ ├── PreviewCanvas.tsx # 预览画布(react-konva)
│ │ │ │ ├── TextOverlay.tsx # 文字叠层
│ │ │ │ ├── StickerLayer.tsx # 贴纸层
│ │ │ │ └── VideoLayer.tsx # 视频画面层
│ │ │ ├── Toolbar/
│ │ │ │ ├── EditorToolbar.tsx # 编辑工具栏
│ │ │ │ ├── CropTool.tsx # 裁剪工具
│ │ │ │ └── TextTool.tsx # 文字工具
│ │ │ └── AssetPanel/
│ │ │ ├── AssetLibrary.tsx # 素材库面板
│ │ │ ├── MediaUploader.tsx # 上传组件
│ │ │ └── AIGenerator.tsx # AI 生成入口
│ │ ├── ai/ # AI 功能面板
│ │ │ ├── ScriptGenerator.tsx # 脚本生成
│ │ │ ├── VoiceGenerator.tsx # AI 配音
│ │ │ ├── SubtitleGenerator.tsx # 字幕生成
│ │ │ └── GenerationProgress.tsx # 生成进度(WebSocket)
│ │ └── common/
│ │ ├── LoadingSpinner.tsx
│ │ ├── ErrorBoundary.tsx
│ │ ├── EmptyState.tsx
│ │ └── ConfirmDialog.tsx
│ ├── pages/
│ │ ├── Home.tsx # 首页/项目列表
│ │ ├── Editor.tsx # 🔥 编辑器主页面
│ │ ├── Projects.tsx # 我的项目
│ │ ├── Templates.tsx # 模板市场
│ │ ├── Assets.tsx # 素材管理
│ │ └── Settings.tsx # 用户设置
│ ├── stores/ # zustand 状态
│ │ ├── editorStore.ts # 🔥 编辑器核心状态 + 撤销重做
│ │ ├── projectStore.ts # 项目元信息
│ │ ├── uiStore.ts # UI 状态(面板显隐等)
│ │ └── authStore.ts # 用户认证
│ ├── hooks/ # 自定义 hooks
│ │ ├── useEditor.ts # 编辑器逻辑入口
│ │ ├── useUndoRedo.ts # 撤销重做封装
│ │ ├── useWebSocket.ts # WebSocket 连接
│ │ ├── useMediaUpload.ts # 上传逻辑
│ �� └── useAIGeneration.ts # AI 生成调用
│ ├── api/ # API 层
│ │ ├── client.ts # axios/fetch 实例
│ │ ├── projects.ts # 项目 CRUD
│ │ ├── media.ts # 素材上传/管理
│ │ ├── generation.ts # AI 生成接口
│ │ └── auth.ts # 认证接口
│ ├── types/ # TypeScript 类型
│ │ ├── project.ts
│ │ ├── timeline.ts # 时间轴轨道类型
│ │ ├── media.ts
│ │ └── api.ts # API 响应类型
│ └── utils/
│ ├── time.ts # 时间格式化
│ └── file.ts # 文件工具
│
├── backend/ # Python 后端
│ ├── pyproject.toml # 项目管理(uv/poetry)
│ ├── alembic.ini # 数据库迁移配置
│ ├── Dockerfile
│ ├── docker-compose.yml # 本地开发环境
│ ├── app/
│ │ ├── __init__.py
│ │ ├── main.py # FastAPI 入口
│ │ ├── config.py # 配置管理(pydantic-settings)
│ │ ├── dependencies.py # 依赖注入
│ │ ├── api/
│ │ │ ├── __init__.py
│ │ │ ├── v1/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── router.py # 路由聚合
│ │ │ │ ├── auth.py # 认证
│ │ │ │ ├── projects.py # 项目 CRUD
│ │ │ │ ├── media.py # 素材上传
│ │ │ │ ├── generation.py # AI 生成
│ │ │ │ ├─�� templates.py # 模板
│ │ │ │ └── websocket.py # WebSocket 进度推送
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ ├── user.py
│ │ │ ├── project.py
│ │ │ ├── media.py
│ │ │ └── template.py
│ │ ├── schemas/
│ │ │ ├── __init__.py
│ │ │ ├── user.py
│ │ │ ├── project.py
│ │ │ ├── media.py
│ │ │ └── generation.py
│ │ ├── services/
│ │ │ ├── __init__.py
│ │ │ ├── project_service.py
│ │ │ ├── media_service.py
│ │ │ ├── script_generator.py # 🔥 AI 脚本生成
│ │ │ ├── voice_service.py # 🔥 AI 配音
│ │ │ ├── subtitle_service.py # 🔥 AI 字幕
│ │ │ ├── video_renderer.py # 🔥 视频合成
│ │ │ └── storage_service.py # 文件存储(MinIO/S3)
│ │ ├── tasks/ # Celery 异步任务
│ │ │ ├── __init__.py
│ │ │ ├── celery_app.py
│ │ │ ├── generation_tasks.py # AI 生成任务
│ │ │ └── media_tasks.py # 媒体处理任务
│ │ ├── core/
│ │ │ ├── __init__.py
│ │ │ ├── security.py # JWT / OAuth
│ │ │ ├── database.py # SQLAlchemy 引擎
│ │ │ └── exceptions.py
│ │ └── utils/
│ │ ├── __init__.py
│ │ └── helpers.py
│ ├── alembic/
│ │ ├── env.py
│ │ └── versions/
│ ├── tests/
│ │ ├── conftest.py
│ │ ├── test_projects.py
│ │ └── test_generation.py
│ └── requirements/
│ ├── base.txt
│ ├── dev.txt
│ └── prod.txt
│
└── docs/ # 文档
├── api-spec.md # API 接口说明
└── editor-architecture.md # 编辑器架构设计
三、前端核心依赖
// frontend/package.json (关键字段)
{
"name": "ai-video-platform",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint ."
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router": "^7.0.0",
"@tanstack/react-query": "^5.0.0",
"zustand": "^5.0.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.0",
"react-konva": "^18.2.0",
"konva": "^9.3.0",
"framer-motion": "^11.0.0",
"react-hook-form": "^7.53.0",
"@hookform/resolvers": "^3.9.0",
"zod": "^3.23.0",
"axios": "^1.7.0",
"clsx": "^2.1.0",
"tailwind-merge": "^2.5.0",
"class-variance-authority": "^0.7.0",
"lucide-react": "^0.460.0",
"sonner": "^1.7.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@vitejs/plugin-react": "^4.3.0",
"vite": "^6.0.0",
"typescript": "^5.6.0",
"tailwindcss": "^4.0.0",
"@tailwindcss/vite": "^4.0.0",
"eslint": "^9.0.0"
}
}
四、后端核心依赖
# backend/requirements/base.txt
# Web 框架
fastapi>=0.115,<1.0
uvicorn[standard]>=0.32,<1.0
python-multipart>=0.0.18 # 文件上传
# 数据库
sqlalchemy>=2.0,<3.0
asyncpg>=0.30,<1.0 # PostgreSQL 异步驱动
alembic>=1.14,<2.0 # 数据库迁移
pydantic>=2.10,<3.0
pydantic-settings>=2.6,<3.0
# 缓存 & 队列
redis>=5.2,<6.0
celery>=5.4,<6.0
# 认证
python-jose[cryptography]>=3.3,<4.0
passlib[bcrypt]>=1.7,<2.0
# 文件存储
boto3>=1.35,<2.0 # S3/MinIO
minio>=7.2,<8.0
# AI SDK
openai>=1.55,<2.0
# 工具
httpx>=0.28,<1.0
loguru>=0.7,<1.0
五、初始化步骤(逐条命令)
5.1 创建项目目录
mkdir ai-video-platform && cd ai-video-platform
5.2 前端初始化
# 1. Vite + React + TypeScript
npm create vite@latest frontend -- --template react-ts
cd frontend
npm install
# 2. 安装运行时依赖
npm install react-router @tanstack/react-query zustand @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities react-konva konva framer-motion react-hook-form @hookform/resolvers zod axios clsx tailwind-merge class-variance-authority lucide-react sonner
# 3. 安装开发依赖
npm install -D tailwindcss @tailwindcss/vite
# 4. 初始化 shadcn/ui
npx shadcn@latest init
# 选择:TypeScript / Neutral / CSS variables / Yes to all
# 5. 添加 shadcn 组件
npx shadcn@latest add button card dialog slider tabs dropdown-menu input textarea select toast tooltip sheet skeleton
5.3 Tailwind CSS v4 配置
// frontend/vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
},
'/ws': {
target: 'ws://localhost:8000',
ws: true,
},
},
},
})
/* frontend/src/index.css */
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
/* ... 暗色主题变量 ... */
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
5.4 后端初始化
cd backend
# 1. 创建虚拟环境
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. 安装依赖
pip install -r requirements/base.txt
# 3. 初始化 Alembic
alembic init alembic
# 修改 alembic/env.py 指向你的数据库
# 4. 创建初始迁移
alembic revision --autogenerate -m "init"
alembic upgrade head
# 5. 启动开发服务器
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
5.5 本地基础设施
# docker-compose.yml — 一键启动 PostgreSQL + Redis + MinIO
docker compose up -d
# backend/docker-compose.yml
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: video_dev
POSTGRES_PASSWORD: video_dev
POSTGRES_DB: ai_video_platform
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- miniodata:/data
volumes:
pgdata:
miniodata:
六、编辑器核心状态设计(zustand store)
这是整个前端的灵魂。交给 Trae 后,它是编码优先级最高的模块。
// frontend/src/stores/editorStore.ts
import { create } from 'zustand';
import { temporal } from 'zundo'; // zustand 撤销重做中间件
interface TrackItem {
id: string;
type: 'video' | 'image' | 'audio' | 'text' | 'sticker';
trackId: string;
startTime: number; // 毫秒
duration: number; // 毫秒
properties: {
x?: number;
y?: number;
width?: number;
height?: number;
rotation?: number;
opacity?: number;
text?: string;
fontSize?: number;
fontColor?: string;
// ... 其他属性
};
source: {
url?: string; // 媒体文件 URL
fileId?: string; // 后端文件 ID
};
}
interface EditorState {
// 项目元信息
projectId: string | null;
projectName: string;
// 轨道数据
tracks: TrackItem[];
// 播放状态
currentTime: number;
isPlaying: boolean;
duration: number;
// 选中状态
selectedItemIds: string[];
// 缩放
zoom: number; // 0.25 ~ 4.0
// 操作
addTrackItem: (item: TrackItem) => void;
removeTrackItem: (id: string) => void;
updateTrackItem: (id: string, updates: Partial<TrackItem>) => void;
moveTrackItem: (id: string, newStartTime: number, newTrackId?: string) => void;
setCurrentTime: (time: number) => void;
togglePlay: () => void;
selectItems: (ids: string[]) => void;
setZoom: (zoom: number) => void;
}
export const useEditorStore = create<EditorState>()(
temporal(
(set) => ({
projectId: null,
projectName: '未命名项目',
tracks: [],
currentTime: 0,
isPlaying: false,
duration: 60000,
selectedItemIds: [],
zoom: 1,
addTrackItem: (item) =>
set((s) => ({ tracks: [...s.tracks, item] })),
removeTrackItem: (id) =>
set((s) => ({
tracks: s.tracks.filter((t) => t.id !== id),
selectedItemIds: s.selectedItemIds.filter((sid) => sid !== id),
})),
updateTrackItem: (id, updates) =>
set((s) => ({
tracks: s.tracks.map((t) =>
t.id === id ? { ...t, ...updates } : t
),
})),
moveTrackItem: (id, newStartTime, newTrackId) =>
set((s) => ({
tracks: s.tracks.map((t) =>
t.id === id
? { ...t, startTime: newStartTime, trackId: newTrackId ?? t.trackId }
: t
),
})),
setCurrentTime: (time) => set({ currentTime: time }),
togglePlay: () => set((s) => ({ isPlaying: !s.isPlaying })),
selectItems: (ids) => set({ selectedItemIds: ids }),
setZoom: (zoom) => set({ zoom }),
}),
{ limit: 50 } // 保留 50 步撤销历史
)
);
七、后端 FastAPI 入口骨架
# backend/app/main.py
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1.router import api_router
from app.core.database import engine, Base
from app.config import settings
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时:创建表(开发环境)
# async with engine.begin() as conn:
# await conn.run_sync(Base.metadata.create_all)
yield
# 关闭时清理
await engine.dispose()
app = FastAPI(
title="AI 短视频创作平台",
version="0.1.0",
lifespan=lifespan,
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(api_router, prefix="/api/v1")
@app.get("/health")
async def health_check():
return {"status": "ok"}
WebSocket 进度推送
# backend/app/api/v1/websocket.py
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
router = APIRouter()
class ConnectionManager:
def __init__(self):
self.active_connections: dict[str, WebSocket] = {}
async def connect(self, task_id: str, websocket: WebSocket):
await websocket.accept()
self.active_connections[task_id] = websocket
def disconnect(self, task_id: str):
self.active_connections.pop(task_id, None)
async def send_progress(self, task_id: str, data: dict):
ws = self.active_connections.get(task_id)
if ws:
await ws.send_json(data)
manager = ConnectionManager()
@router.websocket("/ws/generation/{task_id}")
async def generation_progress(websocket: WebSocket, task_id: str):
await manager.connect(task_id, websocket)
try:
while True:
# 保持连接,等待 Celery 任务推送进度
await websocket.receive_text()
except WebSocketDisconnect:
manager.disconnect(task_id)
八、前后端联调约定
API 规范
| 事项 | 约定 |
|---|---|
| 接口前缀 | /api/v1/ |
| 请求格式 | application/json,上传用 multipart/form-data |
| 响应格式 | { "code": 0, "data": {...}, "message": "ok" } |
| 分页格式 | { "code": 0, "data": { "items": [...], "total": 100, "page": 1, "page_size": 20 } } |
| 错误码 | 0=成功,4xxx=客户端错误,5xxx=服务端错误 |
| WebSocket | /ws/generation/{task_id} — AI 生成进度实时推送 |
| 认证 | Bearer Token(JWT),Header: Authorization: Bearer <token> |
统一响应模型
# backend/app/schemas/common.py
from pydantic import BaseModel
from typing import Generic, TypeVar
T = TypeVar("T")
class ApiResponse(BaseModel, Generic[T]):
code: int = 0
message: str = "ok"
data: T | None = None
class PageResponse(BaseModel, Generic[T]):
items: list[T]
total: int
page: int
page_size: int
前端请求封装
// frontend/src/api/client.ts
import axios from 'axios';
const client = axios.create({
baseURL: '/api/v1',
timeout: 30000,
});
// 请求拦截:自动带 Token
client.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截:统一错误处理
client.interceptors.response.use(
(res) => res.data,
(err) => {
if (err.response?.status === 401) {
// 跳转登录
}
return Promise.reject(err);
}
);
export default client;
九、AI 生成核心功能拆解
按优先级排列,建议 Trae 按此顺序实现:
| 优先级 | 功能 | 前端关键组件 | 后端关键服务 | 复杂度 |
|---|---|---|---|---|
| P0 | AI 脚本生成 | ScriptGenerator.tsx(输入主题/关键词 → 流式显示脚本) |
script_generator.py(调用 LLM API,SSE 流式返回) |
⭐⭐ |
| P0 | 视频编辑器基础 | Timeline/ + Canvas/ + editorStore |
项目 CRUD、素材上传 | ⭐⭐⭐⭐⭐ |
| P1 | AI 配音 | VoiceGenerator.tsx(选择音色 → 试听 → 插入时间轴) |
voice_service.py(TTS API) |
⭐⭐⭐ |
| P1 | AI 字幕 | SubtitleGenerator.tsx(语音识别 → 字幕轨道展示) |
subtitle_service.py(ASR) |
⭐⭐⭐ |
| P2 | 模板市场 | Templates.tsx(模板浏览 → 一键套用) |
templates.py(模板 CRUD) |
⭐⭐ |
| P2 | 视频合成导出 | 导出进度条 | video_renderer.py(FFmpeg 合成 + Celery 异步) |
⭐⭐⭐⭐ |
十、开发工作流
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ WorkBuddy │────▶│ Trae │────▶│ Git Commit │
│ 方案 & 架构 │ │ 编码 & 调试 │ │ 版本管理 │
└──────────────┘ └──────────────┘ └──────────────┘
▲ │
└────────────────────────────────────────┘
遇到架构问题回 WorkBuddy 讨论
- WorkBuddy 产出本方案 → Trae 读者直接执行
- Trae 按 P0 → P1 → P2 顺序编码
- 每完成一个模块,前端
npm run dev即时验证 - 后端
pytest+uvicorn --reload同步验证 - 遇到技术选型/架构疑问 → 回 WorkBuddy 讨论
- 确定方案后继续在 Trae 编码
十一、交付清单
给 Trae 的第一阶段任务(建议一次不要超过 5 个文件):
frontend/package.json— 按第四节配置frontend/vite.config.ts— 按 5.3 节配置frontend/tailwind.config.ts— 按 5.3 节配置frontend/src/index.css— 按 5.3 节配置frontend/src/main.tsx— React 入口frontend/src/App.tsx— 路由 + 布局壳frontend/src/components/layout/AppShell.tsx— shadcn/ui 侧边栏 + 顶栏frontend/src/stores/editorStore.ts— 编辑器核心状态(第六节)frontend/src/pages/Home.tsx— 首页占位frontend/src/pages/Editor.tsx— 编辑器主��面占位backend/pyproject.toml— 项目配置backend/requirements/base.txt— 按第四节配置backend/app/main.py— 第七节完整代码backend/app/config.py— pydantic-settings 配置backend/app/core/database.py— SQLAlchemy 引擎backend/app/api/v1/router.py— 路由聚合backend/app/api/v1/websocket.py— WebSocket 进度推送backend/app/schemas/common.py— 统一响应模型backend/docker-compose.yml— 本地基础设施
---
_方案版本:v1.0 | 产出日期:2026-07-31 | 产出工具:WorkBuddy | 执行工具:Trae_