# AI 剧本解析提示词 > **文档版本**:v2.0 > **最后更新**:2026-02-06 > **重要变更**:支持两阶段解析,解决Token限制问题 --- ## 目录 1. [解析策略](#解析策略) 2. [阶段1:提取元素](#阶段1提取元素) 3. [阶段2:拆解分镜](#阶段2拆解分镜) 4. [字段说明](#字段说明) 5. [枚举值对照表](#枚举值对照表) 6. [后端集成](#后端集成) 7. [重要提示](#重要提示) --- ## 解析策略 为了解决长剧本的Token限制问题,采用**两阶段解析**策略: ### 阶段1:提取全局元素(1次AI调用) - 输入:完整剧本文本 - 输出:角色、场景、道具及其标签 - Token消耗:约15,000 tokens ### 阶段2:分批拆解分镜(N次AI调用,可并行) - 输入:剧本片段 + 已提取的元素列表 - 输出:该片段的分镜数组(含对白) - Token消耗:每批约5,000-8,000 tokens ### 用户体验流程 ``` 用户上传剧本 ↓ 阶段1:提取元素 ↓ 前端显示元素列表(用户可审核/修改) ↓ 用户确认 → 开始拆解分镜 ↓ 阶段2:分批拆解分镜(实时进度) ↓ 完成:查看完整分镜列表 ``` --- ## 阶段1:提取元素 ### 完整提示词(阶段1) 将以下内容复制给AI使用: ````markdown # 系统角色 你是一个专业的影视剧本分析专家,擅长从剧本中提取角色、场景、道具信息,并识别它们的不同状态和变体。 --- # 任务说明 请分析以下剧本,提取所有角色、场景、道具信息,并为每个元素识别不同的状态标签。 ## 1. 角色(Characters) - **识别所有出现的角色** - **为每个角色提取不同的年龄段/状态标签**(如:少年、青年、老年、受伤状态等) - **描述每个标签的具体特征**(年龄、服装、外貌、情绪状态等) - **标注角色类型**:主角(main)、配角(supporting)、群演(extra) - **标注是否为画外音角色**(如纪录片解说员、旁白) **示例**: - 角色名:孙悟空 - 标签1:少年(15岁,穿着布衣,活泼好动) - 标签2:青年(30岁,身穿金甲,英勇果敢) ## 2. 场景(Locations) - **识别所有拍摄场景** - **为每个场景提取不同的时间/氛围标签**(如:白天、夜晚、春天、冬天等) - **描述每个标签的具体特征**(光照、天气、季节、氛围等) **示例**: - 场景名:花果山 - 标签1:白天(阳光明媚,鸟语花香) - 标签2:夜晚(月光下,宁静神秘) ## 3. 道具(Props) - **识别所有重要道具** - **为每个道具提取不同的状态标签**(如:崭新、破损、生锈等) - **描述每个标签的具体特征** - **标注道具类型**: - `interactive`(互动道具):角色会使用/操作的道具 - `set_dressing`(布景道具):场景装饰性道具 - **标注归属**: - 互动道具:标注归属角色(`owner_character`) - 布景道具:标注归属场景(`owner_location`) **示例**: - 道具名:金箍棒 - 类型:interactive - 归属角色:孙悟空 - 标签1:崭新(刚打造,金光闪闪) - 标签2:破损(战斗后,有裂纹) - 道具名:石桌 - 类型:set_dressing - 归属场景:花果山 - 标签1:风化(经年累月,长满青苔) --- # 输出格式要求 请严格按照以下JSON格式返回结果: ```json { "characters": [ { "name": "角色名", "description": "角色描述", "role_type": "main|supporting|extra", "is_offscreen": false, "meta_data": { "gender": "male|female", "species": "人类|动物|其他", "personality": "性格描述" } } ], "character_tags": { "角色名": [ { "tag_key": "youth", "tag_label": "少年", "description": "15岁的孙悟空,穿着布衣", "meta_data": { "age": 15, "clothing": "布衣", "mood": "活泼" } } ] }, "locations": [ { "name": "场景名", "location": "地点", "description": "场景描述", "meta_data": {} } ], "location_tags": { "场景名": [ { "tag_key": "daytime", "tag_label": "白天", "description": "阳光明媚的花果山", "meta_data": { "lighting": "natural", "weather": "sunny" } } ] }, "props": [ { "name": "道具名", "description": "道具描述", "prop_type": "interactive|set_dressing", "owner_character": "角色名(互动道具)", "owner_location": "场景名(布景道具)", "meta_data": { "material": "材质", "size": "尺寸" } } ], "prop_tags": { "道具名": [ { "tag_key": "new", "tag_label": "崭新", "description": "刚打造的金箍棒", "meta_data": { "condition": "new" } } ] } } ``` --- # 剧本内容 {在这里插入剧本文本} --- # 重要提示 1. **标签必须有明确的视觉差异**:不同标签应该在画面上有明显区别 2. **道具分类准确**:互动道具归属角色,布景道具归属场景 3. **元数据完整**:尽可能提供详细的meta_data信息 4. **名称一致性**:确保所有名称拼写一致,后续阶段会引用这些名称 ```` --- ### 输出格式(阶段1) 返回JSON格式,结构如下: ```json { "characters": [ { "name": "角色名", "description": "角色描述", "role_type": "main|supporting|extra", "is_offscreen": false, "meta_data": { "gender": "male|female", "species": "人类|动物|其他", "personality": "性格描述" } } ], "character_tags": { "角色名": [ { "tag_key": "youth", "tag_label": "少年", "description": "15岁的孙悟空,穿着布衣", "meta_data": { "age": 15, "clothing": "布衣", "mood": "活泼" } } ] }, "locations": [ { "name": "场景名", "location": "地点", "description": "场景描述", "meta_data": {} } ], "location_tags": { "场景名": [ { "tag_key": "daytime", "tag_label": "白天", "description": "阳光明媚的花果山", "meta_data": { "lighting": "natural", "weather": "sunny" } } ] }, "props": [ { "name": "道具名", "description": "道具描述", "prop_type": "interactive|set_dressing", "owner_character": "角色名(互动道具)", "owner_location": "场景名(布景道具)", "meta_data": { "material": "材质", "size": "尺寸" } } ], "prop_tags": { "道具名": [ { "tag_key": "new", "tag_label": "崭新", "description": "刚打造的金箍棒", "meta_data": { "condition": "new" } } ] } } ``` --- ## 阶段2:拆解分镜 ### 完整提示词(阶段2) 将以下内容复制给AI使用: ````markdown # 系统角色 你是一个专业的影视分镜师,擅长将剧本拆解为可执行的分镜脚本。你需要根据已识别的角色、场景、道具,将剧本片段拆解为详细的分镜。 --- # 已识别的元素列表 ## 角色 {在这里插入角色列表及其标签,格式如下:} - 孙悟空 - 少年:15岁,穿着布衣,活泼好动 - 青年:30岁,身穿金甲,英勇果敢 - 菩提祖师 - 老年:白发苍苍,身穿道袍,仙风道骨 ## 场景 {在这里插入场景列表及其标签,格式如下:} - 花果山 - 白天:阳光明媚,鸟语花香 - 夜晚:月光下,宁静神秘 - 斜月三星洞 - 夜晚:火把摇曳,光影交错 ## 道具 {在这里插入道具列表及其标签,格式如下:} - 金箍棒(互动道具,归属:孙悟空) - 崭新:金光闪闪,光芒四射 - 石桌(布景道具,归属:花果山) - 风化:表面有青苔和裂纹 - 蒲团(布景道具,归属:斜月三星洞) - 陈旧:边缘磨损,但依然整洁 --- # 任务说明 请将以下剧本片段拆解为分镜脚本。 ## 拆解要求 为每个分镜提供: ### 1. 基本信息 - **标题**:简短描述(如"孙悟空初登场") - **描述**:画面内容详细描述 - **拍摄描述**:景深、运镜方式、镜头语言、拍摄技巧 ### 2. 影视专业参数 - **景别(shot_size)**:1-8(见下方枚举表) - **运镜(camera_movement)**:1-9(见下方枚举表) - **预估时长(estimated_duration)**:秒 ### 3. 元素关联 - **角色**:使用已识别的角色名和标签名 - **场景**:使用已识别的场景名和标签名 - **道具**:使用已识别的道具名和标签名 - 为每个元素指定: - `action`:动作描述(如"大笑"、"奔跑"、"挥舞") - `position`:画面位置(left/center/right/background/foreground) - `is_visible`:是否可见(画外音设为false) ### 4. 对白(Dialogues) - **角色名**:说话的角色(必须是已识别的角色) - **内容**:对白文本 - **对白类型**:1=普通对白, 2=内心OS, 3=旁白 - **顺序**:在分镜中的顺序(从0开始) - **情绪**:高兴/悲伤/愤怒等(可选,用于TTS) --- # 枚举值对照表 ## 景别(shot_size) 1. extreme_wide_shot - 大远景(建立场景) 2. wide_shot - 远景(展示环境) 3. full_shot - 全景(全身) 4. medium_shot - 中景(腰部以上) 5. medium_close_up - 中近景(胸部/肩部以上) 6. close_up - 特写(面部) 7. extreme_close_up - 大特写(局部细节) 8. over_shoulder - 过肩镜头(对话场景) ## 运镜(camera_movement) 1. static - 固定 2. pan - 摇镜(水平旋转) 3. tilt - 俯仰(垂直旋转) 4. dolly - 推拉(前后移动) 5. zoom - 变焦(焦距变化) 6. tracking - 跟踪(跟随主体) 7. arc - 环绕(圆周运动) 8. crane - 升降(垂直移动/摇臂) 9. handheld - 手持(纪录片风格) ## 对白类型(dialogue_type) 1. normal - 普通对白(角色之间的正常对话) 2. inner_monologue - 内心OS(角色的内心独白,其他角色听不到) 3. narration - 旁白(画外音、解说、回忆旁白等) --- # 输出格式要求 请严格按照以下JSON格式返回结果: ```json { "storyboards": [ { "title": "分镜标题", "description": "画面描述", "shooting_description": "拍摄描述", "shot_size": 4, "camera_movement": 1, "estimated_duration": 5.5, "order_index": 1, "start_time": 0.0, "end_time": 5.5, "meta_data": { "lighting": "自然光", "weather": "晴天", "time_of_day": "上午", "camera_angle": "仰拍", "lens": "广角" }, "characters": [ { "name": "孙悟空", "tag_label": "少年", "action": "挥舞金箍棒", "position": "center", "is_visible": true, "order": 0 } ], "locations": [ { "name": "花果山", "tag_label": "白天", "order": 0 } ], "props": [ { "name": "金箍棒", "tag_label": "崭新", "action": "被挥舞", "position": "foreground", "order": 0 } ], "dialogues": [ { "character_name": "孙悟空", "content": "今日我便要闯出一番天地!", "dialogue_type": 1, "sequence_order": 0, "emotion": "兴奋" } ] } ] } ``` --- # 剧本片段 {在这里插入剧本片段文本} --- # 重要提示 1. **必须使用已识别的元素**:角色、场景、道具的名称必须与上方列表完全一致 2. **必须使用已识别的标签**:tag_label必须是该元素的已识别标签 3. **动作描述要具体**:如"大笑"、"奔跑"、"挥舞",而不是"动作" 4. **位置要明确**:使用标准位置值(left/center/right/background/foreground) 5. **对白结构化**:每条对白独立,包含完整信息 6. **顺序连续**:order_index从1开始连续递增,时间轴连续 ```` --- ### 输出格式(阶段2) 返回JSON格式,结构如下: ```json { "storyboards": [ { "title": "分镜标题", "description": "画面描述", "shooting_description": "拍摄描述", "shot_size": 4, "camera_movement": 1, "estimated_duration": 5.5, "order_index": 1, "start_time": 0.0, "end_time": 5.5, "meta_data": { "lighting": "自然光", "weather": "晴天" }, "characters": [ { "name": "孙悟空", "tag_label": "少年", "action": "挥舞金箍棒", "position": "center", "is_visible": true, "order": 0 } ], "locations": [ { "name": "花果山", "tag_label": "白天", "order": 0 } ], "props": [ { "name": "金箍棒", "tag_label": "崭新", "action": "被挥舞", "position": "foreground", "order": 0 } ], "dialogues": [ { "character_name": "孙悟空", "content": "今日我便要闯出一番天地!", "dialogue_type": 1, "sequence_order": 0, "emotion": "兴奋" } ] } ] } ``` --- ## 字段说明 ### 角色字段(Characters) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | name | string | ✅ | 角色名称 | | description | string | ✅ | 角色描述 | | role_type | string | ✅ | 角色类型:main(主角)/supporting(配角)/extra(群演) | | is_offscreen | boolean | ✅ | 是否为画外音角色(不出现在画面中) | | meta_data | object | ✅ | 额外元数据(性别、物种、性格等) | ### 角色标签字段(Character Tags) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | tag_key | string | ✅ | 标签键(如youth/adult/old) | | tag_label | string | ✅ | 标签显示名称(如"少年"/"青年"/"老年") | | description | string | ✅ | 标签详细描述(年龄、服装、外貌等) | | meta_data | object | ✅ | 额外元数据(age/clothing/mood等) | ### 场景字段(Locations) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | name | string | ✅ | 场景名称 | | location | string | ⚪ | 场景地点 | | description | string | ✅ | 场景描述 | | meta_data | object | ✅ | 额外元数据 | ### 场景标签字段(Location Tags) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | tag_key | string | ✅ | 标签键(如daytime/night) | | tag_label | string | ✅ | 标签显示名称(如"白天"/"夜晚") | | description | string | ✅ | 标签详细描述(光照、天气、氛围等) | | meta_data | object | ✅ | 额外元数据(lighting/weather/season等) | ### 道具字段(Props) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | name | string | ✅ | 道具名称 | | description | string | ✅ | 道具描述 | | prop_type | string | ✅ | 道具类型:interactive(互动道具)/set_dressing(布景道具) | | owner_character | string | ⚪ | 归属角色(互动道具必填) | | owner_location | string | ⚪ | 归属场景(布景道具必填) | | meta_data | object | ✅ | 额外元数据(material/size/color等) | ### 道具标签字段(Prop Tags) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | tag_key | string | ✅ | 标签键(如new/old/damaged) | | tag_label | string | ✅ | 标签显示名称(如"崭新"/"陈旧"/"破损") | | description | string | ✅ | 标签详细描述 | | meta_data | object | ✅ | 额外元数据(condition/appearance等) | ### 分镜字段(Storyboards) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | title | string | ✅ | 分镜标题 | | description | string | ✅ | 画面描述 | | shooting_description | string | ⚪ | 拍摄描述(景深、运镜方式、镜头语言) | | shot_size | integer | ⚪ | 景别(1-8,见枚举表) | | camera_movement | integer | ⚪ | 运镜(1-9,见枚举表) | | estimated_duration | number | ⚪ | 预估时长(秒) | | order_index | integer | ✅ | 顺序索引(从1开始) | | start_time | number | ✅ | 开始时间(秒) | | end_time | number | ✅ | 结束时间(秒) | | meta_data | object | ✅ | 额外元数据(lighting/weather/time_of_day等) | | characters | array | ✅ | 关联的角色数组 | | locations | array | ✅ | 关联的场景数组 | | props | array | ✅ | 关联的道具数组 | | dialogues | array | ✅ | 对白数组 | ### 分镜角色关联字段 | 字段 | 类型 | 必填 | 说明 | 数据库字段 | |------|------|------|------|-----------| | name | string | ✅ | 角色名称(必须是已识别的角色) | element_name | | tag_label | string | ✅ | 标签名称(必须是该角色的已识别标签) | tag_label | | action | string | ⚪ | 动作描述(如"大笑"/"奔跑") | action_description | | position | string | ⚪ | 画面位置(left/center/right/background/foreground) | spatial_position | | is_visible | boolean | ✅ | 是否在画面内(画外音设为false) | is_visible | | order | integer | ✅ | 显示顺序 | display_order | ### 分镜场景关联字段 | 字段 | 类型 | 必填 | 说明 | 数据库字段 | |------|------|------|------|-----------| | name | string | ✅ | 场景名称(必须是已识别的场景) | element_name | | tag_label | string | ✅ | 标签名称(必须是该场景的已识别标签) | tag_label | | order | integer | ✅ | 显示顺序 | display_order | ### 分镜道具关联字段 | 字段 | 类型 | 必填 | 说明 | 数据库字段 | |------|------|------|------|-----------| | name | string | ✅ | 道具名称(必须是已识别的道具) | element_name | | tag_label | string | ✅ | 标签名称(必须是该道具的已识别标签) | tag_label | | action | string | ⚪ | 动作描述(如"被挥舞"/"被打开") | action_description | | position | string | ⚪ | 画面位置(left/center/right/background/foreground) | spatial_position | | order | integer | ✅ | 显示顺序 | display_order | ### 对白字段(Dialogues) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | character_name | string | ✅ | 说话的角色名称 | | content | string | ✅ | 对白内容 | | dialogue_type | integer | ✅ | 对白类型(1=普通对白, 2=内心OS, 3=旁白) | | sequence_order | integer | ✅ | 在分镜中的顺序(从0开始) | | emotion | string | ⚪ | 情绪标记(用于TTS生成和时长计算,如"高兴"/"悲伤"/"愤怒") | **注意**: - **无需返回时长字段**:台词时长由后端根据字数、语速、情绪自动计算 - **情绪标记很重要**:影响语速调整(高兴/兴奋语速快,悲伤/疲惫语速慢) - **对白类型影响时长**:旁白比普通对白慢15%,内心OS慢10% --- ## 枚举值对照表 ### 角色类型(role_type) | 数值 | 字符串值 | 说明 | |------|---------|------| | - | main | 主角 | | - | supporting | 配角 | | - | extra | 群演 | ### 道具类型(prop_type) | 数值 | 字符串值 | 说明 | |------|---------|------| | - | interactive | 互动道具(角色会使用/操作) | | - | set_dressing | 布景道具(场景装饰性) | ### 景别(shot_size) | 数值 | 字符串值 | 说明 | |------|---------|------| | 1 | extreme_wide_shot | 大远景(建立场景) | | 2 | wide_shot | 远景(展示环境) | | 3 | full_shot | 全景(全身) | | 4 | medium_shot | 中景(腰部以上) | | 5 | medium_close_up | 中近景(胸部/肩部以上) | | 6 | close_up | 特写(面部) | | 7 | extreme_close_up | 大特写(局部细节) | | 8 | over_shoulder | 过肩镜头(对话场景) | ### 运镜(camera_movement) | 数值 | 字符串值 | 说明 | |------|---------|------| | 1 | static | 固定 | | 2 | pan | 摇镜(水平旋转) | | 3 | tilt | 俯仰(垂直旋转) | | 4 | dolly | 推拉(前后移动) | | 5 | zoom | 变焦(焦距变化) | | 6 | tracking | 跟踪(跟随主体) | | 7 | arc | 环绕(圆周运动) | | 8 | crane | 升降(垂直移动/摇臂) | | 9 | handheld | 手持(纪录片风格) | ### 对白类型(dialogue_type) | 数值 | 字符串值 | 说明 | |------|---------|------| | 1 | normal | 普通对白(角色之间的正常对话) | | 2 | inner_monologue | 内心OS(角色的内心独白,其他角色听不到) | | 3 | narration | 旁白(画外音、解说、回忆旁白等) | --- ## 后端集成 ### 阶段1:存储元素 ```python # Celery Worker 调用 async def store_elements(screenplay_id: UUID, parsed_data: Dict): """存储阶段1的解析结果""" # 1. 存储角色 character_id_map = {} for char_data in parsed_data['characters']: character = await screenplay_service.add_character( screenplay_id, char_data ) character_id_map[char_data['name']] = character.character_id # 2. 存储场景 location_id_map = {} for location_data in parsed_data['locations']: location = await screenplay_service.add_location( screenplay_id, location_data ) location_id_map[location_data['name']] = location.location_id # 3. 存储道具 prop_id_map = {} for prop_data in parsed_data['props']: prop = await screenplay_service.add_prop( screenplay_id, prop_data ) prop_id_map[prop_data['name']] = prop.prop_id # 4. 存储标签 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:存储分镜 ```python # Celery Worker 调用 async def store_storyboards( screenplay_id: UUID, storyboards_data: List[Dict], tag_id_maps: Dict ): """存储阶段2的解析结果""" storyboard_ids = await storyboard_service.create_storyboards_from_ai( screenplay_id=screenplay_id, storyboards_data=storyboards_data, tag_id_maps=tag_id_maps ) return storyboard_ids ``` --- ## 重要提示 ### 1. 标签设计原则 - **标签是元素的变体**:一个角色可以有多个年龄段标签,一个场景可以有多个时间标签 - **标签必须有明确的视觉差异**:不同标签应该在画面上有明显区别 - **标签用于分镜关联**:分镜不直接关联"孙悟空",而是关联"孙悟空-少年"这个标签 ### 2. 道具分类规则 - **互动道具**:角色会使用/操作的道具(如武器、工具、手机、钥匙) - 必须标注归属角色(`owner_character`) - 可以有动作描述(`action`) - **布景道具**:场景装饰性道具(如桌椅、花瓶、背景物品) - 必须标注归属场景(`owner_location`) - 通常无动作描述 ### 3. 对白处理 - **结构化数据**:对白必须是数组,每条对白独立 - **角色关联**:`character_name`必须是已识别的角色名称 - **顺序管理**:`sequence_order`从0开始,按对白出现顺序递增 - **情绪标记**:可选,但建议提供,用于TTS生成时的情感控制 ### 4. 分镜关联规则 - **必须使用已识别的元素**:角色、场景、道具的名称必须与阶段1提取的一致 - **必须使用已识别的标签**:`tag_label`必须是该元素的已识别标签 - **动作描述要具体**:如"大笑"、"奔跑"、"挥舞",而不是"动作" - **位置要明确**:使用标准位置值(left/center/right/background/foreground) ### 5. Token优化建议 - **阶段1**:尽可能详细,包含所有元素和标签 - **阶段2**:每批10-20个分镜,避免超过token限制 - **简化模式**:如果剧本很长,可以省略`emotion`字段,由后端推断 ### 6. 数据一致性 - **元素名称必须一致**:阶段2引用的元素名称必须与阶段1完全一致 - **标签名称必须一致**:阶段2引用的标签名称必须与阶段1完全一致 - **顺序索引连续**:分镜的`order_index`必须连续(1, 2, 3...) - **时间轴连续**:分镜的`start_time`和`end_time`应该连续 ### 7. 时长计算说明 **台词时长**: - AI **无需计算**台词时长 - 后端会根据以下因素自动计算: - 字数(中文字符数) - 语速(正常4.5字/秒) - 情绪(高兴/兴奋语速快,悲伤/疲惫语速慢) - 对白类型(旁白比普通对白慢15%) - 标点停顿(逗号0.25秒,句号0.5秒) **分镜时长**: - AI **无需计算**分镜时长 - 后端会根据以下因素自动计算: - 所有台词的总时长 - 台词间隔(0.5秒/条) - 景别(大远景5秒,特写1.5秒) - 运镜(环绕增加50%,固定无增加) - 缓冲时间(前后共1.5秒) **AI只需提供**: - 台词内容(`content`) - 情绪标记(`emotion`) - 对白类型(`dialogue_type`) - 景别(`shot_size`) - 运镜(`camera_movement`) 后端会自动计算并存储 `estimated_duration` 字段。 --- ## 示例文件 完整的示例JSON文件请参考:[screenplay-ai-parse-example.json](./screenplay-ai-parse-example.json)