☰
自动生成结构化剧本:从模板设计到AI落地的完整实践
2026/10/21 3:09:57 网站建设 项目流程

写剧本这件事,我以前总觉得是纯手艺活,灵感到了才能动笔。直到有一次要在一晚上交出三条短视频脚本,才发现光靠灵感根本不靠谱。后来我把目光转向自动生成结构化剧本——不是让AI随手吐一段故事,而是让它严格按照分场、分幕、对白、冲突、钩子的固定骨架去产出内容。这套做法解决的不只是效率问题,更让剧本从一开始就具备可直接拍摄、剪辑和评审的规范格式。如果你也在做短视频口播、微短剧、广告策划、游戏剧情,或者帮客户出创意方案,想减少从“脑海里的一个点”到“能开拍的剧本”之间的空转,这篇文章值得看完。我会把这个项目从设计思路、技术选型到踩坑修复的完整过程,一次性讲透。

1. 项目起源:为什么是“结构化”而不是单纯写剧本

1.1 没有结构的AI文本只能算素材

很多人试过大模型写故事,输入一个题目,三五秒就能冒出几百字的桥段。但真拿去拍摄或做分镜时根本没法用:没有场景号、没有内外景标注、不知道人物在这个位置想达成什么目标,情绪转折也藏在长段落里。编剧行话说“一场戏必须有起承转合”,这句话落到实操里就是结构。自动生成结构化剧本的本质,是给自由散漫的文本套上一套工业级的“施工图”。先定梁、再定柱、最后填装修材料,编剧只需要在结构上做艺术加工。

举个例子,普通AI生成一段情节可能是:

她走进餐厅,看到窗边的座位被占,心里很不舒服。

这句话信息量太少。到了结构化剧本里,至少会变成:

  • 场景编号:3-2
  • 地点:某餐厅·靠窗座位
  • 时间:傍晚
  • 人物目标:女主想确认前任是否在跟踪自己
  • 动作:扫视全场,停顿,攥紧包带
  • 对白:无
  • 冲突:目标与阻碍(座位被占)被看见
  • 时长:20秒

两种文本的差别,就是“故事碎片”和“生产物料”的差别。自动生成结构化剧本的关键,不是让模型更有文采,而是让模型每次输出的内容都能被拆成可执行的字段。

1.2 谁最需要这套东西

我根据自己接到的需求统计了一下,四类场景的诉求完全不同,但对“结构”的依赖都极其明显:

场景类型典型时长对结构的要求自动生成时最容易踩的坑
短视频口播/种草15-90秒开头钩子 + 痛点 + 方案 + 行动号召,顺序不能乱语言书面化,不像说人话
微短剧单集2-5分钟冷开场 + 反转 + 悬念结尾,每集最后必须留钩子场景切太碎,情绪线断裂
游戏支线任务3-10分钟交互对话树 + 多分支,分支要可控分支越写越多,状态前后矛盾
广告TVC/宣传片30-120秒情绪曲线 + 卖点植入,画面描述与文案分离画面和口播文案混在一起

这套需求我们在技术上是分开处理的。短视频和广告偏重“线性模板”,我会把它定义成顺序固定的JSON数组;游戏和互动短剧偏重“分支结构”,我则会使用节点+跳转引用的方式。模板层因此成了整个项目最重要的一环,这一节放在下一段展开说。

2. 整体方案设计:如何让大语言模型当一个听话的“码字员工”

2.1 模板层:先把剧本的骨头定义清楚

自动生成结构化剧本不是把提示词写长就行,而是要让模型明确知道“每一块输出往哪个格子填”。我的做法是设计一份剧本Schema,核心包括元信息、人物表、场景列表三层。

meta(剧本元信息)负责控制主旨:

{ "title": "剧名", "type": "short_film | short_video | game_quest | ad", "logline": "一句话故事", "total_est_seconds": 180, "target_audience": "目标受众" }

character(人物表)负责全局设定一致性,生成每个场景前都会注入:

{ "character": [ { "name": "林姐", "age": 32, "job": "运营组长", "goal": "证明自己的方案可行", "speech_style": "短句,爱反问,不说专业术语", "taboo": "不会直接认错" } ] }

scene(场景列表)是主体,每个场景都包含拍摄单位需要的最小信息:

