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.3 KiB
8.3 KiB
Changelog: 对白格式优化 - 支持多对白和角色关联
日期: 2026-02-09
类型: Feature Enhancement
影响范围: AI Skill Prompt, Screenplay Service, AI Tasks
状态: ✅ 已完成
变更概述
优化剧本解析 AI Skill 中的对白格式:
- 将
dialogue改为dialogues数组,支持一个分镜包含多个对白 - 对白对象包含
content、dialogue_type、character_name、emotion、sequence_order字段 - 支持对白与角色的直接关联和情绪标记
问题背景
旧版格式问题
AI Skill 返回格式:
{
"storyboards": [
{
"dialogue": "你好,世界!" // ❌ 简单字符串,无法关联角色,不支持多对白
}
]
}
问题:
- 一个分镜只能有一个对白(实际场景中可能有多个角色对话)
- 无法直接指定对白的角色
- 无法明确指定对白类型(普通对白、内心OS、旁白)
- 无法标记对白的情绪
- 导致
storyboard_dialogues.character_id和character_name经常为NULL
解决方案
1. 更新 AI Skill Prompt (v1.5.0)
文件: server/app/resources/ai_skills/screenplay_parsing.md
新版格式:
{
"storyboards": [
{
"dialogues": [
{
"content": "师父,我们去哪里?",
"dialogue_type": 1,
"character_name": "孙悟空",
"emotion": "好奇",
"sequence_order": 0
},
{
"content": "去西天取经。",
"dialogue_type": 1,
"character_name": "唐僧",
"emotion": "平静",
"sequence_order": 1
}
]
}
]
}
字段说明:
content: 对白内容(必填)dialogue_type: 对白类型(必填)1= normal(普通对白)2= inner_monologue(内心OS)3= narration(旁白,character_name 为 null)
character_name: 角色名称(可选,旁白时为 null)emotion: 情绪标记(可选,如:开心、愤怒、悲伤、平静等)sequence_order: 对白顺序(必填,从 0 开始)
2. 更新 Screenplay Service
文件: server/app/services/screenplay_service.py
2.1 兼容三种格式
在 _create_storyboards_from_ai() 方法中添加格式兼容逻辑:
dialogues_data = sb_data.get('dialogues') or sb_data.get('dialogue')
# 标准化为数组格式
dialogues_list = []
if isinstance(dialogues_data, list):
# ✅ 新版格式:dialogues 是数组
dialogues_list = dialogues_data
elif isinstance(dialogues_data, dict):
# ⚠️ v1.4.0 格式:dialogue 是单个对象
dialogues_list = [dialogues_data]
elif isinstance(dialogues_data, str):
# ⚠️ 旧版格式:dialogue 是字符串
dialogues_list = [{'content': dialogues_data, 'dialogue_type': 3, 'character_name': None}]
# 遍历创建对白记录
for dialogue_data in dialogues_list:
# 解析 content, dialogue_type, character_name, emotion, sequence_order
# ...
2.2 更新辅助方法
def _has_dialogue(self, storyboard_data: Dict[str, Any]) -> bool:
"""判断分镜是否包含对白(兼容数组、对象、字符串格式)"""
# 优先检查 dialogues 数组(新版)
dialogues = storyboard_data.get('dialogues')
if dialogues and isinstance(dialogues, list) and len(dialogues) > 0:
for d in dialogues:
if isinstance(d, dict) and d.get('content', '').strip():
return True
return False
# 降级检查 dialogue 单个对象/字符串(旧版)
dialogue = storyboard_data.get('dialogue')
# ...
3. 更新 AI Tasks
文件: server/app/tasks/ai_tasks.py
统计对白数量(兼容三种格式):
dialogues_count = 0
for sb in parsed_data.get('storyboards', []):
# 优先检查 dialogues 数组(新版)
dialogues = sb.get('dialogues')
if dialogues and isinstance(dialogues, list):
for d in dialogues:
if isinstance(d, dict) and d.get('content', '').strip():
dialogues_count += 1
else:
# 降级检查 dialogue 单个对象/字符串(旧版)
dialogue = sb.get('dialogue')
if dialogue:
if isinstance(dialogue, str) and dialogue.strip():
dialogues_count += 1
elif isinstance(dialogue, dict) and dialogue.get('content', '').strip():
dialogues_count += 1
技术细节
对白类型映射
数据库枚举 (DialogueType):
class DialogueType(IntEnum):
NORMAL = 1 # 普通对白
INNER_MONOLOGUE = 2 # 内心OS
NARRATION = 3 # 旁白
情绪标记
数据库字段: storyboard_dialogues.emotion (VARCHAR)
示例值:
- 开心、愤怒、悲伤、平静、惊讶、恐惧、厌恶、期待等
- AI 可以根据对白内容自动推断情绪
向后兼容性
✅ 完全兼容旧版格式
支持三种格式:
- 新版(v1.5.0):
dialogues数组 - v1.4.0:
dialogue单个对象 - 旧版:
dialogue字符串
测试建议
1. 测试多对白场景
storyboard_data = {
"dialogues": [
{
"content": "师父,我们去哪里?",
"dialogue_type": 1,
"character_name": "孙悟空",
"emotion": "好奇",
"sequence_order": 0
},
{
"content": "去西天取经。",
"dialogue_type": 1,
"character_name": "唐僧",
"emotion": "平静",
"sequence_order": 1
}
],
"characters": ["孙悟空", "唐僧"]
}
# 预期结果:创建 2 条对白记录
2. 测试旁白
storyboard_data = {
"dialogues": [
{
"content": "西游记第一回,灵根育孕源流出。",
"dialogue_type": 3,
"character_name": null,
"emotion": null,
"sequence_order": 0
}
]
}
# 预期结果:
# - character_id: None
# - character_name: None
# - dialogue_type: NARRATION (3)
# - emotion: None
影响范围
修改的文件
- ✅
server/app/resources/ai_skills/screenplay_parsing.md(v1.4.0 → v1.5.0) - ✅
server/app/services/screenplay_service.py- 修改
_create_storyboards_from_ai()方法(支持 dialogues 数组) - 更新
_has_dialogue()辅助方法
- 修改
- ✅
server/app/tasks/ai_tasks.py- 更新对白统计逻辑
需要重启的服务
# 重启 Celery Worker(加载新的 AI Skill)
docker restart jointo-server-celery-ai
# 重启 FastAPI(加载新的 Service 逻辑)
docker restart jointo-server-app
预期效果
Before(旧版)
SELECT character_id, character_name, content, emotion, sequence_order
FROM storyboard_dialogues
WHERE storyboard_id = 'xxx';
-- 结果(单条对白,无角色关联)
character_id | character_name | content | emotion | sequence_order
-------------|----------------|----------------------|---------|---------------
NULL | NULL | 师父,我们去哪里? | NULL | 0
After(新版)
SELECT character_id, character_name, content, emotion, sequence_order
FROM storyboard_dialogues
WHERE storyboard_id = 'xxx'
ORDER BY sequence_order;
-- 结果(多条对白,有角色关联和情绪)
character_id | character_name | content | emotion | sequence_order
--------------------------------------|----------------|----------------------|---------|---------------
01936e8f-7b2a-7890-8f3e-123456789abc | 孙悟空 | 师父,我们去哪里? | 好奇 | 0
01936e8f-7b2a-7890-8f3e-987654321cba | 唐僧 | 去西天取经。 | 平静 | 1
后续优化建议
-
前端展示优化
- 在分镜编辑器中显示对白的角色头像
- 支持对白类型的可视化标识(普通对白、内心OS、旁白)
- 显示情绪标记(表情图标)
-
AI 提示词优化
- 增加对白类型识别的示例
- 强化角色名称匹配的准确性
- 提供情绪识别的指导
-
数据迁移
- 为历史数据中的对白补充角色关联(基于内容解析)
维护人员: AI Agent
最后更新: 2026-02-09