# editingProject **Repository Path**: kerry008/editing-project ## Basic Information - **Project Name**: editingProject - **Description**: 自动化剪辑脚本 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-30 - **Last Updated**: 2026-04-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 祺快剪辑 - 完整系统规划文档 ## 📋 文档信息 - **项目名称**: 祺快剪辑 (QiKuai Edit) - **版本**: v1.3 (数据库结构统一 + 分镜数据流修复) - **创建日期**: 2026-04-03 - **最后更新**: 2026-04-04 - **技术栈**: React + Ant Design | Python FastAPI | MySQL | FFmpeg --- ## 📁 一、项目整体架构 ### 1.1 前后端分离架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 祺快剪辑系统 │ ├──────────────────────┬──────────────────────────────────────┤ │ 前端 (Frontend) │ 后端 (Backend) │ │ React + Ant Design │ Python FastAPI + MySQL │ │ 运行端口: 3000 │ 运行端口: 8000 │ │ │ │ │ ┌────────────────┐ │ ┌────────────────────────────────┐ │ │ │ 左侧导航栏 │ │ │ API Routes │ │ │ │ - 素材管理 │ │ │ - /api/materials/* │ │ │ │ - 素材选入 │ │ │ - /api/storyboard/* │ │ │ │ - 分镜预览 │ │ │ - /api/video/* │ │ │ │ - 视频预览 │ │ │ - /api/models/* │ │ │ │ - 模型配置 │ │ │ - /api/prompts/* │ │ │ │ - 提示词库 │ │ └────────────────────────────────┘ │ │ └────────────────┘ │ │ │ │ │ ┌───────────────┴───────────────┐ │ │ │ │ Services │ │ │ │ │ - MaterialService │ │ │ │ │ - StoryboardService │ │ │ │ │ - VideoService │ │ │ │ │ - AIService │ │ │ │ │ - PromptService │ │ │ │ └───────────────────────────────┘ │ │ │ │ │ │ │ ┌───────────────┴───────────────┐ │ │ │ │ MySQL Database │ │ │ │ │ - materials │ │ │ │ │ - categories │ │ │ │ │ - storyboards │ │ │ │ │ - storyboard_clips │ │ │ │ │ - videos │ │ │ │ │ - model_configs │ │ │ │ │ - prompts │ │ │ │ │ - prompt_tags │ │ │ │ └───────────────────────────────┘ │ └──────────────────────┴──────────────────────────────────────┘ │ ▼ ┌──────────────────────────────┐ │ 文件存储目录 │ │ /Users/liang/Desktop/... │ │ /uploads/materials/ │ │ /prompts/ │ │ /storyboards/ │ │ /output/videos/ │ └──────────────────────────────┘ ``` ### 1.2 技术选型理由 | 层级 | 技术 | 理由 | |------|------|------| | 前端框架 | React 18 | 生态完善,组件丰富 | | UI 库 | Ant Design 5 | 阿里出品,中文友好,组件美观 | | 状态管理 | Zustand | 轻量,比 Redux 简单 | | 后端框架 | FastAPI | 异步高性能,自动文档 | | 数据库 | MySQL 8.0 | 稳定可靠,运维成熟 | | 视频处理 | FFmpeg | 视频处理标准工具 | | AI 服务 | OpenAI/GPT-4o | 多模态视频理解能力最强 | --- ## 📂 二、数据库设计 (MySQL) ### 2.1 数据库名称 ``` qkvideo ``` ### 2.2 数据表结构 #### 表 1: materials (素材表) ```sql CREATE TABLE materials ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '素材唯一ID', name VARCHAR(255) NOT NULL COMMENT '素材名称', file_path VARCHAR(512) NOT NULL COMMENT '文件存储路径', file_type VARCHAR(50) NOT NULL COMMENT '文件类型: video/audio/image', material_type VARCHAR(50) NOT NULL COMMENT '素材类别: real_person/scene/voice/digital_human/sample_video', thumbnail_path VARCHAR(512) NULL COMMENT '缩略图路径', duration FLOAT NULL COMMENT '视频/音频时长(秒)', size INT NULL COMMENT '文件大小(字节)', category_id INT NULL COMMENT '分类ID', extra_data JSON NULL COMMENT '额外元数据', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_material_type (material_type), INDEX idx_category (category_id), INDEX idx_created_at (created_at), FOREIGN KEY (category_id) REFERENCES categories(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='素材表'; ``` #### 表 2: categories (分类表) ```sql CREATE TABLE categories ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL COMMENT '分类名称', material_type VARCHAR(50) NOT NULL COMMENT '所属素材类别', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_material_type (material_type) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='素材分类表'; ``` #### 表 3: model_configs (模型配置表) ```sql CREATE TABLE model_configs ( id INT PRIMARY KEY AUTO_INCREMENT, provider VARCHAR(100) NOT NULL COMMENT '服务商名称,如 OpenAI/通义千问', base_url VARCHAR(512) NOT NULL COMMENT 'API Base URL', api_key VARCHAR(255) NOT NULL COMMENT 'API Key', model_name VARCHAR(100) NOT NULL COMMENT '模型名称', is_active BOOLEAN DEFAULT TRUE COMMENT '是否激活', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_provider (provider), INDEX idx_is_active (is_active) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型配置表'; ``` #### 表 4: prompts (提示词表) ```sql CREATE TABLE prompts ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '提示词唯一ID', name VARCHAR(255) NOT NULL COMMENT '提示词名称', content TEXT NOT NULL COMMENT '提示词内容', prompt_type VARCHAR(50) NOT NULL COMMENT '类型: storyboard/video_compose', usage_count INT NOT NULL DEFAULT 0 COMMENT '使用次数', is_default BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否是默认提示词', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_prompt_type (prompt_type), INDEX idx_is_default (is_default) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提示词表'; ``` #### 表 5: prompt_tags (提示词标签表) ```sql CREATE TABLE prompt_tags ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL UNIQUE COMMENT '标签名称', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_name (name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提示词标签表'; ``` #### 表 6: prompt_tag_relations (提示词-标签关联表) ```sql CREATE TABLE prompt_tag_relations ( prompt_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY (prompt_id, tag_id), FOREIGN KEY (prompt_id) REFERENCES prompts(id) ON DELETE CASCADE, FOREIGN KEY (tag_id) REFERENCES prompt_tags(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提示词-标签关联表'; ``` #### 表 7: storyboards (分镜表) ```sql CREATE TABLE storyboards ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '分镜唯一ID', name VARCHAR(100) NOT NULL COMMENT '分镜名称,格式:年月日+序号,如202604030001', prompt_id INT NULL COMMENT '使用的分镜生成提示词ID', model_config_id INT NULL COMMENT '使用的模型配置ID', material_selections JSON NULL COMMENT '素材选入记录', generated_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_name (name), INDEX idx_generated_at (generated_at), FOREIGN KEY (prompt_id) REFERENCES prompts(id), FOREIGN KEY (model_config_id) REFERENCES model_configs(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分镜表'; ``` #### 表 8: storyboard_clips (分镜片段表) ```sql CREATE TABLE storyboard_clips ( id INT PRIMARY KEY AUTO_INCREMENT, storyboard_id INT NOT NULL COMMENT '所属分镜ID', clip_index INT NOT NULL COMMENT '片段顺序', material_id INT NOT NULL COMMENT '使用的素材ID', start_time FLOAT NULL COMMENT '开始时间(秒)', end_time FLOAT NULL COMMENT '结束时间(秒)', label VARCHAR(255) NULL COMMENT '标签: 修复前/施工中/修复后', speed FLOAT DEFAULT 1.0 COMMENT '播放速度', transition VARCHAR(50) NULL COMMENT '转场效果', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_storyboard (storyboard_id), INDEX idx_clip_index (clip_index), FOREIGN KEY (storyboard_id) REFERENCES storyboards(id) ON DELETE CASCADE, FOREIGN KEY (material_id) REFERENCES materials(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分镜片段表'; ``` #### 表 9: videos (视频表) ```sql CREATE TABLE videos ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '视频唯一ID', name VARCHAR(100) NOT NULL COMMENT '视频名称', storyboard_id INT NULL COMMENT '关联分镜ID', prompt_id INT NULL COMMENT '使用的视频合成提示词ID', model_config_id INT NULL COMMENT '使用的模型配置ID', file_path VARCHAR(512) NULL COMMENT '输出文件路径', status VARCHAR(50) DEFAULT 'pending' COMMENT '状态: pending/processing/completed/failed', duration FLOAT NULL COMMENT '视频时长(秒)', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_status (status), INDEX idx_created_at (created_at), FOREIGN KEY (storyboard_id) REFERENCES storyboards(id), FOREIGN KEY (prompt_id) REFERENCES prompts(id), FOREIGN KEY (model_config_id) REFERENCES model_configs(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频表'; ``` #### 表 10: video_clips (视频片段表) ```sql CREATE TABLE video_clips ( id INT PRIMARY KEY AUTO_INCREMENT, video_id INT NOT NULL COMMENT '所属视频ID', clip_index INT NOT NULL COMMENT '片段顺序', material_id INT NOT NULL COMMENT '使用的素材ID', start_time FLOAT NULL COMMENT '开始时间(秒)', end_time FLOAT NULL COMMENT '结束时间(秒)', voice_material_id INT NULL COMMENT '配音素材ID', INDEX idx_video (video_id), INDEX idx_clip_index (clip_index), FOREIGN KEY (video_id) REFERENCES videos(id) ON DELETE CASCADE, FOREIGN KEY (material_id) REFERENCES materials(id), FOREIGN KEY (voice_material_id) REFERENCES materials(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频片段表(最终剪辑结果)'; ``` --- ## 📁 三、文件目录结构 ### 3.1 完整目录树 ``` /Users/liang/Desktop/真人素材自动剪辑脚本/ │ ├── backend/ # 后端项目 │ ├── main.py # FastAPI 主入口 │ ├── requirements.txt # Python 依赖 │ ├── .env # 环境变量(API Keys) │ │ │ ├── models/ # 数据模型 │ │ ├── __init__.py │ │ └── schemas.py │ │ │ ├── services/ # 业务逻辑服务 │ │ ├── __init__.py │ │ ├── material_service.py # 素材管理 │ │ ├── storyboard_service.py # 分镜管理 │ │ ├── video_service.py # 视频合成 │ │ ├── ai_service.py # AI 服务 │ │ ├── model_config_service.py # 模型配置 │ │ └── prompt_service.py # 提示词服务 │ │ │ ├── routes/ # API 路由 │ │ ├── __init__.py │ │ ├── materials.py │ │ ├── storyboard.py │ │ ├── video.py │ │ ├── models.py │ │ └── prompts.py │ │ │ └── utils/ # 工具函数 │ ├── __init__.py │ ├── db.py # 数据库连接 │ └── file_utils.py # 文件处理 │ ├── frontend/ # 前端项目 │ ├── public/ │ │ └── index.html │ │ │ ├── src/ │ │ ├── index.tsx │ │ ├── App.tsx │ │ ├── index.css │ │ │ │ │ ├── components/ # 公共组件 │ │ │ ├── Layout/ │ │ │ │ ├── index.tsx # 主布局(左侧导航) │ │ │ │ └── Sidebar.tsx # 侧边栏 │ │ │ │ │ │ │ ├── MaterialCard/ # 素材卡片 │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── ModelSelector/ # 模型选择器 │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── PromptSelector/ # 提示词选择器 │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── VideoPlayer/ # 视频播放器 │ │ │ └── index.tsx │ │ │ │ │ ├── pages/ # 页面 │ │ │ ├── Materials/ # 素材管理 │ │ │ │ ├── index.tsx │ │ │ │ ├── RealPerson.tsx # 真人素材 │ │ │ │ ├── Scene.tsx # 场景素材 │ │ │ │ ├── Voice.tsx # 配音素材 │ │ │ │ ├── DigitalHuman.tsx # 数字人素材 │ │ │ │ └── ExcellentVideo.tsx # 优秀视频 │ │ │ │ │ │ │ ├── MaterialSelect/ # 素材选入 │ │ │ │ ├── index.tsx │ │ │ │ ├── RealPersonSelect.tsx │ │ │ │ ├── SceneSelect.tsx │ │ │ │ ├── VoiceSelect.tsx │ │ │ │ ├── DigitalHumanSelect.tsx │ │ │ │ └── ExampleVideoSelect.tsx │ │ │ │ │ │ │ ├── Storyboard/ # 分镜预览 │ │ │ │ ├── index.tsx │ │ │ │ └── StoryboardDetail.tsx │ │ │ │ │ │ │ ├── VideoPreview/ # 视频预览 │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── ModelConfig/ # 模型配置 │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── PromptLibrary/ # 提示词库 │ │ │ └── index.tsx │ │ │ │ │ ├── services/ # API 服务 │ │ │ ├── api.ts # API 基础配置 │ │ │ ├── material.ts │ │ │ ├── storyboard.ts │ │ │ ├── video.ts │ │ │ ├── model.ts │ │ │ └── prompt.ts │ │ │ │ │ ├── stores/ # 状态管理 │ │ │ ├── materialStore.ts # 素材状态 │ │ │ ├── projectStore.ts # 项目状态 │ │ │ └── modelStore.ts # 模型状态 │ │ │ │ │ └── types/ # TypeScript 类型 │ │ └── index.ts │ │ │ ├── package.json │ ├── tsconfig.json │ ├── vite.config.ts │ └── .env │ ├── uploads/ # 上传文件存储(数据库驱动) │ ├── materials/ # 素材文件 │ │ ├── real_person/ # 真人素材 │ │ ├── scene/ # 场景素材 │ │ │ ├── 室内/ # 子分类 │ │ │ └── 室外/ │ │ ├── voice/ # 配音素材 │ │ ├── digital_human/ # 数字人素材 │ │ └── excellent_video/ # 优秀视频 │ │ │ ├── thumbnails/ # 缩略图 │ │ ├── materials/ │ │ └── videos/ │ │ │ └── temp/ # 临时文件 │ ├── storyboards/ # 分镜文件存储 │ └── {storyboard_id}/ │ ├── clips/ # 分镜片段 │ └── temp/ │ ├── output/ # 输出视频 │ ├── videos/ # 最终视频 │ └── temp/ │ └── README.md # 项目说明 ``` ### 3.2 数据库与目录的对应关系 ``` ┌─────────────────┐ 文件路径存储在 ┌─────────────────────────────┐ │ MySQL │ ──────────────────→ │ uploads/ │ │ materials │ file_path 字段 │ materials/{category}/ │ │ 表 │ │ │ └─────────────────┘ └─────────────────────────────┘ ┌─────────────────┐ 分镜数据存储在 ┌─────────────────────────────┐ │ MySQL │ ──────────────────→ │ storyboards/{id}/ │ │ storyboards │ │ ├── clips/ │ │ 表 │ │ └── metadata.json │ └─────────────────┘ └─────────────────────────────┘ ┌─────────────────┐ 视频路径存储在 ┌─────────────────────────────┐ │ MySQL │ ──────────────────→ │ output/videos/ │ │ videos │ file_path 字段 │ │ └─────────────────┘ └─────────────────────────────┘ ┌─────────────────┐ 提示词存储在 ┌─────────────────────────────┐ │ MySQL │ ──────────────────→ │ prompts 表(数据库) │ │ prompts │ content 字段 │ │ └─────────────────┘ └─────────────────────────────┘ ``` --- ## 🎨 四、前端页面详细规划 ### 4.1 页面总览 ``` ┌────────────────────────────────────────────────────────────────┐ │ 祺快剪辑 │ ├────────────┬───────────────────────────────────────────────────┤ │ │ │ │ 📁 素材 │ 中间内容区域 │ │ ├ 真人素材 │ │ │ ├ 场景素材 │ 根据左侧选择,显示不同内容 │ │ ├ 配音素材 │ │ │ ├ 数字人素材│ │ │ └ 优秀视频 │ │ │ │ │ │ 📋 素材选入 │ │ │ ├ 真人素材 │ │ │ ├ 场景素材 │ │ │ ├ 配音素材 │ │ │ ├ 数字人素材│ │ │ └ 案例视频 │ │ │ │ │ │ 🎬 分镜预览 │ │ │ │ │ │ 🎥 视频预览 │ │ │ │ │ │ ⚙️ 模型配置 │ │ │ │ │ │ 💡 提示词库 │ │ │ │ │ └────────────┴───────────────────────────────────────────────────┘ ``` ### 4.2 各页面详细设计 #### 页面 2.1: 素材管理页(真人素材示例) **入口**: 左侧栏「素材」→「真人素材」 **布局**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 真人素材 [上传] │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ □选中 │ │ □选中 │ │ □选中 │ │ □选中 │ ... │ │ │ 缩略图 │ │ 缩略图 │ │ 缩略图 │ │ 缩略图 │ │ │ │ │ │ │ │ │ │ │ │ │ │ 文件名 │ │ 文件名 │ │ 文件名 │ │ 文件名 │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ [批量删除] │ └─────────────────────────────────────────────────────────────┘ ``` **功能**: 1. 点击「上传」→ 弹出文件选择器 → 选择视频文件 → 上传到服务器 2. 勾选素材 → 点击「批量删除」→ 确认弹窗 → 删除选中项 --- #### 页面 2.2: 素材选入页(核心页面) **入口**: 左侧栏「素材选入」 **布局**: ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 素材选入 [上一步] [下一步] │ ├─────────────────────────────────────────────────────────────────────┤ │ [真人素材] [场景素材] [配音素材] [数字人素材] [案例视频] [提示词▼] [模型▼] │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 已选入素材区 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 素材1 ×│ │ 素材2 ×│ │ 素材3 ×│ [+ 添加] │ │ │ (可拖拽) │ │ (可拖拽) │ │ (可拖拽) │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ 素材库区(点击「+添加」后显示) │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 缩略图 │ │ 缩略图 │ │ 缩略图 │ │ 缩略图 │ │ │ │ │ │ │ │ │ │ │ │ │ │ 文件名 │ │ 文件名 │ │ 文件名 │ │ 文件名 │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ 提示词选择区(点击「提示词▼」后显示) │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ ○ 使用已有提示词 ● 自定义输入 │ │ │ │ [选择提示词 ▼] [输入自定义提示词...] │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ [开始生成] │ └─────────────────────────────────────────────────────────────────────┘ ``` **操作流程**: **Step 1 - 选择真人素材**: 1. 点击顶部「真人素材」标签 2. 点击素材库区的「+添加」 3. 弹出已上传的真人素材列表 4. 点击选择素材 → 素材出现在「已选入素材区」 5. 右上角显示「×」→ 点击可取消选中 **Step 2 - 选择场景素材**: 1. 点击顶部「场景素材」标签 2. 重复 Step 1 的选择流程 **Step 3 - 选择配音素材**: 1. 点击顶部「配音素材」标签 2. 选择配音文件 **Step 4 - 选择数字人素材**: 1. 点击顶部「数字人素材」标签 2. 选择数字人形象 **Step 5 - 选择案例视频(可选)**: 1. 点击顶部「案例视频」标签 2. 选择参考视频,用于 AI 分析剪辑风格 **Step 6 - 配置提示词**: 1. 点击右上角「提示词▼」 2. 选择「使用已有提示词」或「自定义输入」 - 使用已有:选择提示词库中的分镜生成提示词 - 自定义输入:直接输入提示词内容 **Step 7 - 配置模型**: 1. 点击右上角「模型▼」 2. 选择服务商(已有配置的下拉选项) 3. 选择对应模型 **Step 8 - 生成**: ``` 1. 点击底部「开始生成」 2. 系统创建空分镜(记录选入素材),自动跳转到「分镜详情页」 3. 在分镜详情页选择模型,点击「AI 生成片段」 4. 等待 AI 分析和生成分镜(通常 1-3 分钟) 5. 片段存入数据库,分镜详情页显示所有片段 ``` > ⚠️ **流程变更说明(v1.2)**:「开始生成」仅创建空分镜并跳转到详情页;AI 生成片段需要在详情页手动触发。这样设计让用户可以在 AI 生成前调整模型选择和自定义提示词。 --- #### 页面 2.3: 分镜预览页 **入口**: 左侧栏「分镜预览」| 或素材选入页点击「查看」 **命名规则**: 分镜名称格式为「年月日+序号」,例如: - `202604030001` = 2026年04月03日第1个分镜 - `202604030002` = 2026年04月03日第2个分镜 **布局**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 分镜预览 [模型▼] │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 分镜列表(卡片形式,按日期分组显示) │ │ ── 2026-04-03 ────────────────────────────────────── │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 202604030001 [裂变] [查看] │ │ │ 3个片段 | 45秒 | 汽车补漆 │ │ │ └─────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 202604030002 [裂变] [查看] │ │ │ 4个片段 | 60秒 | 冰雹修复 │ │ │ └─────────────────────────────────────────────────────┘ │ │ ── 2026-04-02 ────────────────────────────────────── │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 202604020001 [裂变] [查看] │ │ │ 5个片段 | 75秒 | 凹陷修复 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` **点击「查看」后进入分镜详情页**: ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 分镜详情 202604030001 [服务商▼] [模型▼] [视频合成] │ ├──────────────────────┬──────────────────────────────────────────────┤ │ │ │ │ 分镜视频预览 │ 编辑区 │ │ ┌────────────┐ │ ┌────────────────────────────────────────┐ │ │ │ │ │ │ 音转文字 台词 配音 提示词 │ │ │ │ 分镜1 │ │ ├────────────────────────────────────────┤ │ │ │ │ │ │ │ │ │ │ ▶️ 播放 │ │ │ [开始识别] [全部识别] │ │ │ │ │ │ │ │ │ │ └────────────┘ │ │ 识别结果文字... │ │ │ │ │ │ │ │ ┌────────────┐ │ │ 台词: │ │ │ │ │ │ │ [可编辑的台词输入框] │ │ │ │ 分镜2 │ │ │ │ │ │ │ │ │ │ 配音: │ │ │ └────────────┘ │ │ [选择配音素材 ▼] │ │ │ │ │ │ │ │ ... │ │ 提示词: │ │ │ │ │ ○ 使用已有 ● 自定义 │ │ │ │ │ [选择提示词 ▼] [输入自定义提示词...] │ │ │ │ └────────────────────────────────────────┘ │ ├──────────────────────┴──────────────────────────────────────────────┤ │ [返回列表] │ └─────────────────────────────────────────────────────────────────────┘ ``` **分镜详情操作**: 1. **AI 生成片段**(⭐v1.2 新增独立步骤): - 从分镜列表进入详情页后,选择模型配置 - 可选:输入自定义提示词覆盖默认提示词 - 点击「AI 生成片段」→ 调用 AI 分析素材并生成分镜片段 - 生成的片段显示在中间栏,可手动调整顺序或删除 2. **手动添加片段**: - 点击左侧素材列表中的素材 - 在片段编辑区调整开始/结束时间、速度、转场效果 - 确认添加 3. **音转文字**: - 点击「开始识别」→ 对当前分镜进行语音转文字 - 点击「全部识别」→ 对所有分镜批量识别 4. **台词编辑**: - 显示识别结果 - 可手动编辑修改 5. **配音**: - 选择配音素材 6. **提示词**: - 选择「使用已有」→ 从提示词库选择视频合成提示词 - 选择「自定义」→ 直接输入提示词内容 7. **视频合成**: - 配置完成后点击「视频合成」 - 进入视频生成流程 --- #### 页面 2.4: 视频预览页 **入口**: 左侧栏「视频预览」 **布局**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 视频预览 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 视频列表(卡片形式) │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ [查看] │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ 视频缩略图 │ │ │ │ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ 视频1 | 2026-04-03 | 60秒 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- #### 页面 2.5: 模型配置页 **入口**: 左侧栏「模型配置」 **布局**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 模型配置 [+ 添加模型] │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 通义千问 │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ Base URL: https://dashscope.aliyuncs.com/api/v1 │ │ │ │ API Key: ●●●●●●●●●●●●●●●●●● [测试] [保存] │ │ │ │ │ │ │ │ 模型: [qwen-vl-max ▼] [qwen-tts ▼] [+ 新增模型] │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ OpenAI │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ Base URL: https://api.openai.com/v1 │ │ │ │ API Key: ●●●●●●●●●●●●●●●●●● [测试] [保存] │ │ │ │ │ │ │ │ 模型: [gpt-4o ▼] [gpt-4o-mini ▼] [+ 新增模型] │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` **添加模型操作**: 1. 点击「+ 添加模型」 2. 弹出表单: - 服务商名称: 输入名称 - Base URL: 输入 API 地址 - API Key: 输入密钥 - 模型名称: 输入模型名 3. 点击「测试连接」 - 成功: 绿色提示「连接成功」 - 失败: 红色提示「连接失败: {原因}」 4. 点击「保存」 **添加同服务商不同模型**: - 不新增卡片 - 在现有卡片内新增模型选项 --- #### 页面 2.6: 提示词库页 ⭐新增 **入口**: 左侧栏「提示词库」 **布局**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 提示词库 [+ 新增提示词] [标签管理] │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 类型筛选: [全部] [分镜生成] [视频合成] │ │ │ │ 标签筛选: [汽车维修] [通用] [冰雹] [划痕] [+添加标签] │ │ │ │ ── 分镜生成提示词 ────────────────────────────────────── │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 汽车补漆分镜脚本 [编辑] [删除] │ │ │ │ 标签: [汽车维修] [补漆] │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ 你是一个专业的汽车维修视频剪辑师... │ │ │ │ 使用次数: 15 | 默认 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 冰雹修复分镜脚本 [编辑] [删除] │ │ │ │ 标签: [汽车维修] [冰雹] │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ 你是一个专业的汽车维修师,擅长处理冰雹损伤... │ │ │ │ 使用次数: 8 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ── 视频合成提示词 ────────────────────────────────────── │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 专业解说配音脚本 [编辑] [删除] │ │ │ │ 标签: [通用] [配音] │ │ │ │ ───────────────────────────────────────────────── │ │ │ │ 请为以下视频生成专业的产品解说配音... │ │ │ │ 使用次数: 22 | 默认 │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` **新增提示词弹窗**: ``` ┌─────────────────────────────────────────────────────────────┐ │ 新增提示词 [×] │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 提示词名称: [汽车补漆分镜脚本 ] │ │ │ │ 类型: (●) 分镜生成 ( ) 视频合成 │ │ │ │ 标签: [+添加标签输入框] │ │ [汽车维修 ×] [补漆 ×] │ │ │ │ 提示词内容: │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ 你是一个专业的汽车维修视频剪辑师。 │ │ │ │ │ │ │ │ 请根据以下素材,生成分镜脚本: │ │ │ │ ... │ │ │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ 设为默认: [✓] │ │ │ │ [取消] [保存] │ └─────────────────────────────────────────────────────────────┘ ``` **提示词库操作**: 1. **新增提示词**: - 点击「+ 新增提示词」 - 填写提示词名称、选择类型 - 添加标签(可多选、可新建) - 输入提示词内容 - 可选择设为默认 2. **标签管理**: - 点击「标签管理」 - 可新增、编辑、删除标签 3. **使用提示词**: - 在素材选入页或分镜详情页点击「提示词▼」 - 选择已有提示词或自定义输入 4. **编辑/删除**: - 点击提示词卡片的编辑/删除按钮 --- ## 🔌 五、后端 API 设计 ### 5.1 API 路由总览 ``` /api ├── materials │ ├── GET / # 获取素材列表(支持 ids, material_type, category_id 参数) │ ├── GET /{category} # 按类型获取素材列表(已废弃,建议用 ?material_type=) │ ├── POST /upload # 上传素材 │ ├── DELETE /{category}/{id} # 删除单个素材 │ ├── DELETE /{category}/batch # 批量删除 │ └── POST /category # 添加分类 │ ├── storyboards # ⭐路由已重构(2026-04-04) │ ├── GET / # 获取分镜列表 │ ├── POST /create # 创建空分镜(仅记录选入素材) │ ├── GET /{storyboard_id} # 获取分镜详情(含关联 clips) │ ├── POST /{storyboard_id}/clips # 手动添加片段 │ ├── DELETE /{storyboard_id}/clips/{clip_id} # 删除片段 │ ├── POST /{storyboard_id}/generate-clips # AI 生成片段(POST body: { model_config_id, custom_prompt }) │ └── DELETE /{storyboard_id} # 删除分镜 │ ├── video │ ├── GET / # 获取视频列表 │ ├── GET /{id} # 获取视频详情 │ ├── POST /compose # 合成视频 │ └── GET /{id}/preview # 预览视频 │ ├── models │ ├── GET / # 获取模型配置列表 │ ├── POST / # 添加/更新模型配置 │ ├── POST /test # 测试连接 │ └── DELETE /{provider} # 删除配置 │ ├── prompts # ⭐新增 │ ├── GET / # 获取提示词列表 │ ├── GET /{id} # 获取提示词详情 │ ├── POST / # 添加提示词 │ ├── PUT /{id} # 更新提示词 │ ├── DELETE /{id} # 删除提示词 │ ├── GET /tags # 获取所有标签 │ ├── POST /tags # 添加标签 │ └── DELETE /tags/{tag} # 删除标签 │ └── health └── GET / # 健康检查 ``` > ⚠️ **路由顺序重要**:`/create` 具体路径必须注册在 `/{storyboard_id}` 参数路径之前,否则 FastAPI 会将 `create` 误匹配为 `storyboard_id`(类型 int 验证失败导致 405 Method Not Allowed)。 ### 5.2 请求/响应示例 #### 上传素材 ```http POST /api/materials/upload?category=real_person Content-Type: multipart/form-data file: [二进制文件] Response: { "success": true, "data": { "id": "abc123", "name": "car_repair.mp4", "category": "real_person", "file_path": "/uploads/materials/real_person/20260403_abc123.mp4", "file_type": "video", "file_size": 15728640, "duration": 120.5, "created_at": "2026-04-03T10:30:00" } } ``` #### 获取素材列表 ```http GET /api/materials/real_person Response: { "success": true, "data": [ { "id": "abc123", "name": "car_repair.mp4", "category": "real_person", "file_path": "/uploads/materials/real_person/20260403_abc123.mp4", "file_type": "video", "file_size": 15728640, "duration": 120.5, "thumbnail": "/uploads/thumbnails/materials/abc123.jpg", "created_at": "2026-04-03T10:30:00" } ] } ``` #### 生成分镜(带提示词) ```http # Step 1: 创建空分镜(记录选入素材,不调用 AI) POST /api/storyboards/create Content-Type: application/json { "real_person_ids": ["xxx", "yyy"], "scene_ids": ["zzz"], "voice_ids": [], "digital_human_ids": [], "sample_video_id": null, "prompt_id": "prompt_001", // 可选:分镜生成提示词ID "custom_prompt": null // 可选:自定义提示词(优先于 prompt_id) } Response: { "id": 11, "name": "202604040001", "message": "分镜已创建,请前往分镜详情页添加片段" } # Step 2: AI 生成片段(进入分镜详情页后触发) POST /api/storyboards/11/generate-clips Content-Type: application/json { "model_config_id": 1, "custom_prompt": null } Response: { "clips": [ { "id": 1, "material_id": 5, "start_time": 0, "end_time": 5, "label": "修复前", "speed": 1.0, "transition": "cut", "clip_index": 0 } ], "total_duration": 45, "message": "片段生成成功" } ``` ``` #### 合成视频(带提示词) ```http POST /api/video/compose Content-Type: application/json { "storyboard_id": "story_001", "audio_text": "识别到的台词内容...", // 音转文字结果 "prompt_id": "prompt_002", // ⭐新增:提示词ID "custom_prompt": null, // ⭐新增:自定义提示词 "provider": "tongyi", "model": "qwen-tts" } Response: { "success": true, "data": { "video_id": "video_001", "status": "composing", "message": "视频合成中,请稍候..." } } ``` #### 提示词管理 ```http # 获取提示词列表 GET /api/prompts?type=storyboard_generate Response: { "success": true, "data": [ { "id": "prompt_001", "name": "汽车补漆分镜脚本", "type": "storyboard_generate", "content": "你是一个专业的汽车维修视频剪辑师...", "tags": ["汽车维修", "补漆"], "is_default": true, "usage_count": 15 } ] } # 新增提示词 POST /api/prompts { "name": "汽车补漆分镜脚本", "type": "storyboard_generate", "content": "你是一个专业的汽车维修视频剪辑师...", "tags": ["汽车维修", "补漆"], "is_default": false } # 获取所有标签 GET /api/prompts/tags Response: { "success": true, "data": ["汽车维修", "补漆", "冰雹", "划痕", "通用", "配音"] } ``` --- ## 🔄 六、AI 剪辑流程详解 ### 6.1 完整工作流 ``` ┌─────────────────────────────────────────────────────────────────┐ │ AI 智能剪辑流程 │ └─────────────────────────────────────────────────────────────────┘ 用户上传素材 │ ▼ ┌─────────────┐ │ 1. AI 分析 │ │ 视觉理解 │ ─── AI 识别每段视频的内容 │ │ "这是一段车漆划痕特写" │ │ "这是一段喷漆施工过程" └─────────────┘ │ ▼ ┌─────────────┐ │ 2. AI 决策 │ │ 剪辑方案 │ ─── AI 决定剪辑顺序和时间点 │ │ 使用用户提供的提示词(或默认提示词) │ │ "第1段取 0-5秒(划痕特写)" │ │ "第2段取 10-25秒(施工过程,2倍速)" │ │ "第3段取 0-5秒(成品展示)" └─────────────┘ │ ▼ ┌─────────────┐ │ 3. 生成分镜 │ │ 保存剪辑点 │ ─── 保存到数据库 │ │ 自动命名:年月日+序号 │ │ 生成中间文件 └─────────────┘ │ ▼ ┌─────────────┐ │ 4. 视频合成 │ │ FFmpeg 执行 │ ─── 按分镜剪辑 │ │ 使用用户提供的合成提示词 │ │ 拼接视频 │ │ 添加字幕 │ │ 混音配音 └─────────────┘ │ ▼ 成品视频 ``` ### 6.2 AI 提示词设计 #### 默认分镜生成提示词 ``` 你是一个专业的汽车维修视频剪辑师。 请分析以下视频素材的内容,并生成分镜脚本: - 视频文件路径: {file_path} - 视频时长: {duration}秒 素材列表: {materials_list} 参考视频(可选): {reference_video} 要求: - 最终视频时长控制在 30-60秒 - 结构:修复前(3-5秒)+ 施工过程(15-25秒)+ 修复后(3-5秒) - 使用施工过程的2-3倍速,让视频更紧凑 - 每个片段需要有字幕标签 请用JSON格式返回分镜脚本: { "clips": [ { "material_id": "xxx", "start_time": 0, "end_time": 5, "label": "修复前", "speed": 1.0, "transition": "fade" }, ... ], "total_duration": 45, "narration": "这段视频的解说词..." } ``` #### 默认视频合成提示词 ``` 请为以下视频生成专业的产品解说配音脚本。 视频内容: - 分镜片段: {clips_info} - 总时长: {total_duration}秒 - 主题: {theme} 要求: - 语言简洁有力,适合短视频 - 突出修复前后的对比 - 体现专业性和信任感 请返回配音脚本内容。 ``` --- ## 🚀 七、系统使用流程(用户操作手册) ### 7.1 首次使用流程 **Step 1: 配置 AI 模型** ``` 1. 左侧栏点击「模型配置」 2. 点击「+ 添加模型」 3. 选择服务商(通义千问/OpenAI/其他) 4. 输入 Base URL、API Key 5. 输入模型名称 6. 点击「测试连接」 7. 成功后点击「保存」 ``` **Step 2: 配置提示词库** ⭐新增 ``` 1. 左侧栏点击「提示词库」 2. 点击「+ 新增提示词」 3. 选择类型「分镜生成」 4. 输入提示词名称和内容 5. 添加标签(汽车维修、通用等) 6. 可选:设为默认 7. 点击保存 8. 重复以上步骤,添加「视频合成」类型的提示词 ``` **Step 3: 上传素材** ``` 1. 左侧栏点击「素材」 2. 选择「真人素材」 3. 点击右上角「上传」 4. 选择视频文件 5. 等待上传完成 6. 重复以上步骤,上传场景素材、配音素材等 ``` ### 7.2 日常剪辑流程 **Step 1: 素材选入** ``` 1. 左侧栏点击「素材选入」 2. 点击顶部「真人素材」标签 3. 点击「+添加」→ 选择之前上传的真人素材 4. 点击顶部「场景素材」标签 5. 重复选择场景素材 6. 如需配音,点击顶部「配音素材」标签 7. 如需参考视频,点击顶部「案例视频」标签 ``` **Step 2: 配置提示词** ⭐核心新增 ``` 1. 点击右上角「提示词▼」 2. 选择提示词使用方式: - 「使用已有提示词」:从下拉列表选择分镜生成提示词 - 「自定义输入」:直接输入提示词内容 3. 选择的提示词将用于指导 AI 生成分镜 ``` **Step 3: 配置模型** ``` 1. 点击右上角「模型▼」 2. 选择服务商(如:通义千问) 3. 选择模型(如:qwen-vl-max) ``` **Step 4: 生成** ``` 1. 点击右下角「开始生成」 2. 等待 AI 分析和生成分镜(通常 1-3 分钟) 3. 分镜自动命名为「年月日+序号」(如 202604030001) 4. 生成完成后自动跳转到「分镜预览」 ``` ### 7.3 分镜调整流程 **Step 1: 查看分镜** ``` 1. 在分镜预览列表点击「查看」 2. 左侧显示分镜视频预览 3. 右侧显示编辑面板 ``` **Step 2: 调整内容** ``` 1. 音转文字:点击「开始识别」→ 识别配音 2. 编辑台词:在台词输入框中修改 3. 更换配音:选择其他配音素材 4. 配置提示词:选择「使用已有」或「自定义」视频合成提示词 ``` **Step 3: 合成视频** ``` 1. 配置完成后,点击右上角「视频合成」 2. 等待视频生成(通常 2-5 分钟) 3. 完成后跳转到「视频预览」 ``` ### 7.4 视频查看流程 ``` 1. 左侧栏点击「视频预览」 2. 在视频列表中找到目标视频 3. 点击「查看」 4. 预览完整视频 5. 可下载或分享 ``` ### 7.5 提示词库管理流程 ⭐新增 **管理提示词** ``` 1. 左侧栏点击「提示词库」 2. 查看所有提示词(按类型筛选) 3. 使用标签快速筛选 4. 编辑或删除现有提示词 ``` **创建新提示词** ``` 1. 点击「+ 新增提示词」 2. 填写基本信息 3. 添加标签 4. 输入完整的提示词内容 5. 保存 ``` --- ## 📊 八、状态管理与数据流 ### 8.1 核心状态 ```typescript // 项目状态 (projectStore) interface ProjectState { // 当前选中的素材 selectedMaterials: { realPerson: Material[]; // 真人素材 scene: Material[]; // 场景素材 voice: Material[]; // 配音素材 digitalHuman: Material[]; // 数字人素材 exampleVideo: Material[]; // 案例视频 }; // 当前分镜 currentStoryboard: Storyboard | null; // 当前视频 currentVideo: Video | null; // 当前步骤 currentStep: 1 | 2 | 3; // 1:素材选入 2:分镜预览 3:视频预览 // ⭐新增:提示词 selectedPrompt: { type: 'storyboard_generate' | 'video_compose'; promptId: string | null; // 已有提示词ID customContent: string | null; // 自定义提示词 isCustom: boolean; // 是否自定义 }; } ``` ### 8.2 组件层级 ``` App └── MainLayout ├── Sidebar (左侧导航) │ ├── 素材下拉菜单 │ ├── 素材选入菜单 │ ├── 分镜预览 │ ├── 视频预览 │ ├── 模型配置 │ └── 提示词库 // ⭐新增 │ └── ContentArea (右侧内容) ├── MaterialsPage │ ├── RealPersonTab │ ├── SceneTab │ ├── VoiceTab │ ├── DigitalHumanTab │ └── ExcellentVideoTab │ ├── MaterialSelectPage │ ├── MaterialTabs (顶部导航) │ ├── SelectedMaterialsArea │ ├── MaterialLibrary (点击添加后显示) │ ├── PromptSelector (提示词选择) // ⭐新增 │ └── BottomBar (上一步/下一步/开始生成) │ ├── StoryboardPage │ ├── StoryboardList │ └── StoryboardDetail │ ├── VideoPreview │ └── EditPanel │ ├── 音转文字 │ ├── 台词 │ ├── 配音 │ └── PromptSelector (提示词选择) // ⭐新增 │ ├── VideoPage │ └── VideoList │ ├── ModelConfigPage │ └── ModelCards │ └── PromptLibraryPage // ⭐新增 ├── PromptList (按类型分组) ├── PromptCard └── PromptForm (新增/编辑弹窗) ``` --- ## 🛠️ 九、开发任务分解 ### 第一阶段:项目初始化 **任务 1.1**: 创建项目结构 ``` 操作: 1. 创建 /Users/liang/Desktop/真人素材自动剪辑脚本/ 2. 创建 backend/ 目录 3. 创建 frontend/ 目录 4. 创建 uploads/ 目录及子目录 5. 创建 storyboards/ 目录 6. 创建 output/ 目录 ``` **任务 1.2**: 初始化后端 ``` 操作: 1. cd backend 2. python3 -m venv venv 3. source venv/bin/activate 4. pip install fastapi uvicorn python-multipart ffmpeg-python 5. pip install openai dashscope 6. 创建 requirements.txt 7. 创建 main.py ``` **任务 1.3**: 初始化前端 ``` 操作: 1. cd frontend 2. npm create vite@latest . -- --template react-ts 3. npm install antd @ant-design/icons 4. npm install zustand axios 5. npm install react-router-dom ``` **任务 1.4**: 创建数据库 ``` 操作: 1. 安装 MySQL (如果未安装) 2. 登录 MySQL: mysql -u root -p 3. 创建数据库: CREATE DATABASE qkvideo; 4. 执行建表SQL (参考第二章,包含新增的 prompts 和 prompt_tags 表) ``` ### 第二阶段:后端开发 **任务 2.1**: 实现素材管理 API ``` 操作: 1. 创建 models/schemas.py - 定义数据模型 2. 创建 services/material_service.py - 素材业务逻辑 3. 创建 routes/materials.py - 素材路由 4. 实现文件上传接口 5. 实现素材查询接口 6. 实现素材删除接口 7. 测试 API ``` **任务 2.2**: 实现模型配置 API ``` 操作: 1. 创建 services/model_config_service.py 2. 创建 routes/models.py 3. 实现模型配置 CRUD 4. 实现连接测试接口 5. 测试 API ``` **任务 2.3**: 实现提示词服务 ⭐新增 ``` 操作: 1. 创建 services/prompt_service.py - 提示词业务逻辑 2. 创建 routes/prompts.py - 提示词路由 3. 实现提示词 CRUD 4. 实现标签管理 5. 实现提示词使用统计 ``` **任务 2.4**: 实现 AI 服务 ``` 操作: 1. 创建 services/ai_service.py 2. 集成通义千问 VL API 3. 集成 OpenAI GPT-4o Vision API 4. 实现视频分析函数 5. 实现分镜生成函数(支持自定义提示词) 6. 实现视频合成函数(支持自定义提示词) ``` **任务 2.5**: 实现分镜管理 API ``` 操作: 1. 创建 services/storyboard_service.py 2. 创建 routes/storyboard.py 3. 实现分镜生成接口(自动命名:年月日+序号) 4. 实现分镜查询接口 5. 实现分镜裂变接口 ``` **任务 2.6**: 实现视频合成服务 ``` 操作: 1. 创建 services/video_service.py 2. 创建 routes/video.py 3. 集成 FFmpeg 4. 实现视频合成逻辑 5. 实现字幕添加逻辑 6. 实现配音混音逻辑 ``` ### 第三阶段:前端开发 **任务 3.1**: 实现基础布局组件 ``` 操作: 1. 创建 Layout/index.tsx - 主布局 2. 创建 Layout/Sidebar.tsx - 侧边栏(包含提示词库入口) 3. 配置 React Router 4. 测试页面切换 ``` **任务 3.2**: 实现素材管理页面 ``` 操作: 1. 创建 pages/Materials/index.tsx 2. 实现素材上传组件 3. 实现素材列表展示 4. 实现批量删除功能 5. 实现添加分类功能(场景素材) ``` **任务 3.3**: 实现素材选入页面 ``` 操作: 1. 创建 pages/MaterialSelect/index.tsx 2. 实现顶部标签导航 3. 实现已选素材展示区 4. 实现素材选择弹窗 5. 实现 PromptSelector 提示词选择组件 // ⭐新增 6. 实现模型选择器 7. 实现上一步/下一步逻辑 8. 实现开始生成按钮 ``` **任务 3.4**: 实现分镜预览页面 ``` 操作: 1. 创建 pages/Storyboard/index.tsx 2. 实现分镜列表展示(按日期分组,自动命名显示) 3. 实现分镜详情页 4. 实现音转文字功能 5. 实现台词编辑 6. 实现配音选择 7. 实现 PromptSelector 提示词选择组件 // ⭐新增 8. 实现视频合成按钮 ``` **任务 3.5**: 实现视频预览页面 ``` 操作: 1. 创建 pages/VideoPreview/index.tsx 2. 实现视频列表展示 3. 实现视频播放器 ``` **任务 3.6**: 实现模型配置页面 ``` 操作: 1. 创建 pages/ModelConfig/index.tsx 2. 实现模型卡片组件 3. 实现添加模型弹窗 4. 实现连接测试功能 5. 实现保存功能 ``` **任务 3.7**: 实现提示词库页面 ⭐新增 ``` 操作: 1. 创建 pages/PromptLibrary/index.tsx 2. 实现提示词列表(按类型分组) 3. 实现标签筛选 4. 实现新增提示词弹窗 5. 实现编辑提示词功能 6. 实现删除提示词功能 7. 实现标签管理弹窗 ``` ### 第四阶段:联调与测试 **任务 4.1**: 前后端联调 ``` 操作: 1. 配置前端 API 代理 2. 测试素材上传 3. 测试提示词 CRUD 4. 测试分镜生成(验证自动命名) 5. 测试视频合成(验证提示词传递) 6. 修复问题 ``` **任务 4.2**: 完整流程测试 ``` 操作: 1. 上传测试素材 2. 执行完整剪辑流程 3. 验证输出视频 4. 优化体验 ``` --- ## 📝 十、开发时间估算 | 阶段 | 任务 | 预计时间 | |------|------|---------| | 第一阶段 | 项目初始化 | 2-3 小时 | | 第二阶段 | 后端开发 | 7-9 小时 | | 第三阶段 | 前端开发 | 10-12 小时 | | 第四阶段 | 联调测试 | 3-4 小时 | | **总计** | | **22-28 小时** | --- ## ⚠️ 十一、注意事项 ### 11.1 文件存储 1. **不要将文件存储在数据库中** - 只存储路径 2. **定期备份 uploads 目录** 3. **视频文件可能很大** - 确保磁盘空间充足 ### 11.2 API 安全 1. **API Key 不要硬编码** - 使用环境变量 2. **生产环境启用 CORS 白名单** 3. **文件上传限制大小** - 建议最大 500MB ### 11.3 AI 成本控制 1. **视频分析会消耗 API 调用次数** 2. **建议先在小素材上测试** 3. **监控 API 使用量** ### 11.4 提示词管理 1. **提示词是系统的核心** - 好的提示词能大幅提升生成质量 2. **建议预设几种常见场景的提示词** 3. **用户自定义提示词需要做安全过滤** --- ## 📚 附录 ### A. 环境变量示例 (.env) ```env # 后端环境变量 DATABASE_URL=mysql://root:password@localhost:3306/qikai_edit UPLOAD_DIR=/Users/liang/Desktop/真人素材自动剪辑脚本/uploads # AI 服务 (通义千问) DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx # AI 服务 (OpenAI) OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx # 服务配置 HOST=0.0.0.0 PORT=8000 ``` ### B. FFmpeg 安装 ```bash # macOS brew install ffmpeg # Ubuntu/Debian sudo apt update sudo apt install ffmpeg # Windows # 下载 https://ffmpeg.org/download.html ``` ### C. MySQL 建表 SQL ```sql -- 完整建表脚本请参考第二章数据表结构 -- 执行方式: mysql -u root -p qikai_edit < init.sql ``` ### D. 默认提示词示例 ```json { "prompts": [ { "name": "汽车补漆分镜脚本", "type": "storyboard_generate", "content": "你是一个专业的汽车维修视频剪辑师。\n\n请根据以下素材,生成分镜脚本:\n- 最终视频时长控制在 20-30秒\n- 结构:修复前(3-5秒)+ 施工过程(10-15秒)+ 修复后(3-5秒)\n- 使用施工过程的2-3倍速,让视频更紧凑\n- 每个片段需要有字幕标签", "tags": ["汽车维修", "补漆"], "is_default": true }, { "name": "专业解说配音脚本", "type": "video_compose", "content": "请为以下视频生成专业的产品解说配音脚本。\n\n要求:\n- 语言简洁有力,适合短视频\n- 突出修复前后的对比\n- 体现专业性和信任感", "tags": ["通用", "配音"], "is_default": true } ] } ``` --- --- ## 📋 十二、版本变更记录 ### v1.2 (2026-04-04) — 修复分镜模块核心 Bug + 架构优化 #### 🔧 Bug 修复 **Bug 1: POST /api/storyboards/create 返回 405 Method Not Allowed** - **根因**: FastAPI 路由注册顺序问题。`GET /api/storyboards/{storyboard_id}`(类型 `int`)在 `POST /api/storyboards/create` 之前注册,导致 `create` 被误匹配为 `storyboard_id`,类型验证失败("create" 不是 int)返回 405 - **修复**: 将 `POST /api/storyboards/create` 路由移到 `GET /api/storyboards/{storyboard_id}` 之前 - **经验**: FastAPI 按注册顺序匹配路径,具体路径必须在参数路径之前 **Bug 2: AI 生成片段返回 400 Bad Request** - **根因**: 前端用 JSON body 发送 `{ model_config_id, custom_prompt }`,但后端函数签名将这些参数当作 query parameters 处理(无 `Body()` 标注),导致 `model_config_id` 始终为 None - **修复**: 新增 `GenerateClipsRequest(BaseModel)`,用 body model 接收参数 **Bug 3: 手动添加片段返回 500 Internal Server Error** - **根因**: 代码使用 `db.func.max(...)`,但 `Session` 对象没有 `func` 属性。`func` 应从 `sqlalchemy` 直接导入 - **修复**: 在文件顶部添加 `from sqlalchemy import func`,将 `db.func.max` 改为 `func.max` **Bug 4: 退出分镜详情页再进入,片段消失** - **根因**: `StoryboardDetailPage` 组件初始化时依赖 `props.detail._materialDetails` 构建左栏素材列表,但从分镜列表页进入时该字段不存在,导致素材列表为空 - **修复**: - 组件挂载时主动调用 `getStoryboard(detail.id)` 从后端重新拉取最新数据 - 左栏素材列表改为组件自身 state,初始化时若没有 `_materialDetails` 则通过 `GET /api/materials?ids=id1,id2,...` 批量拉取素材详情 - **后端配合**: `GET /api/materials` 新增 `ids` 查询参数支持(逗号分隔 ID 列表) #### 🏗️ 架构变更 | 变更点 | 变更前 | 变更后 | |--------|--------|--------| | storyboards 路由结构 | `POST /generate`(单次完成创建+生成) | `POST /create`(创建空分镜)+ `POST /{id}/generate-clips`(AI生成片段)分离 | | generate-clips 参数接收 | query parameters | JSON body (`GenerateClipsRequest`) | | 素材列表加载 | 依赖 props 传入的 `_materialDetails` | 组件自主从后端拉取 | | `/api/materials` | 不支持 ids 过滤 | 支持 `?ids=1,2,3` 批量查询 | #### 📝 补充说明 1. **分镜数据流(修复后)**: ``` 素材选入 → POST /api/storyboards/create → 分镜详情页 → POST /api/storyboards/{id}/generate-clips(AI生成片段) → 片段存入数据库 storyboard_clips 表 退出详情页 → 重新进入 → getStoryboard(id) → 从数据库读取 clips → 正常显示 ``` 2. **当前已知问题(待修复)**: - 退出再进入分镜片段消失问题仍需进一步排查(可能与 AI 返回的 material_id 外键约束有关) --- ### v1.3 (2026-04-04) — 数据库结构统一 #### 🔧 数据库修复 **问题 1: prompts表字段缺失** - **根因**: 实际数据库缺少`usage_count`和`is_default`字段 - **修复**: - 添加`usage_count INT NOT NULL DEFAULT 0`字段 - 添加`is_default BOOLEAN NOT NULL DEFAULT FALSE`字段 - 创建数据库迁移脚本自动更新 **问题 2: 外键约束不完整** - **根因**: 部分表可能缺少外键约束 - **修复**: 验证并确保所有外键关系完整 - `storyboard_clips.material_id` → `materials.id` - 所有关联表的外键约束已验证 **问题 3: 文档与实际不一致** - **根因**: 系统规划文档中的SQL与实际数据库结构不一致 - **修复**: - 更新第二章数据库设计,与实际结构保持一致 - 使用INT自增主键替代VARCHAR(36) - 调整字段名称和类型与实际匹配 #### 🛠️ 创建的工具 1. **数据库迁移工具**: - `001_add_prompt_fields.py` - 添加缺失字段 - `002_fix_database_schema.sql` - 数据库优化 2. **验证工具**: - `verify_database.py` - 数据库结构验证 - `update_documentation.py` - 文档同步工具 3. **报告文件**: - `数据库结构更新报告.md` - 实际数据库结构 - `问题修复报告_数据库设计问题.md` - 完整修复报告 #### ✅ 验证结果 - ✅ prompts表包含usage_count字段 - ✅ prompts表包含is_default字段 - ✅ storyboard_clips表有正确的外键约束 - ✅ 数据完整性检查通过,没有无效的外键引用 - ✅ 所有关键验证通过!数据库结构符合系统规划 --- ### v1.2 (2026-04-04) — 修复分镜模块核心Bug + 路由优化 #### 🔧 Bug 修复 **Bug 1: POST /api/storyboards/create 返回 405 Method Not Allowed** - **根因**: FastAPI 路由注册顺序问题。`GET /api/storyboards/{storyboard_id}`(类型 `int`)在 `POST /api/storyboards/create` 之前注册,导致 `create` 被误匹配为 `storyboard_id`,类型验证失败("create" 不是 int)返回 405 - **修复**: 将 `POST /api/storyboards/create` 路由移到 `GET /api/storyboards/{storyboard_id}` 之前 - **经验**: FastAPI 按注册顺序匹配路径,具体路径必须在参数路径之前 **Bug 2: AI 生成片段返回 400 Bad Request** - **根因**: 前端用 JSON body 发送 `{ model_config_id, custom_prompt }`,但后端函数签名将这些参数当作 query parameters 处理(无 `Body()` 标注),导致 `model_config_id` 始终为 None - **修复**: 新增 `GenerateClipsRequest(BaseModel)`,用 body model 接收参数 **Bug 3: 手动添加片段返回 500 Internal Server Error** - **根因**: 代码使用 `db.func.max(...)`,但 `Session` 对象没有 `func` 属性。`func` 应从 `sqlalchemy` 直接导入 - **修复**: 在文件顶部添加 `from sqlalchemy import func`,将 `db.func.max` 改为 `func.max` **Bug 4: 退出分镜详情页再进入,片段消失** - **根因**: `StoryboardDetailPage` 组件初始化时依赖 `props.detail._materialDetails` 构建左栏素材列表,但从分镜列表页进入时该字段不存在,导致素材列表为空 - **修复**: - 组件挂载时主动调用 `getStoryboard(detail.id)` 从后端重新拉取最新数据 - 左栏素材列表改为组件自身 state,初始化时若没有 `_materialDetails` 则通过 `GET /api/materials?ids=id1,id2,...` 批量拉取素材详情 - **后端配合**: `GET /api/materials` 新增 `ids` 查询参数支持(逗号分隔 ID 列表) #### 🏗️ 架构变更 | 变更点 | 变更前 | 变更后 | |--------|--------|--------| | storyboards 路由结构 | `POST /generate`(单次完成创建+生成) | `POST /create`(创建空分镜)+ `POST /{id}/generate-clips`(AI生成片段)分离 | | generate-clips 参数接收 | query parameters | JSON body (`GenerateClipsRequest`) | | 素材列表加载 | 依赖 props 传入的 `_materialDetails` | 组件自主从后端拉取 | | `/api/materials` | 不支持 ids 过滤 | 支持 `?ids=1,2,3` 批量查询 | #### 📝 补充说明 1. **分镜数据流(修复后)**: ``` 素材选入 → POST /api/storyboards/create → 分镜详情页 → POST /api/storyboards/{id}/generate-clips(AI生成片段) → 片段存入数据库 storyboard_clips 表 退出详情页 → 重新进入 → getStoryboard(id) → 从数据库读取 clips → 正常显示 ``` 2. **当前已知问题(待修复)**: - 退出再进入分镜片段消失问题仍需进一步排查(可能与 AI 返回的 material_id 外键约束有关) --- ### v1.1 (2026-04-03) — 增加提示词库 - 新增提示词库页面,支持分镜生成/视频合成两类提示词 - 支持标签管理、多标签筛选 - 素材选入页和分镜详情页支持选择提示词 --- *文档版本: v1.3 | 最后更新: 2026-04-04*