字段含义为什么必须要
scene_id场景唯一编号后续剪辑和拍摄单全靠它定位
location地点场景表、分镜表直接引用
time_of_day白天/夜晚/黄昏影响灯光和情绪
characters出场角色角色预算和演员统筹
objective本场角色的核心目标防止AI写一场废戏
conflict冲突/阻碍没有冲突就没有推进
action关键动作描写镜头有画面可用
dialogue对白列表每条对白带说话人
plot_hook本场结尾钩子保证观众愿意看下一段

选择JSON而不是自然语言段落当输出格式,是因为JSON可以做到“字段级校验”。比如要求场景数量不少于4个、每个场景必须有conflict字段、对白总字数在200-400字之间,程序能一条条自动检查,不合格就重新生成。

2.2 生成层:提示词不是聊天,是生产参数

模型没有义务猜你脑子里想要什么,所以我把提示词拆成“身份指令 + 产出规格 + 少样本示例 + 本次任务参数”四段。这段的写法直接决定生成质量。

身份指令要少而具体:

你是一个有十年商业剧本写作经验的编剧,擅长把抽象创意转化成可直接拍摄的剧本。

产出规格要可验证:

  • 只输出一个JSON对象,不要任何解释性文字
  • 不使用Markdown代码块包裹
  • 每个场景都必须包含conflict字段
  • 所有对白必须口语化,单句不超过30字
  • 单集目标时长按每秒4-5字控制

少样本示例的目的是“锁定格式感”。我通常会在系统提示词里放一个两场景的完整JSON输出,让模型模仿字段名称和嵌套层级,这样解析层不会出错。如果只靠指令,模型还是可能突然换字段名。

本次任务参数则放在用户消息里,例如:

{ "task": "生成一条60秒短视频口播脚本", "topic": "如何把卧室改造成高效办公区", "tone": "轻松接地气,不要贩卖焦虑", "cta": "引导点击评论区链接拿改造清单" }

实际操作中,我还会把temperature调到0.5左右。自动生成结构化剧本的场景里,我们宁可要保守稳定的输出,也不希望模型放飞自我,输出一堆有文采但不符合格式的东西。

2.3 校验层:让程序盯住AI的质量底线

提示词写得再好,模型也会失手。我采用“校验失败就带着错误信息重试”的套路,模仿软件工程里契约设计的思维方式。主要校验以下内容:

  • 是否能够解析为合法JSON
  • 必填字段是否齐全,字段类型是否正确
  • 场景数量是否落在预设范围
  • 对白单句长度是否超限
  • 角色表里出现的人是否都在场景中被使用
  • 是否存在明显重复的场景开头

重试时不要把原始错误原样丢给模型,而是只提取最关键的报错信息,告诉模型“缺少xxx字段”。这样第二次生成的命中率会显著提升。极端情况下,连续重试三次仍失败,就降级输出半结构化文本,至少保住人工修复的基础。

3. 实操过程:从零搭一个可复用的剧本生成器

3.1 第一步:选定一个足够小的场景,把模板写细

做这种项目,我强烈建议你先选一个自己能手动完成的小场景,比如“60秒口播脚本”,而不是一开始就挑战两小时电影。短视频口播需要的结构很简单,我按“钩子-痛点-方案-证明-行动号召”五段式来扣:

部分内容要求建议时长
hook0-3秒内出现反常现象或结果5秒
pain_point说出目标用户正在经历的具体麻烦10秒
solution给出方法或产品,说清“怎么做”25秒
proof提供前后对比、数字或使用感受15秒
cta明确让用户做什么5秒

这段模板我直接在提示词里用表格结构描述给模型,但它输出的时候还是需要JSON格式。五段之间的字数比例很重要,如果模型生成的hook只有一句话但pain_point占了半篇,人工就得大量删改。

3.2 第二步:写好一套可执行的提示词模板

下面是我实际在用的提示词模板。它本身不会变化太多,真正变动的只有任务参数:

系统提示词: 你是一个短视频剧本写手。你必须严格按照schema输出JSON。 schema定义: { "title": "字符串", "sections": [ { "name": "hook", "purpose": "用一句话制造停顿感", "content": "口播词", }, { "name": "pain_point", "purpose": "描述目标用户具体痛点", "content": "口播词,不超过三句话", }, ... ] } 1. 只输出JSON,不要解释; 2. 口播词要像真人说话,允许使用停顿词,比如“说实话”“你发现没有”; 3. 每句不超过25字; 4. 不要输出任何Markdown符号。

提示词的细节越量化,模型越听话。“说人话”这种模糊要求没有用,改成“允许使用‘你发现没有’这种口语连接词”,效果立刻不一样。

