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.
 

16 KiB

AI 剧本解析字段映射对照表

文档版本:v1.0
最后更新:2026-02-06
用途:说明AI输出的JSON字段如何映射到数据库表字段


目录

  1. 阶段1:元素提取字段映射
  2. 阶段2:分镜拆解字段映射
  3. 字段不匹配问题
  4. 后端处理逻辑

阶段1:元素提取字段映射

1.1 角色字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name screenplay_characters name TEXT 角色名称
description screenplay_characters description TEXT 角色描述
role_type screenplay_characters role_type SMALLINT 角色类型:1=main, 2=supporting, 3=extra
is_offscreen screenplay_characters is_offscreen BOOLEAN 是否为画外音角色
meta_data screenplay_characters meta_data JSONB 额外元数据(性别、物种、性格等)

枚举值映射

  • role_type: "main" → 1, "supporting" → 2, "extra" → 3

1.2 角色标签字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
tag_key screenplay_element_tags tag_key TEXT 标签键(如youth/adult/old)
tag_label screenplay_element_tags tag_label TEXT 标签显示名称(如"少年"/"青年"/"老年")
description screenplay_element_tags description TEXT 标签详细描述
meta_data screenplay_element_tags meta_data JSONB 额外元数据(age/clothing/mood等)

后端自动填充字段

  • element_type: 1 (角色)
  • element_id: 从 character_id_map 获取
  • element_name: 从AI输出的角色名称获取
  • screenplay_id: 从上下文获取

1.3 场景字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name screenplay_locations name TEXT 场景名称
location screenplay_locations location TEXT 场景地点
description screenplay_locations description TEXT 场景描述
meta_data screenplay_locations meta_data JSONB 额外元数据

1.4 场景标签字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
tag_key screenplay_element_tags tag_key TEXT 标签键(如daytime/night)
tag_label screenplay_element_tags tag_label TEXT 标签显示名称(如"白天"/"夜晚")
description screenplay_element_tags description TEXT 标签详细描述
meta_data screenplay_element_tags meta_data JSONB 额外元数据(lighting/weather/season等)

后端自动填充字段

  • element_type: 2 (场景)
  • element_id: 从 location_id_map 获取
  • element_name: 从AI输出的场景名称获取

1.5 道具字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name screenplay_props name TEXT 道具名称
description screenplay_props description TEXT 道具描述
meta_data screenplay_props meta_data JSONB 额外元数据(material/size/color等)

⚠️ 字段缺失问题

  • AI输出包含 prop_type, owner_character, owner_location 字段
  • 数据库表 screenplay_props 不包含这些字段
  • 建议:将这些信息存储在 meta_data

meta_data 建议结构

{
  "material": "金属",
  "size": "可变",
  "prop_type": "interactive",
  "owner_character": "孙悟空",
  "owner_location": null
}

1.6 道具标签字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
tag_key screenplay_element_tags tag_key TEXT 标签键(如new/old/damaged)
tag_label screenplay_element_tags tag_label TEXT 标签显示名称(如"崭新"/"陈旧"/"破损")
description screenplay_element_tags description TEXT 标签详细描述
meta_data screenplay_element_tags meta_data JSONB 额外元数据(condition/appearance等)

后端自动填充字段

  • element_type: 3 (道具)
  • element_id: 从 prop_id_map 获取
  • element_name: 从AI输出的道具名称获取

阶段2:分镜拆解字段映射

2.1 分镜基本字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
title storyboards title TEXT 分镜标题
description storyboards description TEXT 画面描述
shooting_description storyboards shooting_description TEXT 拍摄描述
shot_size storyboards shot_size SMALLINT 景别(1-8)
camera_movement storyboards camera_movement SMALLINT 运镜(1-9)
estimated_duration storyboards estimated_duration NUMERIC(10,3) 预估时长(秒)
order_index storyboards order_index INTEGER 顺序索引
start_time storyboards start_time NUMERIC(10,3) 开始时间(秒)
end_time storyboards end_time NUMERIC(10,3) 结束时间(秒)
meta_data storyboards meta_data JSONB 额外元数据

后端自动填充字段

  • project_id: 从上下文获取
  • screenplay_id: 从上下文获取(可选)
  • storyboard_id: 应用层生成 UUID v7

