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

Changelog: 对白格式优化 - 支持多对白和角色关联

日期: 2026-02-09
类型: Feature Enhancement
影响范围: AI Skill Prompt, Screenplay Service, AI Tasks
状态: 已完成


变更概述

优化剧本解析 AI Skill 中的对白格式:

  1. dialogue 改为 dialogues 数组,支持一个分镜包含多个对白
  2. 对白对象包含 contentdialogue_typecharacter_nameemotionsequence_order 字段
  3. 支持对白与角色的直接关联和情绪标记

问题背景

旧版格式问题

AI Skill 返回格式

{
  "storyboards": [
    {
      "dialogue": "你好,世界!"  //  简单字符串,无法关联角色,不支持多对白
    }
  ]
}

问题

  1. 一个分镜只能有一个对白(实际场景中可能有多个角色对话)
  2. 无法直接指定对白的角色
  3. 无法明确指定对白类型(普通对白、内心OS、旁白)
  4. 无法标记对白的情绪
  5. 导致 storyboard_dialogues.character_idcharacter_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 可以根据对白内容自动推断情绪

向后兼容性

完全兼容旧版格式

支持三种格式:

  1. 新版(v1.5.0): dialogues 数组
  2. v1.4.0: dialogue 单个对象
  3. 旧版: 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

影响范围

修改的文件

  1. server/app/resources/ai_skills/screenplay_parsing.md (v1.4.0 → v1.5.0)
  2. server/app/services/screenplay_service.py
    • 修改 _create_storyboards_from_ai() 方法(支持 dialogues 数组)
    • 更新 _has_dialogue() 辅助方法
  3. 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

后续优化建议

  1. 前端展示优化

    • 在分镜编辑器中显示对白的角色头像
    • 支持对白类型的可视化标识(普通对白、内心OS、旁白)
    • 显示情绪标记(表情图标)
  2. AI 提示词优化

    • 增加对白类型识别的示例
    • 强化角色名称匹配的准确性
    • 提供情绪识别的指导
  3. 数据迁移

    • 为历史数据中的对白补充角色关联(基于内容解析)

维护人员: AI Agent
最后更新: 2026-02-09