3.3 第三步:用Python把生成、解析、校验串起来

我不是建议人人都写一遍接口,但自己留一套最小实现会很有价值。下面这个例子基于通用的大模型API封装,你只需要把call_llm替换成自己接入的模型服务:

# script_generator.py import json import re def call_llm(messages, temperature=0.5): # 这里接入你自己的模型服务 # 返回字符串 raise NotImplementedError def clean_json(raw: str) -> str: # 去掉可能包装JSON的markdown代码块 raw = raw.strip() if raw.startswith("```"): raw = re.sub(r"^```[a-zA-Z]*\n", "", raw) raw = re.sub(r"\n```$", "", raw) return raw def validate(data: dict) -> dict: required = ["title", "sections"] if not all(key in data for key in required): missing = [key for key in required if key not in data] raise ValueError(f"missing: {missing}") if len(data["sections"]) < 3: raise ValueError("sections should be >= 3") return data def generate_script(topic: str, retry: int = 3) -> dict: system = "你是短视频剧本写手,严格按schema输出JSON,不要输出解释。" user = f"主题:{topic}\n请生成60秒口播剧本。" messages = [ {"role": "system", "content": system}, {"role": "user", "content": user}, ] for attempt in range(retry): raw = call_llm(messages, temperature=0.5) try: raw = clean_json(raw) data = json.loads(raw) data = validate(data) return data except Exception as e: messages.append({"role": "assistant", "content": raw}) messages.append({ "role": "user", "content": f"生成失败:{e}\n请重新输出一个合法JSON,不要包含其他内容。" }) raise RuntimeError("连续重试三次仍未通过校验")

带错误信息重试这个机制是整个项目的命脉。没有它,AI偶尔犯一次格式错误,你就得人工改半天;接上它之后,大部分错误都能在第二次修复。

3.4 第四步:角色一致性与对白优化

做微短剧和游戏剧情时,最大的难点不是格式,而是角色“前后不像一个人”。我的办法是在系统提示词里加入角色卡,并且在生成当前场景之前,把该角色此前做过的关键决定浓缩成两三条摘要喂回去。模型不知道“这个女人前两场已经发过火了”,但角色摘要会告诉它。

对白方面,初代输出经常像说明书。后来我在生成完成之后,单独加了一个“对白重写”步骤:

  • 第一步:让模型生成带动作提示和情绪的对白
  • 第二步:把所有旁白和动作描写暂时剥离,只保留对白文本
  • 第三步:再让模型用指定角色的说话风格重写对白,要求“像人聊天的感觉,不要像新闻播报”

这样拆两步,比一次性生成要稳得多。第一次生成管信息量,第二次重写管语气。

3.5 第五步:人工修订要有固定清单

自动生成不代表直接可用,我给自己定了一套每次生成后必跑的检查清单:

  • 每一场戏的主角目标是否清晰?
  • 冲突是否来自“目标与阻碍”的真实对抗,而不是单纯嘴硬?
  • 最后有没有留下一个让观众好奇的钩子?
  • 对白有没有超过角色该有的信息量?
  • 是否出现AI爱用的“意识到”“下定决心”等无效描写,改成“拿起手机又放下”这种可拍动作。

通常我只需要修改2-3处转折点,剩余内容就能直接进拍摄流程。相比从零开始写,单条脚本的时间从两小时压缩到二十分钟,修改比重大概是30%。

4. 实际踩坑与排查:这些问题几乎每次都会遇到

4.1 生成内容“假大空”,不够具体

这是最让我头疼的问题。比如让它写“文案感觉很专业”,模型会写“高效赋能”“专业闭环”,但观众听不懂。这是提示词缺少对词汇和句长的约束引起的。

我后来的解决办法是在提示词里增加“禁用词列表”:

  • 禁止使用“赋能”“闭环”“助力”“极致”等营销黑话
  • 禁止出现形容词堆砌,比如“非常”“十分”“超级”
  • 每句话必须指出一个可被镜头拍到的动作或真实场景

试过之后,生成质量明显落地。不是模型变聪明了,而是你把它往具体方向上逼了一把。

4.2 JSON解析失败,连着报错

模型有时候会在JSON前后加markdown代码块,有时候中途截断,有时候把“JSON”这几个字也当内容输出来。我的排查顺序是:

  1. 先用clean_json去首尾多余内容
  2. 如果json.loads还是失败,就把原始输出里的错误信息拼到下一次请求里
  3. 如果连续失败,检查是否有一个字段的引号或括号没闭合,再提示模型“你上一次输出的JSON不完整,请补齐”

