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.
10 KiB
10 KiB
Changelog: 剧本解析自动创建分镜对白记录
日期: 2026-02-09
类型: Feature Enhancement
影响范围: 剧本解析功能
关联: 2026-02-09-screenplay-ai-parse-format-fix.md
功能描述
在剧本 AI 解析过程中,自动将 storyboards[].dialogue 数据写入 storyboard_dialogues 表,实现分镜对白的自动化管理。
背景
现状
- AI 解析剧本时会返回
storyboards数组,每个分镜包含dialogue字段 - 之前的实现仅将
dialogue存储在storyboards.meta_data中 - 前端需要从
meta_data中提取对白数据,不够规范
问题
- 数据冗余: 对白数据存储在
meta_data中,不利于查询和管理 - 缺少结构化: 无法利用
storyboard_dialogues表的完整功能(角色关联、时间管理、情绪标记等) - 功能受限: 无法支持多条对白、对白类型、TTS 配音等高级功能
解决方案
实现逻辑
文件: server/app/services/screenplay_service.py
方法: _create_storyboards_from_ai()
新增代码:
# 7. 创建分镜对白记录(如果有 dialogue 数据)
dialogue_content = sb_data.get('dialogue', '').strip()
if dialogue_content:
from app.models.storyboard_resource import StoryboardDialogue, DialogueType
from app.utils.id_generator import generate_uuid
# 解析对白类型(默认为旁白)
dialogue_type = DialogueType.NARRATION # 默认为旁白
# 尝试从 meta_data 中获取对白类型
dialogue_type_str = sb_data.get('meta_data', {}).get('dialogue_type')
if dialogue_type_str:
type_mapping = {
'normal': DialogueType.NORMAL,
'inner_monologue': DialogueType.INNER_MONOLOGUE,
'narration': DialogueType.NARRATION
}
dialogue_type = type_mapping.get(dialogue_type_str.lower(), DialogueType.NARRATION)
# 创建对白记录
dialogue = StoryboardDialogue(
dialogue_id=generate_uuid(),
storyboard_id=created.storyboard_id,
character_id=None, # AI 解析暂不关联具体角色
character_name=None,
content=dialogue_content,
dialogue_type=dialogue_type,
sequence_order=0, # 默认为第一条对白
start_time=start_time,
duration=estimated_duration,
emotion=sb_data.get('meta_data', {}).get('emotion'),
notes=None,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc)
)
self.db.add(dialogue)
await self.db.flush()
logger.info(
"创建分镜对白: storyboard_id=%s, dialogue_id=%s, type=%s, content_length=%d",
created.storyboard_id,
dialogue.dialogue_id,
dialogue.dialogue_type_str,
len(dialogue_content)
)
数据映射
AI 返回格式 → 数据库字段
| AI 返回字段 | 数据库字段 | 类型 | 说明 |
|---|---|---|---|
dialogue |
content |
TEXT |
对白内容(必填) |
meta_data.dialogue_type |
dialogue_type |
SMALLINT |
对白类型:1=普通对白, 2=内心OS, 3=旁白 |
start_time |
start_time |
NUMERIC(10,3) |
开始时间(秒) |
estimated_duration |
duration |
NUMERIC(10,3) |
时长(秒) |
meta_data.emotion |
emotion |
VARCHAR |
情绪标记(可选) |
| - | sequence_order |
INTEGER |
顺序号(默认 0) |
| - | character_id |
UUID |
角色 ID(暂为 NULL) |
| - | character_name |
VARCHAR |
角色名称(暂为 NULL) |
默认值策略
| 字段 | 默认值 | 说明 |
|---|---|---|
dialogue_type |
NARRATION (3) |
默认为旁白,因为 AI 解析时通常无法准确识别对白类型 |
sequence_order |
0 |
默认为第一条对白,后续可手动调整 |
character_id |
NULL |
AI 解析暂不关联具体角色,需要用户手动关联 |
character_name |
NULL |
同上 |
emotion |
NULL |
仅当 AI 返回时才填充 |
notes |
NULL |
保留给用户手动添加备注 |
使用示例
AI 返回数据示例
{
"storyboards": [
{
"shot_number": 1,
"title": "开场镜头",
"description": "海边日出,女孩独自站在沙滩上",
"dialogue": "这是一个关于勇气和梦想的故事...",
"shot_size": "full_shot",
"camera_movement": "static",
"estimated_duration": 10,
"characters": ["女孩"],
"locations": ["海边"],
"meta_data": {
"dialogue_type": "narration",
"emotion": "平静"
}
}
]
}
数据库记录
storyboards 表:
INSERT INTO storyboards (
storyboard_id, project_id, title, description,
shot_size, camera_movement, estimated_duration,
start_time, end_time, order_index, meta_data
) VALUES (
'019c4212-08db-7b32-8b00-b24e66817410',
'019c4212-08db-7b32-8b00-b24e66817411',
'开场镜头',
'海边日出,女孩独自站在沙滩上',
3, -- full_shot
1, -- static
10.000,
0.000,
10.000,
0,
'{"dialogue": "这是一个关于勇气和梦想的故事...", "emotion": "平静"}'
);
storyboard_dialogues 表:
INSERT INTO storyboard_dialogues (
dialogue_id, storyboard_id, content, dialogue_type,
sequence_order, start_time, duration, emotion,
created_at, updated_at
) VALUES (
'019c4212-08db-7b32-8b00-b24e66817412',
'019c4212-08db-7b32-8b00-b24e66817410',
'这是一个关于勇气和梦想的故事...',
3, -- NARRATION
0,
0.000,
10.000,
'平静',
NOW(),
NOW()
);
功能特性
1. 自动化创建
- ✅ AI 解析剧本时自动创建对白记录
- ✅ 无需手动操作,提升效率
- ✅ 保持数据一致性
2. 类型识别
- ✅ 支持三种对白类型:普通对白、内心OS、旁白
- ✅ 默认为旁白(最常见的场景)
- ✅ 可通过
meta_data.dialogue_type自定义
3. 时间同步
- ✅ 对白的
start_time和duration与分镜保持一致 - ✅ 便于后续的时间轴管理和 TTS 配音
4. 扩展性
- ✅ 预留
character_id字段,支持后续关联角色 - ✅ 预留
emotion字段,支持情绪标记 - ✅ 预留
notes字段,支持用户备注
后续优化建议
1. 角色关联
问题: 当前 character_id 为 NULL,无法关联具体角色
建议:
- 在 AI 解析时尝试识别对白的说话者
- 根据
storyboards[].characters自动关联角色 - 提供 API 支持用户手动关联角色
实现示例:
# 尝试从分镜的角色列表中匹配
characters_in_shot = sb_data.get('characters', [])
if characters_in_shot and len(characters_in_shot) == 1:
# 如果只有一个角色,自动关联
char_name = characters_in_shot[0]
char_id = character_id_map.get(char_name)
if char_id:
dialogue.character_id = char_id
dialogue.character_name = char_name
2. 多条对白支持
问题: 当前仅支持单条对白(sequence_order=0)
建议:
- 支持 AI 返回多条对白(数组格式)
- 自动分配
sequence_order - 支持对白的时间分段
AI 返回格式:
{
"storyboards": [
{
"dialogues": [
{
"content": "你好,我是小明",
"character": "小明",
"dialogue_type": "normal",
"start_time": 0,
"duration": 2
},
{
"content": "你好,我是小红",
"character": "小红",
"dialogue_type": "normal",
"start_time": 2,
"duration": 2
}
]
}
]
}
3. 对白类型智能识别
问题: 当前默认为旁白,可能不准确
建议:
- 使用 NLP 技术识别对白类型
- 根据对白内容和上下文判断
- 提供置信度评分
识别规则:
- 包含"他想"、"她想"等关键词 → 内心OS
- 包含"旁白"、"解说"等关键词 → 旁白
- 其他 → 普通对白
4. TTS 配音集成
问题: 对白创建后需要手动触发 TTS
建议:
- 在对白创建后自动触发 TTS 任务
- 生成
storyboard_voiceovers记录 - 支持批量配音
测试验证
测试场景 1: 基本对白创建
输入:
{
"storyboards": [
{
"title": "测试分镜",
"dialogue": "这是一段测试对白",
"estimated_duration": 5
}
]
}
预期结果:
- ✅ 创建 1 条
storyboards记录 - ✅ 创建 1 条
storyboard_dialogues记录 - ✅
dialogue_type= 3 (NARRATION) - ✅
sequence_order= 0 - ✅
duration= 5.000
测试场景 2: 自定义对白类型
输入:
{
"storyboards": [
{
"title": "测试分镜",
"dialogue": "我在想什么呢...",
"meta_data": {
"dialogue_type": "inner_monologue",
"emotion": "困惑"
}
}
]
}
预期结果:
- ✅
dialogue_type= 2 (INNER_MONOLOGUE) - ✅
emotion= "困惑"
测试场景 3: 空对白处理
输入:
{
"storyboards": [
{
"title": "测试分镜",
"dialogue": ""
}
]
}
预期结果:
- ✅ 创建 1 条
storyboards记录 - ❌ 不创建
storyboard_dialogues记录(对白为空)
影响范围
受影响的功能
- ✅ 剧本 AI 解析 (
POST /api/v1/screenplays/{id}/parse) - ✅ 分镜创建逻辑 (
ScreenplayService._create_storyboards_from_ai) - ✅ 分镜详情查询(需要关联查询
storyboard_dialogues)
数据库变更
- ✅ 新增数据写入:
storyboard_dialogues表 - ✅ 无表结构变更(使用现有表)
API 变更
- ✅ 无 API 接口变更
- ✅ 响应数据可能包含对白信息(如果前端查询)
相关文档
- 对白模型:
server/app/models/storyboard_resource.py:StoryboardDialogue - 分镜服务:
server/app/services/screenplay_service.py:_create_storyboards_from_ai - 数据库迁移:
server/alembic/versions/20260203_1527_*_add_storyboard_resources_tables.py - 前端 Mock:
client/src/mocks/storyboard-dialogues.ts
总结
本次增强实现了剧本解析时自动创建分镜对白记录的功能,将对白数据从 meta_data 迁移到专用的 storyboard_dialogues 表,提升了数据结构的规范性和可扩展性。
核心价值:
- 自动化: 无需手动创建对白记录
- 结构化: 利用专用表管理对白数据
- 可扩展: 支持角色关联、TTS 配音等高级功能
- 向后兼容: 保留
meta_data中的对白数据,不影响现有功能