You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.2 KiB
8.2 KiB
分镜音效服务实现
日期: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 权限
数据库表结构
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. 创建背景音乐
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. 叠加多个音效
# 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. 切换音效版本
# 1. 生成新版本的背景音乐
POST /api/v1/storyboards/{storyboard_id}/sound-effects
{ "effectType": 1, "effectName": "新背景音乐", ... }
# 2. 激活新版本
POST /api/v1/sound-effects/{new_sound_effect_id}/activate
// 旧版本自动停用
4. 调整音效参数
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
测试建议
- 创建不同类型的音效
- 测试多版本管理和激活切换
- 测试文件去重机制
- 测试播放参数更新
- 测试权限控制
- 测试删除音效(验证引用计数)
后续工作
- 添加单元测试
- 添加集成测试
- 前端 UI 实现
- AI 音效生成服务集成