另一个隐藏坑是:模型可能在JSON字符串里加入换行导致对齐错误。因此我在Schema定义里尽量用简单类型,不允许嵌套过深的数组,把复杂度控制在两层以内。

4.3 长剧本超出上下文窗口

剧本越长,模型越容易忘掉前面的设定。强行把所有内容放进一个请求,轻则输出烂尾,重则直接长度溢出。我把生成过程分成“大纲-分幕-分场”三级:

  • 第一级:让模型生成三幕剧整体大纲,每幕只保留目标、核心冲突和结局
  • 第二级:每幕生成2-3个关键场景摘要
  • 第三级:对照摘要逐场生成详细内容,并且把当前场景的“幕摘要”和“此前场景摘要”作为上下文传入

每一场生成完,我就把这一场的摘要追加到全局摘要文件里。这个方式类似“滚动大纲”,能保证单次请求的信息量始终可控。

4.4 所有角色说话都是一个味

角色同质化在自动生成里特别常见。原因是模型没有记住每个角色的“说话方式”,只会输出标准书面语。我建立了一个角色语音表,系统提示词里放着,需要谁就动态拼谁:

角色平均句长常用口头禅绝对不能说的话说话习惯
老板6-10字“说重点”任何客套话喜欢用祈使句
程序员15-25字“理论上可以”确定性的肯定句爱加“但是”
新人助手8-15字“我查一下”下结论句尾常用“吧”

加完这个表,不同角色之间终于能听着像不同的人。实际运营时,这个表要不断根据试拍结果补充。

另外整理一份速查表:

现象原因解决方案
台词书面化缺少口语词约束添加允许使用的连接词
JSON报错输出夹杂markdown或截断清洗+带错误重试
场景衔接不上上下文太长被遗忘滚动摘要+分场生成
角色同质化缺乏角色风格记忆角色语音表
冲突不够强只写情绪没有行动要求写“行动+阻碍”字段

5. 继续往下走:让剧本生成接入内容生产流水线

5.1 从结构化剧本自动转成分镜脚本

当剧本以JSON保存后,分镜生成就变成了一个字段映射问题。每个场景的action字段可以转成“画面描述”,dialogue字段转成“拍摄台词”,我再用一套简单的景别映射规则决定镜头:

  • 场景开始:全景,建立地点关系
  • 人物对话中的情绪转折:中近景或特写
  • 关键道具出现:推镜或特写

这个粒度虽然还不能直接给摄影组用,但作为拍摄前沟通底稿,已经能省掉大部分整理时间。

5.2 扩展互动叙事与游戏对话树

游戏支线剧情需要多分支结构。我用统一的对话节点来组织:

{ "node_id": "n1", "speaker": "铸剑的老人家", "dialogue": "你手里的剑,是从哪来的?", "options": [ {"text": "是家里长辈留下的", "next_node": "n3"}, {"text": "路上捡的,有问题吗", "next_node": "n4"} ] }

模型每次只生成一个节点和最多三个选项,再逐个生成下一层节点,避免一次生成几十条分支导致漏设定。这样人工只需要检查关键分支的跳转逻辑,不用阅读整片森林。

5.3 接入设定库,让长篇项目不“吃书”

做长篇剧集时,角色关系、时间线、伏笔随时可能冲突。我的方案是单独维护一个“设定库”,用JSON记录人物关系、重大事件、当前线索状态。每次生成某场景前,程序先从设定库中检索与该场景相关的实体和事件,再拼进提示词里。

比如设定库里写“林姐在第三集发现方案被否的真相”,那么生成第五集涉及她情绪反应时,模型就会带着这条设定,不会突然把方案被否写成“正常调整”。这一步对短项目来说有点重,但一旦进入连续制作阶段,收益非常明显。

我自己现在的习惯是:每次生成完剧本,不会直接拿去用,而是先读一遍“场景冲突列表”,只修改那些真正影响转折的地方。自动化的意义不是替代编剧,而是把格式搭建、分场重复劳动吃进去,让人把精力留在需要创造力的关键节点。如果你也想做类似工具,我建议从小场景、小模板开始,先把结构定细一点,再慢慢扩大规模。最后一个小窍门:把每次调好的提示词和JSON Schema存成版本化模板,三个月后你会发现自己攒下的不是几段prompt,而是一套可以复用的内容生产基础设施。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询