# AI视频生成模块开发文档 ## 模块概述 实现完整的AI视频生成模块,集成阿里云百炼平台(DashScope),支持数字人合成和通用视频合成两大功能。 ## 技术栈 - 后端框架:FastAPI - ORM:SQLAlchemy 2.0 - 数据库:PostgreSQL(schema: aigcspace) - AI平台:阿里云百炼平台(dashscope SDK + HTTP API) - 存储:阿里云OSS(已有oss_service) - 认证:JWT Token(已有auth中间件) --- ## 一、子模块划分 ### 1.1 数字人合成模块 基于数字人模型,通过单张图片和音频生成动作自然的说话/唱歌/表演视频。 **模型列表:** | 模型ID(model_id) | 功能 | 计费说明 | |---------|------|------| | wan2.2-s2v | 数字人视频合成 | 按视频时长计费,从model_price表获取单价 | | wan2.2-s2v-detect | 图像检测(检测图片是否符合规范) | 按张计费,从model_price表获取单价 | **支持参数(完全参照文档):** - `image_url`:人物图片URL(必填) - `audio_url`:音频文件URL(必填,wav/mp3,<15M,<20s) - `resolution`:分辨率(可选,480P/720P,默认480P) ### 1.2 视频合成模块 统一API端点,支持三种输入模式的视频生成。 **模型列表:** | 模型ID(model_id) | 功能 | 计费说明 | |---------|------|------| | wan2.6-t2v | 文生视频(多镜头叙事、自动配音、720P/1080P、5/10/15秒) | 按视频时长计费,从model_price表获取单价 | | wan2.6-i2v | 图生视频(首帧/尾帧控制、音频同步、720P/1080P、5/10/15秒) | 按视频时长计费,从model_price表获取单价 | **三种输入模式:** 1. **仅提示词**:调用`wan2.6-t2v`文生视频 2. **提示词+首帧图片**:调用`wan2.6-i2v`图生视频 3. **提示词+首帧+尾帧图片**:调用`wan2.6-i2v`图生视频(尾帧控制结束画面) --- ## 二、API端点设计 ### 2.1 数字人合成API ``` # 图像检测(前端预检测) POST /api/video/avatar/detect 请求体:{ "image_url": "string" } 响应:{ "check_pass": bool, "humanoid": bool, "message": "string" } # 创建数字人合成任务 POST /api/video/avatar/generate 请求体:{ "image_url": "string", // 必填,人物图片URL "audio_url": "string", // 必填,音频URL "resolution": "480P|720P" // 可选,默认480P } 响应:{ "task_id": "string", "task_status": "PENDING" } # 查询任务状态 GET /api/video/avatar/task/{task_id} 响应:{ "task_id": "string", "task_status": "PENDING|RUNNING|SUCCEEDED|FAILED", "video_url": "string", // 成功时返回 "video_duration": float, // 视频时长(秒) "error_message": "string" // 失败时返回 } ``` ### 2.2 视频合成API(统一端点) ``` # 创建视频生成任务 POST /api/video/generate 请求体:{ "prompt": "string", // 必填,视频描述提示词 "first_frame_url": "string", // 可选,首帧图片URL "last_frame_url": "string", // 可选,尾帧图片URL(需先有首帧) "negative_prompt": "string", // 可选,反向提示词 "resolution": "720P|1080P", // 可选,默认720P "duration": 5|10|15, // 可选,默认5秒 "audio_url": "string", // 可选,自定义音频URL "audio": bool, // 可选,是否自动生成音频,默认true "prompt_extend": bool, // 可选,是否智能改写,默认true "shot_type": "single|multi", // 可选,镜头类型(仅文生视频) "watermark": bool, // 可选,是否添加水印,默认false "seed": int // 可选,随机种子 } 响应:{ "task_id": "string", "task_status": "PENDING" } # 查询任务状态 GET /api/video/task/{task_id} 响应:{ "task_id": "string", "task_status": "PENDING|RUNNING|SUCCEEDED|FAILED", "video_url": "string", "video_duration": float, "actual_prompt": "string", // 智能改写后的提示词 "error_message": "string" } # 获取历史记录 GET /api/video/history?page=1&page_size=20 响应:{ "items": [...], "total": int, "page": int, "page_size": int } ``` --- ## 三、数据表设计 ### 3.1 视频模型参数表(video_model_config) 存储各视频模型的支持参数配置,供前端动态渲染表单。 ```sql CREATE TABLE IF NOT EXISTS aigcspace.video_model_config ( id SERIAL PRIMARY KEY, model_name VARCHAR(100) NOT NULL UNIQUE, -- 模型名称(如wan2.6-t2v) model_id VARCHAR(100) NOT NULL, -- 模型ID model_type VARCHAR(50) NOT NULL, -- 模型类型:t2v/i2v/s2v supported_params JSONB NOT NULL, -- 支持的参数配置JSON is_active BOOLEAN DEFAULT TRUE, -- 是否启用 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 索引 CREATE INDEX idx_video_model_config_type ON aigcspace.video_model_config(model_type); CREATE INDEX idx_video_model_config_active ON aigcspace.video_model_config(is_active); ``` **supported_params JSON结构示例:** ```json { "resolutions": ["720P", "1080P"], "durations": [5, 10, 15], "max_prompt_length": 1500, "supports_audio": true, "supports_audio_url": true, "supports_multi_shot": true, "supports_first_frame": false, "supports_last_frame": false, "aspect_ratios": { "720P": ["1280*720", "720*1280", "960*960"], "1080P": ["1920*1080", "1080*1920", "1440*1440"] } } ``` ### 3.2 视频生成记录表(ai_video) ```sql CREATE TABLE IF NOT EXISTS aigcspace.ai_video ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, -- 用户ID task_id VARCHAR(100) NOT NULL UNIQUE, -- 百炼平台任务ID model_name VARCHAR(100) NOT NULL, -- 使用的模型名称 video_type VARCHAR(50) NOT NULL, -- 视频类型:t2v/i2v/s2v -- 输入参数 input_params JSONB NOT NULL, -- 输入参数JSON(包含所有请求参数) prompt TEXT, -- 原始提示词 actual_prompt TEXT, -- 智能改写后的提示词 first_frame_url VARCHAR(500), -- 首帧图片URL last_frame_url VARCHAR(500), -- 尾帧图片URL audio_url VARCHAR(500), -- 音频URL -- 输出结果 video_url VARCHAR(500), -- 输出视频OSS URL video_duration NUMERIC(10, 2), -- 视频时长(秒) resolution VARCHAR(20), -- 视频分辨率 -- 任务状态 status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING/RUNNING/SUCCEEDED/FAILED error_message TEXT, -- 错误信息 -- 费用 bill NUMERIC(10, 4) DEFAULT 0, -- 任务消耗费用 -- 时间戳 submit_time TIMESTAMP, -- 任务提交时间 scheduled_time TIMESTAMP, -- 任务开始执行时间 end_time TIMESTAMP, -- 任务完成时间 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 索引 CREATE INDEX idx_ai_video_user_id ON aigcspace.ai_video(user_id); CREATE INDEX idx_ai_video_task_id ON aigcspace.ai_video(task_id); CREATE INDEX idx_ai_video_status ON aigcspace.ai_video(status); CREATE INDEX idx_ai_video_created_at ON aigcspace.ai_video(created_at DESC); CREATE INDEX idx_ai_video_video_type ON aigcspace.ai_video(video_type); -- 表注释 COMMENT ON TABLE aigcspace.ai_video IS 'AI视频生成记录表'; COMMENT ON COLUMN aigcspace.ai_video.video_type IS '视频类型:t2v=文生视频,i2v=图生视频,s2v=数字人合成'; COMMENT ON COLUMN aigcspace.ai_video.input_params IS '完整输入参数JSON,便于追溯'; COMMENT ON COLUMN aigcspace.ai_video.actual_prompt IS '开启prompt_extend时返回的改写后提示词'; ``` --- ## 四、后端服务实现 ### 4.1 文件结构 ``` backend/app/ ├── models/ │ └── ai_video.py # 视频相关ORM模型 ├── schemas/ │ └── video_schema.py # 视频相关Pydantic模型 ├── services/ │ ├── video_service.py # 视频合成服务(统一入口) │ ├── avatar_service.py # 数字人合成服务 │ └── video_billing.py # 视频费用计算 ├── routers/ │ └── video_router.py # 视频API路由 └── migrations/ ├── 022_create_video_model_config.sql └── 023_create_ai_video_table.sql ``` ### 4.2 核心服务实现要点 #### video_billing.py(视频费用计算) ```python """ 视频生成计费计算器 从数据库model_price表获取模型价格,计算视频生成费用 视频模型使用output_price字段存储每秒视频的价格 计费公式: cost = output_price × video_duration """ from decimal import Decimal, ROUND_HALF_UP from sqlalchemy.orm import Session, joinedload from app.models.model import Model, ModelPrice class VideoBillingCalculator: """视频生成计费计算器""" def __init__(self, db: Session): self.db = db def calculate_cost(self, model_id: str, video_duration: float) -> Decimal: """ 计算视频生成费用 Args: model_id: 模型标识(如 wan2.6-t2v, wan2.2-s2v) video_duration: 视频时长(秒) Returns: 费用金额(CNY),精度4位小数 """ if video_duration <= 0: return Decimal("0.0000") model = self.db.query(Model).options( joinedload(Model.price_info) ).filter(Model.title == model_id).first() if not model or not model.price_info: return Decimal("0.0000") price_per_second = Decimal(str(model.price_info.output_price)) total_cost = price_per_second * Decimal(str(video_duration)) return total_cost.quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP) def calculate_detect_cost(self, model_id: str = "wan2.2-s2v-detect") -> Decimal: """计算图像检测费用(按张计费)""" model = self.db.query(Model).options( joinedload(Model.price_info) ).filter(Model.title == model_id).first() if not model or not model.price_info: return Decimal("0.0000") return Decimal(str(model.price_info.output_price)).quantize( Decimal("0.0001"), rounding=ROUND_HALF_UP ) ``` #### video_service.py(视频合成服务) ```python class VideoService: """视频合成服务 - 统一处理文生视频和图生视频""" async def generate(self, request: VideoGenerateRequest) -> VideoTaskResponse: """ 统一视频生成入口 根据输入参数自动选择模型: - 有first_frame_url → 使用wan2.6-i2v(图生视频) - 无first_frame_url → 使用wan2.6-t2v(文生视频) """ if request.first_frame_url: return await self._image_to_video(request) else: return await self._text_to_video(request) async def _text_to_video(self, request): """文生视频 - 调用wan2.6-t2v""" # 构建请求参数(完全参照文档) # 异步提交任务 # 保存记录到数据库 # 返回task_id pass async def _image_to_video(self, request): """图生视频 - 调用wan2.6-i2v""" # 支持首帧+可选尾帧 # 异步提交任务 # 保存记录到数据库 # 返回task_id pass async def get_task_status(self, task_id: str) -> VideoTaskResult: """查询任务状态并更新数据库""" # 调用百炼API查询 # 更新本地数据库状态 # 如果成功,下载视频到OSS pass ``` #### avatar_service.py(数字人合成服务) ```python class AvatarService: """数字人合成服务""" async def detect_image(self, image_url: str) -> AvatarDetectResponse: """图像检测 - 调用wan2.2-s2v-detect""" # 同步调用检测API # 返回检测结果 pass async def generate(self, request: AvatarGenerateRequest) -> VideoTaskResponse: """数字人视频合成 - 调用wan2.2-s2v""" # 异步提交任务 # 保存记录到数据库 # 返回task_id pass ``` ### 4.3 API调用规范 **文生视频(wan2.6-t2v)HTTP调用:** ``` POST https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis Headers: - Authorization: Bearer {API_KEY} - Content-Type: application/json - X-DashScope-Async: enable Body: { "model": "wan2.6-t2v", "input": { "prompt": "...", "negative_prompt": "...", "audio_url": "..." }, "parameters": { "size": "1280*720", "duration": 10, "prompt_extend": true, "shot_type": "single", "watermark": false, "seed": 12345 } } ``` **图生视频(wan2.6-i2v)SDK调用:** ```python from dashscope import VideoSynthesis rsp = VideoSynthesis.async_call( api_key=api_key, model='wan2.6-i2v', prompt='...', img_url=first_frame_url, audio_url=audio_url, resolution="1080P", duration=10, prompt_extend=True, watermark=False, seed=12345 ) ``` **数字人合成(wan2.2-s2v)HTTP调用:** ``` POST https://dashscope.aliyuncs.com/api/v1/services/aigc/image2video/video-synthesis Headers: - Authorization: Bearer {API_KEY} - Content-Type: application/json - X-DashScope-Async: enable Body: { "model": "wan2.2-s2v", "input": { "image_url": "...", "audio_url": "..." }, "parameters": { "resolution": "720P" } } ``` --- ## 五、前端完善要点 ### 5.1 现有页面分析 前端`VideoSynthesis.tsx`已有基础框架,包含: - 数字人合成Tab(basic):形象选择、音频上传、配置面板 - 视频合成Tab(video):首帧/尾帧上传、提示词输入、参数配置 ### 5.2 需要完善的功能 **数字人合成Tab:** 1. 自定义形象上传时调用图像检测API 2. 检测不通过时显示错误提示 3. 音频上传限制(wav/mp3,<15M,<20s) 4. 分辨率选择(480P/720P) 5. 调用数字人合成API **视频合成Tab:** 1. 根据是否有首帧自动切换模型 2. 音频设置:上传自定义音频 / 自动生成音频 3. 镜头类型选择(仅文生视频时显示) 4. 完善参数传递与API调用 ### 5.3 videoApi.ts 需要新增的接口 ```typescript // 数字人图像检测 async detectAvatarImage(imageUrl: string): Promise> // 数字人合成 async createAvatarTask(request: AvatarGenerateRequest): Promise> // 查询数字人任务状态 async getAvatarTaskStatus(taskId: string): Promise> ``` --- ## 六、开发任务清单 ### 阶段一:数据库迁移 - [ ] 创建video_model_config表迁移文件 - [ ] 创建ai_video表迁移文件 - [ ] 执行迁移并初始化模型配置数据 ### 阶段二:后端服务 - [ ] 创建ai_video.py ORM模型 - [ ] 创建video_schema.py Schema定义 - [ ] 实现video_service.py(文生视频、图生视频) - [ ] 实现avatar_service.py(数字人检测、合成) - [ ] 实现video_billing.py(费用计算) - [ ] 创建video_router.py API路由 - [ ] 注册路由到main.py ### 阶段三:前端完善 - [ ] 完善videoApi.ts接口定义 - [ ] 数字人合成Tab:图像检测、参数完善、API调用 - [ ] 视频合成Tab:参数完善、API调用 - [ ] 任务状态轮询与结果展示 ### 阶段四:测试与优化 - [ ] 接口联调测试 - [ ] 错误处理完善 - [ ] 费用计算验证 --- ## 七、注意事项 1. **API地域**:使用北京地域API(https://dashscope.aliyuncs.com/api/v1) 2. **视频URL有效期**:百炼返回的video_url仅24小时有效,需下载到OSS永久存储 3. **任务查询有效期**:task_id查询有效期24小时 4. **费用计算**: - 从`model_price`表根据`model_id`获取单价(output_price字段) - 视频模型按时长计费:`bill = output_price × video_duration` - 图像检测按张计费:`bill = output_price × 1` - 参考`ImageBillingCalculator`实现方式 5. **音频限制**: - 数字人合成:wav/mp3,<15M,<20s - 视频合成:wav/mp3,3~30s,<15MB 6. **图片限制**:jpg/jpeg/png/bmp/webp,宽高[400, 7000]像素