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

分镜音效服务实现

日期: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 - 注册 StoryboardSoundEffectSoundEffectType
  • 更新 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

测试建议

  1. 创建不同类型的音效
  2. 测试多版本管理和激活切换
  3. 测试文件去重机制
  4. 测试播放参数更新
  5. 测试权限控制
  6. 测试删除音效(验证引用计数)

后续工作

  • 添加单元测试
  • 添加集成测试
  • 前端 UI 实现
  • AI 音效生成服务集成