# 分镜音效服务实现 **日期**:2026-02-12 **类型**:新功能 **影响范围**:后端 API、数据库 ## 变更概述 完整实现分镜音效服务(Storyboard Sound Effect Service),支持 AI 生成的环境音、背景音乐、特效音和氛围音的管理,包括多版本管理、激活切换、播放参数控制等功能。 ## 实现内容 ### 1. Model 层 **文件**:`server/app/models/storyboard_sound_effect.py` - 创建 `StoryboardSoundEffect` 模型 - 创建 `SoundEffectType` 枚举(1=background_music, 2=ambient, 3=sound_effect, 4=atmosphere) - 支持多版本管理(version 字段) - 支持激活状态管理(is_active 字段) - 包含播放参数(volume, fade_in_duration, fade_out_duration, loop_enabled) - 包含时间轴定位(start_time, duration) - 集成文件去重机制(checksum 字段) ### 2. Schema 层 **文件**:`server/app/schemas/storyboard_sound_effect.py` - `SoundEffectCreate`:创建音效请求 - `SoundEffectUpdate`:更新音效参数请求 - `SoundEffectResponse`:音效响应 ### 3. Repository 层 **文件**:`server/app/repositories/storyboard_sound_effect_repository.py` 核心方法: - `create()` - 创建音效 - `get_by_id()` - 根据 ID 获取音效 - `get_by_storyboard()` - 获取分镜的所有音效 - `get_by_storyboard_and_type()` - 获取指定类型的所有版本 - `get_active_effects()` - 获取所有激活音效 - `get_active_effect_by_type()` - 获取指定类型的激活音效 - `get_max_version_by_type()` - 获取最大版本号 - `deactivate_by_type()` - 取消指定类型的激活状态 - `update()` / `update_by_id()` - 更新音效 - `delete()` - 删除音效 ### 4. Service 层 **文件**:`server/app/services/storyboard_sound_effect_service.py` 核心功能: - `create_sound_effect()` - 创建音效(支持文件去重) - `get_sound_effects()` - 获取音效列表(可按类型筛选) - `get_active_sound_effects()` - 获取所有激活音效 - `get_active_effect_by_type()` - 获取指定类型的激活音效 - `set_active_sound_effect()` - 设置激活音效(自动取消同类型其他音效) - `update_sound_effect()` - 更新音效参数 - `delete_sound_effect()` - 删除音效(减少文件引用计数) - `deactivate_sound_effect()` - 停用音效 - `_check_storyboard_permission()` - 权限检查 ### 5. API 层 **文件**:`server/app/api/v1/storyboard_sound_effects.py` REST API 接口: - `POST /storyboards/{storyboard_id}/sound-effects` - 创建音效 - `GET /storyboards/{storyboard_id}/sound-effects` - 获取音效列表 - `GET /storyboards/{storyboard_id}/sound-effects/active` - 获取所有激活音效 - `GET /storyboards/{storyboard_id}/sound-effects/active/{effect_type}` - 获取指定类型的激活音效 - `POST /sound-effects/{sound_effect_id}/activate` - 激活音效 - `POST /sound-effects/{sound_effect_id}/deactivate` - 停用音效 - `PATCH /sound-effects/{sound_effect_id}` - 更新音效参数 - `DELETE /sound-effects/{sound_effect_id}` - 删除音效 ### 6. 数据库迁移 **文件**:`server/alembic/versions/20260212_2000_add_storyboard_sound_effects.py` 创建 `storyboard_sound_effects` 表: - 27 个字段(包含音效元数据、播放参数、AI 生成参数等) - 部分唯一索引(同一类型只能有一个激活音效) - 5 个普通索引(storyboard_id, status, effect_type, checksum, active) - 完整的字段注释(符合 jointo-tech-stack 规范) ### 7. 模块注册 - 更新 `server/app/models/__init__.py` - 注册 `StoryboardSoundEffect` 和 `SoundEffectType` - 更新 `server/app/api/v1/__init__.py` - 注册 `storyboard_sound_effects` 路由 ## 技术特性 ### 1. 多版本管理 - 每次生成同类型音效自动递增版本号 - 支持保留历史版本 - 支持版本切换 ### 2. 激活状态管理 - 同一类型只能有一个激活音效(通过部分唯一索引实现) - 激活新版本时自动取消旧版本 - 支持停用音效(不删除) ### 3. 文件去重 - 通过 `checksum` 字段关联 `file_checksums` 表 - 相同音效文件只存储一次 - 引用计数管理(创建时 +1,删除时 -1) - 引用计数为 0 时自动删除文件 ### 4. 播放参数控制 - 音量控制(0.0-1.0) - 淡入淡出时长 - 循环播放开关 - 时间轴定位(start_time, duration) ### 5. 权限控制 - 所有操作需要分镜权限验证 - 创建/更新/删除需要 editor 权限 - 查询需要 viewer 权限 ## 数据库表结构 ```sql CREATE TABLE storyboard_sound_effects ( sound_effect_id UUID PRIMARY KEY, storyboard_id UUID NOT NULL, audio_url TEXT NOT NULL, status SMALLINT NOT NULL, -- 0=pending, 1=processing, 2=completed, 3=failed is_active BOOLEAN DEFAULT false, version INTEGER DEFAULT 1 NOT NULL, effect_type SMALLINT NOT NULL, -- 1=background_music, 2=ambient, 3=sound_effect, 4=atmosphere effect_name TEXT, volume NUMERIC(3, 2) DEFAULT 1.0, fade_in_duration NUMERIC(10, 3) DEFAULT 0.0, fade_out_duration NUMERIC(10, 3) DEFAULT 0.0, loop_enabled BOOLEAN DEFAULT false, start_time NUMERIC(10, 3) DEFAULT 0.0 NOT NULL, duration NUMERIC(10, 3), file_size BIGINT, format TEXT, sample_rate INTEGER, bit_rate INTEGER, checksum TEXT NOT NULL, storage_provider TEXT, storage_path TEXT NOT NULL, ai_model TEXT, ai_prompt TEXT, ai_params JSONB DEFAULT '{}', error_message TEXT, created_at TIMESTAMPTZ DEFAULT now() NOT NULL, completed_at TIMESTAMPTZ ); -- 部分唯一索引(同一类型只能有一个激活音效) CREATE UNIQUE INDEX storyboard_sound_effects_type_active_unique ON storyboard_sound_effects (storyboard_id, effect_type, is_active) WHERE is_active = true; -- 普通索引 CREATE INDEX idx_storyboard_sound_effects_storyboard_id ON storyboard_sound_effects(storyboard_id); CREATE INDEX idx_storyboard_sound_effects_status ON storyboard_sound_effects(status); CREATE INDEX idx_storyboard_sound_effects_type ON storyboard_sound_effects(effect_type); CREATE INDEX idx_storyboard_sound_effects_checksum ON storyboard_sound_effects(checksum); CREATE INDEX idx_storyboard_sound_effects_active ON storyboard_sound_effects(storyboard_id, is_active) WHERE is_active = true; ``` ## 使用示例 ### 1. 创建背景音乐 ```python POST /api/v1/storyboards/{storyboard_id}/sound-effects { "audioUrl": "https://storage.example.com/audio/bgm.mp3", "checksum": "abc123...", "storagePath": "/audio/bgm.mp3", "effectType": 1, // background_music "effectName": "轻音乐", "volume": 0.6, "loopEnabled": true, "startTime": 0.0, "duration": 60.0, "fileSize": 512000, "format": "mp3", "sampleRate": 44100, "bitRate": 128000, "storageProvider": "minio", "aiModel": "audio-gen-v1", "aiPrompt": "轻松的背景音乐", "status": 2, // completed "isActive": true } ``` ### 2. 叠加多个音效 ```python # 1. 添加背景音乐 POST /api/v1/storyboards/{storyboard_id}/sound-effects { "effectType": 1, "effectName": "背景音乐", ... } # 2. 添加环境音(雨声) POST /api/v1/storyboards/{storyboard_id}/sound-effects { "effectType": 2, "effectName": "雨声", ... } # 3. 添加特效音(开门声) POST /api/v1/storyboards/{storyboard_id}/sound-effects { "effectType": 3, "effectName": "开门声", ... } # 4. 获取所有激活音效 GET /api/v1/storyboards/{storyboard_id}/sound-effects/active // 返回:[bgm, ambient, sfx] ``` ### 3. 切换音效版本 ```python # 1. 生成新版本的背景音乐 POST /api/v1/storyboards/{storyboard_id}/sound-effects { "effectType": 1, "effectName": "新背景音乐", ... } # 2. 激活新版本 POST /api/v1/sound-effects/{new_sound_effect_id}/activate // 旧版本自动停用 ``` ### 4. 调整音效参数 ```python PATCH /api/v1/sound-effects/{sound_effect_id} { "volume": 0.4, "fadeInDuration": 5.0, "fadeOutDuration": 5.0 } ``` ## 相关文档 - ADR: `docs/server/adrs/06-storyboard-sound-effect-service.md` - 技术栈规范: jointo-tech-stack skill ## 测试建议 1. 创建不同类型的音效 2. 测试多版本管理和激活切换 3. 测试文件去重机制 4. 测试播放参数更新 5. 测试权限控制 6. 测试删除音效(验证引用计数) ## 后续工作 - 添加单元测试 - 添加集成测试 - 前端 UI 实现 - AI 音效生成服务集成