Files
mcn-short-video/project/AI创作平台toc/ENGINEERING_BLUEPRINT.md
T

27 KiB
Raw Blame History

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 讨论
  1. WorkBuddy 产出本方案 → Trae 读者直接执行
  2. Trae 按 P0 → P1 → P2 顺序编码
  3. 每完成一个模块,前端 npm run dev 即时验证
  4. 后端 pytest + uvicorn --reload 同步验证
  5. 遇到技术选型/架构疑问 → 回 WorkBuddy 讨论
  6. 确定方案后继续在 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_