2.2 分镜角色关联字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name storyboard_items element_name TEXT 角色名称(冗余)
tag_label storyboard_items tag_label TEXT 标签名称(冗余)
action storyboard_items action_description TEXT 动作描述
position storyboard_items spatial_position TEXT 画面位置
is_visible storyboard_items is_visible BOOLEAN 是否可见
order storyboard_items display_order INTEGER 显示顺序

⚠️ 字段名称不匹配

  • AI输出:action → 数据库:action_description
  • AI输出:position → 数据库:spatial_position
  • AI输出:order → 数据库:display_order

后端自动填充字段

  • item_type: 1 (ElementTag)
  • element_tag_id: 从 tag_id_maps['character_tags'] 获取
  • cover_url: 从标签关联的资源获取(可选)
  • z_index: 默认 0

2.3 分镜场景关联字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name storyboard_items element_name TEXT 场景名称(冗余)
tag_label storyboard_items tag_label TEXT 标签名称(冗余)
order storyboard_items display_order INTEGER 显示顺序

后端自动填充字段

  • item_type: 1 (ElementTag)
  • element_tag_id: 从 tag_id_maps['location_tags'] 获取
  • cover_url: 从标签关联的资源获取(可选)

2.4 分镜道具关联字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
name storyboard_items element_name TEXT 道具名称(冗余)
tag_label storyboard_items tag_label TEXT 标签名称(冗余)
action storyboard_items action_description TEXT 动作描述
position storyboard_items spatial_position TEXT 画面位置
order storyboard_items display_order INTEGER 显示顺序

后端自动填充字段

  • item_type: 1 (ElementTag)
  • element_tag_id: 从 tag_id_maps['prop_tags'] 获取
  • cover_url: 从标签关联的资源获取(可选)

2.5 对白字段映射

AI输出字段 数据库表 数据库字段 类型 必填 说明
character_name storyboard_dialogues character_name TEXT 说话的角色名称
content storyboard_dialogues content TEXT 对白内容
dialogue_type storyboard_dialogues dialogue_type SMALLINT 对白类型(1/2/3)
sequence_order storyboard_dialogues sequence_order INTEGER 顺序(从0开始)
emotion storyboard_dialogues emotion TEXT 情绪标记

后端自动填充字段

  • storyboard_id: 从上下文获取
  • character_id: 从 character_id_map 获取(可选)
  • dialogue_id: 应用层生成 UUID v7

枚举值映射

  • dialogue_type: 1=normal, 2=inner_monologue, 3=narration

字段不匹配问题

问题1:分镜关联字段名称不一致

AI输出

{
  "action": "大笑",
  "position": "center",
  "order": 0
}

数据库字段

action_description TEXT,
spatial_position TEXT,
display_order INTEGER

解决方案:后端在存储时进行字段名称映射

# 后端映射逻辑
storyboard_item = StoryboardItem(
    action_description=char_data.get('action'),  # action → action_description
    spatial_position=char_data.get('position'),  # position → spatial_position
    display_order=char_data.get('order', 0)      # order → display_order
)

问题2:道具分类字段缺失

AI输出

{
  "name": "金箍棒",
  "prop_type": "interactive",
  "owner_character": "孙悟空",
  "owner_location": null
}

数据库表screenplay_props不包含 prop_type, owner_character, owner_location 字段

解决方案:将这些信息存储在 meta_data

# 后端存储逻辑
prop = ScreenplayProp(
    name=prop_data['name'],
    description=prop_data['description'],
    meta_data={
        **prop_data.get('meta_data', {}),
        'prop_type': prop_data.get('prop_type'),
        'owner_character': prop_data.get('owner_character'),
        'owner_location': prop_data.get('owner_location')
    }
)

问题3:缺少 tag_key 字段

AI输出

{
  "tag_key": "youth",
  "tag_label": "少年"
}

数据库表screenplay_element_tags包含 tag_key 字段

结论:无问题,AI输出已包含该字段


后端处理逻辑

阶段1:存储元素

