# 分镜视频缩略图功能实现 **日期**: 2026-02-14 **类型**: Feature **影响范围**: 后端 API、数据库、AI 生成流程 ## 📋 变更概述 为 `storyboard_videos` 表添加 `thumbnail_url` 字段,并在视频生成完成后自动提取第一帧作为缩略图。 ## 🗄️ 数据库变更 ### 1. Model 更新 **文件**: `server/app/models/storyboard_resource.py` ```python class StoryboardVideo(SQLModel, table=True): # ... 其他字段 thumbnail_url: Optional[str] = Field(default=None, max_length=500) # 新增字段 ``` ### 2. 数据库迁移 **文件**: `server/alembic/versions/20260214_1214_add_thumbnail_url_to_storyboard_videos.py` ```sql ALTER TABLE storyboard_videos ADD COLUMN thumbnail_url VARCHAR(500); ``` **执行命令**: ```bash docker exec jointo-server-app python scripts/db_migrate.py upgrade ``` ## 🔧 业务逻辑实现 ### 1. 缩略图生成服务 **文件**: `server/app/services/ai_generation_result_service.py` **新增方法**: `_generate_video_thumbnail` **实现逻辑**: 1. 从 MinIO 下载视频文件 2. 使用 `ffmpeg` 提取第一帧(0 秒位置) 3. 缩放到 300x300(保持宽高比) 4. 上传缩略图到 MinIO(category: `thumbnail_video`) 5. 返回缩略图 URL **参考实现**: `project_resource_service._generate_video_thumbnail` ### 2. 视频保存逻辑更新 **文件**: `server/app/services/ai_generation_result_service.py` **方法**: `_save_storyboard_video` **变更内容**: ```python # 生成视频缩略图 thumbnail_url = await self._generate_video_thumbnail( video_url=output_data['file_url'], checksum=output_data['checksum'], user_id=user_id ) # 保存到数据库 video = StoryboardVideo( # ... 其他字段 thumbnail_url=thumbnail_url, # ✅ 新增 ) ``` ### 3. Schema 更新 **文件**: `server/app/schemas/storyboard_resource.py` **类**: `VideoResponse` ```python class VideoResponse(BaseModel): # ... 其他字段 thumbnail_url: Optional[str] = Field(None, serialization_alias="thumbnailUrl", description="缩略图URL") @field_serializer("thumbnail_url") def serialize_thumbnail_url(self, value: Optional[str]) -> Optional[str]: """统一构建缩略图访问 URL""" if value is None: return None return build_file_url(value) ``` ## 📡 API 响应变更 ### 获取分镜视频列表/详情 **API**: `GET /api/v1/storyboards/{storyboard_id}/videos` **响应示例**: ```json { "success": true, "data": { "videoId": "01a2b3c4-...", "storyboardId": "01b3c4d5-...", "url": "http://localhost:9000/jointo/videos/video_xxx.mp4", "thumbnailUrl": "http://localhost:9000/jointo/thumbnail_video/thumbnail_xxx.jpg", // ✅ 新增 "status": 2, "isActive": true, // ... 其他字段 } } ``` ## 🧪 测试命令 ### 1. 创建 AI 对话并生成视频 ```bash # 1. 创建对话会话 curl -X POST 'http://localhost:8000/api/v1/ai/conversations' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "projectId": "PROJECT_ID", "targetType": 1, "targetId": "STORYBOARD_ID", "mediaType": 2 }' # 2. 发送消息生成视频(替换 {conversation_id}) curl -X POST 'http://localhost:8000/api/v1/ai/conversations/{conversation_id}/messages' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "content": "生成一个日落海滩的视频", "generate": { "generationType": "video", "modelId": "wan-video-1.0", "aiParams": { "resolution": "1080p", "aspectRatio": "16:9", "duration": 5 } } }' ``` ### 2. 查询视频缩略图 ```bash # 查看视频详情(确认 thumbnailUrl 字段) curl -X GET 'http://localhost:8000/api/v1/storyboards/{storyboard_id}/videos' \ -H 'Authorization: Bearer YOUR_TOKEN' ``` ## 🔍 技术要点 ### ffmpeg 命令 ```bash ffmpeg -i input.mp4 \ -ss 00:00:00 \ # 从第 0 秒开始 -vframes 1 \ # 提取 1 帧 -vf scale=300:300:force_original_aspect_ratio=decrease \ # 缩放 -y output.jpg # 覆盖输出 ``` ### 依赖关系 - **ffmpeg**: 容器内必须安装(已在 Dockerfile 中配置) - **httpx**: 下载视频文件 - **FileStorageService**: 上传缩略图到 MinIO ### 错误处理 - 缩略图生成失败不影响视频保存(`thumbnail_url` 为 `NULL`) - 日志记录所有错误便于排查 - 临时文件自动清理 ## 📝 相关文件清单 ``` server/ ├── alembic/versions/ │ └── 20260214_1214_add_thumbnail_url_to_storyboard_videos.py # 迁移脚本 ├── app/ │ ├── models/ │ │ └── storyboard_resource.py # Model 更新 │ ├── schemas/ │ │ └── storyboard_resource.py # Schema 更新 │ └── services/ │ └── ai_generation_result_service.py # 业务逻辑实现 └── docs/server/changelogs/ └── 2026-02-14-storyboard-video-thumbnail.md # 本文档 ``` ## ✅ 验证清单 - [x] 数据库字段已添加 - [x] 迁移脚本已执行成功 - [x] Model 更新完成 - [x] Schema 更新完成 - [x] 缩略图生成逻辑已实现 - [x] API 响应包含 `thumbnailUrl` 字段 - [ ] 前端集成测试(待前端实现) - [ ] 生产环境部署验证(待部署) ## 🚀 后续优化建议 1. **异步处理**: 将缩略图生成改为 Celery 异步任务,避免阻塞视频保存 2. **多帧选择**: 支持提取视频中间帧或多帧合成 3. **缓存策略**: 对同一视频的缩略图请求添加缓存 4. **CDN 加速**: 缩略图 URL 接入 CDN 提升加载速度 5. **质量配置**: 支持自定义缩略图尺寸和质量参数