async def store_parsed_elements(
    self,
    screenplay_id: UUID,
    parsed_data: Dict[str, Any]
) -> Dict[str, Any]:
    """存储 AI 解析的剧本元素"""
    
    # 1. 存储角色
    character_id_map = {}
    for char_data in parsed_data.get('characters', []):
        # 枚举值映射
        role_type_map = {'main': 1, 'supporting': 2, 'extra': 3}
        role_type = role_type_map.get(char_data['role_type'], 2)
        
        character = await self.repository.add_character(
            screenplay_id,
            {
                'name': char_data['name'],
                'description': char_data['description'],
                'role_type': role_type,
                'is_offscreen': char_data.get('is_offscreen', False),
                'meta_data': char_data.get('meta_data', {})
            }
        )
        character_id_map[char_data['name']] = character.character_id
    
    # 2. 存储道具(处理缺失字段)
    prop_id_map = {}
    for prop_data in parsed_data.get('props', []):
        # 将 prop_type, owner_character, owner_location 存入 meta_data
        meta_data = prop_data.get('meta_data', {})
        if 'prop_type' in prop_data:
            meta_data['prop_type'] = prop_data['prop_type']
        if 'owner_character' in prop_data:
            meta_data['owner_character'] = prop_data['owner_character']
        if 'owner_location' in prop_data:
            meta_data['owner_location'] = prop_data['owner_location']
        
        prop = await self.repository.add_prop(
            screenplay_id,
            {
                'name': prop_data['name'],
                'description': prop_data['description'],
                'meta_data': meta_data
            }
        )
        prop_id_map[prop_data['name']] = prop.prop_id
    
    # 3. 存储标签(包含 tag_key)
    tag_id_maps = await tag_service.store_tags(
        screenplay_id,
        parsed_data,
        character_id_map,
        location_id_map,
        prop_id_map
    )
    
    return {
        'character_id_map': character_id_map,
        'location_id_map': location_id_map,
        'prop_id_map': prop_id_map,
        'tag_id_maps': tag_id_maps
    }

阶段2:存储分镜

async def create_storyboards_from_ai(
    self,
    screenplay_id: UUID,
    storyboards_data: List[Dict],
    tag_id_maps: Dict
) -> List[UUID]:
    """从 AI 解析结果创建分镜"""
    
    for storyboard_data in storyboards_data:
        # 1. 创建分镜记录
        storyboard = Storyboard(
            screenplay_id=screenplay_id,
            title=storyboard_data['title'],
            description=storyboard_data['description'],
            # ... 其他字段
        )
        created_storyboard = await self.repository.create(storyboard)
        
        # 2. 创建角色关联(字段名称映射)
        for char_data in storyboard_data.get('characters', []):
            map_key = f"{char_data['name']}-{char_data['tag_label']}"
            element_tag_id = tag_id_maps['character_tags'].get(map_key)
            
            if element_tag_id:
                await self.repository.create_item(StoryboardItem(
                    storyboard_id=created_storyboard.storyboard_id,
                    item_type=1,  # ElementTag
                    element_tag_id=element_tag_id,
                    element_name=char_data['name'],
                    tag_label=char_data['tag_label'],
                    action_description=char_data.get('action'),      # action → action_description
                    spatial_position=char_data.get('position'),      # position → spatial_position
                    is_visible=char_data.get('is_visible', True),
                    display_order=char_data.get('order', 0)          # order → display_order
                ))
        
        # 3. 创建对白
        for dialogue_data in storyboard_data.get('dialogues', []):
            await self.repository.create_dialogue(StoryboardDialogue(
                storyboard_id=created_storyboard.storyboard_id,
                character_name=dialogue_data['character_name'],
                content=dialogue_data['content'],
                dialogue_type=dialogue_data['dialogue_type'],
                sequence_order=dialogue_data['sequence_order'],
                emotion=dialogue_data.get('emotion')
            ))

总结

完全匹配的字段

  1. 角色基本字段(name, description, role_type, is_offscreen, meta_data)
  2. 场景基本字段(name, location, description, meta_data)
  3. 标签字段(tag_key, tag_label, description, meta_data)
  4. 分镜基本字段(title, description, shot_size, camera_movement等)
  5. 对白字段(character_name, content, dialogue_type, sequence_order, emotion)

⚠️ 需要映射的字段

AI输出字段 数据库字段 处理方式
action action_description 后端映射
position spatial_position 后端映射
order display_order 后端映射

缺失的字段

AI输出字段 数据库表 解决方案
prop_type screenplay_props 存入 meta_data
owner_character screenplay_props 存入 meta_data
owner_location screenplay_props 存入 meta_data

建议

  1. 更新AI提示词:将 action, position, order 改为 action_description, spatial_position, display_order,与数据库字段名称保持一致
  2. 更新数据库表:为 screenplay_props 表添加 prop_type, owner_character, owner_location 字段(可选)
  3. 保持现状:后端在存储时进行字段名称映射和数据转换(推荐,无需修改AI提示词)

文档版本:v1.0
最后更新:2026-02-06