1. 把“小说改短剧”拆成五个 Skill,成功的概率才上去
最早我把一本 30 万字的小说整段丢给大模型,让它直接输出“短剧剧本 + 分镜”。结果很典型:前两集还算像样,从第三集开始人名开始飘,主角的性格从隐忍变成了莽撞,分镜里出现了小说里根本没有的场景,最后交付的文档看着很厚,但没人敢拿去开工。后来我复盘,问题不在模型能力,而在我把一件本来该分五步做的事,压成了一次对话。这套被称作 shuohao-skills 的技能包,本质上就是把 AI 短剧投产的五个环节固化成可复用的指令模块:小说拆解、角色设定、剧本生成、分镜拆解、投产包组装。它解决的不是“AI 能不能写剧本”,而是“AI 写出来的东西能不能直接进生产线”。适合三类人看:想用 AI 把小说改编成短剧的独立创作者、需要批量产出内容的小团队、以及已经试过一次性生成但被一致性问题和返工成本劝退的人。下面这套流程我在几个模拟项目里反复跑过,哪一步容易出错、哪一步能省时间,我会尽量讲清楚。
1.1 一次性生成为什么会崩:三个绕不过去的硬限制
第一个限制是上下文窗口的物理边界。一本网文动辄 30 万到 100 万字,就算模型能吃下,注意力在中后段也会明显衰减,前面交代的人物设定到第 20 章基本就“忘了”。这不是调参能解决的问题,是信息密度和注意力机制的天然特性。
第二个限制是任务耦合。拆故事骨架需要的是“判断力”,要决定哪些情节留、哪些砍;写角色卡需要的是“收敛力”,把模糊的人物小传压成可复现的视觉锚点;写分镜需要的是“拆解力”,把一个动作拆成 3 个 2 秒镜头。三种能力放在一个提示词里,模型会互相干扰,最后每一项都做到六十分。
第三个限制是不可回溯。一次性生成的结果是一整块文本,出了问题你不知道是哪一环错的。是骨架阶段就把主线搞歪了,还是剧本阶段把配角写崩了?没有中间产物,就只能整段重跑,成本翻倍。
踩过这个坑之后我的结论很直接:AI 做长内容,靠的不是更强的模型,而是更细的交接。每一步都产出结构化的中间文件,下一步只读这个文件,不读原文。
1.2 拆分依据:按交付物切分,不按工作流程切分
很多人拆 Skill 会按“先想、再写、后改”这种流程切,我不推荐。流程切法的毛病是每一环的输入输出都是模糊的,你没法判断这一步到底做完没有。我采用的是按交付物切:每个 Skill 必须产出一个有明确字段、能被下游直接消费的文件。
| Skill | 交付物 | 主要消费者 | 完成判据 |
|---|---|---|---|
| Skill 1 拆解 | 故事骨架 JSON | Skill 3 剧本 | 每集有冲突点、有钩子 |
| Skill 2 角色 | 角色卡 YAML | Skill 3、Skill 4 | 每个出场人物有视觉锚点 |
| Skill 3 剧本 | 分集分场稿 | Skill 4 分镜 | 每场有时长估算、有台词 |
| Skill 4 分镜 | 镜头表 CSV | Skill 5 组装 | 每镜有秒数、有画面描述 |
| Skill 5 组装 | 投产包目录 | 制作执行方 | 缺口清单为空 |
这张表是我后来补上的。最开始我没写“完成判据”这一列,结果经常出现“剧本写完了但分场时长加起来是 40 分钟,目标是 20 分钟”这种返工。判据必须是可量化的,不能是“质量达标”这种话。
1.3 五个 Skill 的串联关系:数据流决定顺序
顺序不能随便调。角色卡必须在剧本之前,因为剧本里的台词风格要跟角色卡里的“说话方式”字段对齐;分镜必须在剧本之后,因为镜头表要引用场号;投产包必须在最后,因为它要做一次全局缺口扫描。
我用一段伪配置说明这个串联关系,这也是我在实际项目里给每个 Skill 写的入口声明:
pipeline: short-drama-production skills: - id: novel-skeleton input: raw_text/*.txt, project_meta.yaml output: 01_skeleton/story.json - id: character-card input: 01_skeleton/story.json output: 02_characters/*.yaml - id: script-forge input: 01_skeleton/story.json, 02_characters/*.yaml output: 03_script/SxxExx.md - id: storyboard input: 03_script/SxxExx.md, 02_characters/*.yaml output: 04_board/SxxExx.csv - id: production-pack input: 01_* ~ 04_* output: 05_pack/注意每个 Skill 的 input 里都只出现了上一环的产物,没有一个 Skill 直接读原始小说。这是整套流程最关键的设计。原文只在 Skill 1 被读一次,之后全部靠结构化中间件传递,这样每一环的成本是可预测的,也能单独重跑。
一个容易被忽略的细节:
02_characters同时被 Skill 3 和 Skill 4 消费。写剧本时用它约束台词语气,拆分镜时用它约束外貌描述。同一个文件被两处引用,才能保证“台词里的她是她,镜头里的她也是她”。
2. Skill 1 小说拆解:把长篇压缩成能判断的结构化骨架
这个 Skill 最容易被人低估,觉得无非是“总结一下”。但总结和拆解是两回事。总结产出的是给人看的摘要,拆解产出的是给下游消费的结构。差别的核心在于:摘要可以含糊,结构不能含糊。
2.1 输入要按章节切片,并做滚动摘要回填
直接把整本小说喂进去,前 20% 和中间 20% 的质量差得很明显。我用的办法是滑动窗口加滚动摘要:每 10 章为一个批次,批次结束时让模型输出一段 300 字以内的“已读摘要”,这个摘要会带着全部人物和未解决的悬念,拼到下一批的上下文里。
# 简化示意:分批处理并累积摘要,避免上下文无限膨胀 state = {"summary": "", "characters": [], "open_threads": []} for batch in chunks(chapters, size=10): prompt = build_prompt( batch=batch, carry_over=state, # 上一批沉淀的摘要与人物名册 task="提取本批次的情节事件、人物变化、悬念钩子" ) result = call_model(prompt) state["summary"] = merge_summary(state["summary"], result["batch_summary"], max_len=300) state["characters"] = merge_unique(state["characters"], result["characters"]) state["open_threads"] = update_threads(state["open_threads"], result["threads"])滚动摘要的长度必须设上限,我一般卡 300 到 400 字。不设上限的话,跑到第 50 章时“摘要”本身就有一万多字了,等于没压缩。合并时要显式告诉模型“旧的摘要优先保留主线,新内容优先补充变化”,否则它会把早期的重要设定挤掉。
2.2 输出字段:决定能不能开工的就这七项
骨架 JSON 我固定输出七个字段。少一个,后面某一环就会卡住。
| 字段 | 作用 | 缺失后果 |
|---|---|---|
| logline | 一句话卖点 | 剧本没有统一调性 |
| 三幕主线 | 整体节奏 | 分集时集与集之间没有递进 |
| 爽点、钩子列表 | 每集结尾的抓手 | 剧情平,留不住人 |
| 人物名册 | 谁在什么时候出现 | 人物无限增加 |
| 场景清单 | 需要多少实景或素材 | 制作成本失控 |
| 时间线 | 顺序、回忆、插叙 | 分镜逻辑乱 |
| 可影视化评分 | 改编难度评估 | 做了一半发现拍不出来 |
其中“可影视化评分”是我自己加的,值得单独说。我按四个维度各打 1 到 5 分:场景复用度(同一场景出现的频率高不高)、特效依赖度(有没有大量玄幻、灾难场面)、对话占比(对白驱动的戏更好改)、群演规模(动辄几十人同框的戏成本高)。四项加起来低于 10 分的,我会重新评估要不要做,或者先做前几集试水。
2.3 取舍原则:砍情节的三个明确标准
拆解阶段最难的是砍。我的三条标准是:不推动主线的支线全砍、不改变人物关系的过场全砍、不产生新信息的对话全砍。判断“是否产生新信息”有个笨办法,把这段戏删掉,看后面的剧情还讲不讲得通,讲得通就删。
但有一条必须保留:人物性格的转折点。哪怕这场戏很短、很“水”,只要它解释了主角为什么从隐忍变成反击,就得留。短剧的观众对情节容错率比长视频低,但对“人设崩了”的容忍度更低。我一般会在骨架里单独标一个turning_points数组,剧本阶段强制要求这些点每集不超过一个,且必须落在集尾。
3. Skill 2 角色设定:确保 AI 生成的脸在二十个镜头里是同一个人
角色卡是整套流程里最容易被敷衍、又最容易出问题的一环。很多人写的角色卡是“女主,25 岁,美丽大方,性格坚强”,这种卡下游完全没法用:图像生成不知道长什么样,剧本不知道该怎么说话,分镜不知道该给什么景别。
3.1 字段设计:每个字段都要有“可复现”属性
我的角色卡固定包含九项,其中前三项是硬约束,缺了下游直接报错。
code: C01 name: 主角代号 identity: 身份与处境(一句话) visual_anchors: # 视觉锚点,必须可量化 hair: 齐耳短发,栗棕色,发尾微外翘 face: 偏圆脸,单眼皮,眉尾上挑 body: 身高约 165,偏瘦,肩线窄 outfit_main: 卡其色工装外套,内搭白色圆领,深色直筒裤 prop: 左手腕常年戴一只旧皮表 speech_style: # 说话方式,直接约束台词 sentence_len: 短句为主,单句不超过 20 字 tone: 少用形容词,喜欢反问 catchphrase: “行吧。” motivation: 表层欲望与深层需求 arc: 从 A 到 B 的三段式变化 relations: 与其他人物的关系及称呼 lock: # 一致性锁 ref_image_id: C01_v2 negative: 避免浓妆、避免长卷发、避免高跟鞋关键在于visual_anchors里没有出现任何一个“漂亮”“气质好”这类无法转成视觉描述的形容词。所有描述必须是摄影师听了能摆机位、画师看了能下笔的粒度。发色写“栗棕”不写“棕色”,因为纯棕在暖光下容易偏红;发尾写“微外翘”不写“自然”,因为“自然”这个词等于没说。
3.2 从人物小传到视觉锚点:三步压缩法
从小说里抠出来的往往是“她有一双会说话的眼睛”这种句子。转成视觉锚点要走三步:
- 删修饰,只留物理特征:会说话的眼睛 → 眼睛偏大,双眼皮,眼尾略下垂。
- 加可辨识细节:给每个主角配一个“记忆点”,比如一块旧皮表、一道浅疤、一个固定的发绳。这个细节要在分镜里反复出现,观众才记得住。
- 写负面约束:明确写出“不要什么”,比写“要什么”更有效。比如配角 C03 是个中年男性,负面里要写“不要胡须、不要眼镜”,否则每次生成都可能多一副眼镜。
我实测下来,负面约束能减少大约三到四成的角色漂移。这一步很多人省了,结果就是同一个角色在不同镜头里像两个人。
3.3 一致性如何向下游传递:一个文件、两处引用
角色卡不是写完就放着,它要在两个地方被强制引用。剧本阶段,每段台词生成前,把该场出场角色的speech_style拼进提示词;分镜阶段,每个镜头生成前,把visual_anchors和lock拼进提示词。
我用的做法是给每个角色卡算一个短哈希,剧本和分镜的每一行都带上这个哈希。返工时如果发现某个镜头的角色不对,直接查哈希就知道当时用的是哪一版角色卡。这个技巧在改了三次主角发型之后救了我一次,因为我能精确知道哪些镜头需要重跑,而不是全片返工。
提醒一句:角色卡一旦定稿,就不要在剧本阶段“顺手改一下”。改了就必须回填版本号,并且标记受影响的下游文件。我吃过这个亏,改完忘了标记,结果分镜里一半用旧版一半用新版,人物在两个镜头之间换了发型。
4. Skill 3 剧本生成:从大纲到分场,再到能念出口的台词
到了这一步,很多人会急着一口气把整集台词写出来。我的经验是必须分成三稿,而且三稿由三次独立的模型调用生成,不要合并。
4.1 三稿制:每稿只解决一个问题
第一稿是大纲稿,只输出每集的 logline、三到五个情节点、集尾钩子。这一稿不写台词,纯粹解决“这一集讲什么”。写完必须人工过一遍,因为这是全流程里性价比最高的人工介入点,改一句话的成本,比改到分镜阶段低两个数量级。
第二稿是分场稿,把情节点拆成场。每场标明场号、时间(日/夜)、地点、出场人物、本场事件、预估时长。分场稿的核心产出是时长表,把所有场的秒数加起来,跟目标时长对一下。对不上就现场调,别拖到分镜阶段。
第三稿是台词稿,只在这时才写台词。写的时候把角色卡的speech_style拼进去,逐场生成。
4.2 时长换算:一个能救命的对照表
短剧的时长控制非常严格,多 20 秒可能就影响投放。我用的换算基准是:中文对白每分钟约 220 到 260 字,加上动作描述和留白,剧本正文每分钟对应约 300 到 350 字。
| 单集目标时长 | 对白字数 | 场次数 | 镜头数(估) |
|---|---|---|---|
| 60 秒 | 220-260 | 2-3 | 12-18 |
| 90 秒 | 330-390 | 3-4 | 18-25 |
| 120 秒 | 440-520 | 4-5 | 25-35 |
| 180 秒 | 660-780 | 5-7 | 35-50 |
这张表我贴在项目文档最上面。每次分场稿写完先算一遍,超了就砍场,不要想着“到时候节奏快一点就行”,节奏一快观众跟不上,数据更差。
4.3 台词自检:六条能直接对照的清单
台词稿生成完之后,我会跑一遍自检。这六条是踩坑踩出来的,不是理论:
- 单句超过 25 字就拆。短剧观众是碎片时间在看,长句听不完。
- 一场戏里超过两句连续的书面语就改口语。“因此”“然而”“使得”这类词在短剧台词里基本不该出现。
- 每三句至少有一个信息增量或情绪变化,否则就是废话。
- 避免大段独白。真有内心戏,用旁白加空镜,别让演员站着说话。
- 称呼要统一。主角叫“周姐”就不能中途变“周女士”,除非剧情需要。
- 每场结尾留一个未完成动作或未回答问题,这是留人的最小单位。
我在实际项目里发现最容易被忽略的是第五条。模型很爱在不同场景换称谓,尤其是有第三人在场时会自动“变正式”。解决办法是在角色卡的relations字段里写死称呼规则,比如“对上级永远称职务,对同级永远称名字,不使用敬语”。
5. Skill 4 分镜拆解:把剧本变成能直接开工的镜头表
剧本是给演员看的,分镜是给拍摄或生成环节看的。这两者之间的转换,信息损失最大。我见过太多项目,剧本写得挺好,分镜一拆就散架,因为分镜里缺了“这个动作到底怎么拍”的具体描述。
5.1 镜头表字段:少一个字段就多一次沟通成本
我的镜头表固定用 CSV,字段如下。用 CSV 而不是 Markdown 表格,是因为它能直接被表格软件打开排序,也能被脚本处理。
| 字段 | 含义 | 示例 |
|---|---|---|
| shot_id | 镜号 | S01E01_SH03 |
| scene_id | 场号 | S01E01_SC02 |
| dur | 时长(秒) | 3 |
| shot_size | 景别 | 中近景 |
| angle | 机位角度 | 平视略仰 |
| move | 运镜 | 固定 |
| visual | 画面内容 | 她站在门口,手停在门把上 |
| action | 角色动作 | 缓慢转头看向走廊 |
| line | 台词、旁白 | “行吧。” |
| audio | 音效、音乐 | 走廊回声,低频铺底 |
| gen_prompt | 生成提示词 | 见下方映射规则 |
| char_lock | 角色锁哈希 | a3f2 |
dur这一列是硬约束。我要求单镜头时长在 2 到 6 秒之间,超过 6 秒必须拆,低于 2 秒要考虑合并。原因很实在:太长的镜头在生成端容易画面漂移,太短的镜头观众看不清。
5.2 提示词映射:从镜头表字段拼出生成描述
gen_prompt不是手写的,是拼出来的。拼装顺序固定:景别 + 机位 + 角色视觉锚点 + 动作 + 环境 + 光线 + 风格锚点 + 负面约束。这个顺序有讲究,主体信息放前面权重更高。
def build_gen_prompt(shot, char_cards, style_anchor): c = char_cards[shot["char_code"]] parts = [ shot["shot_size"], shot["angle"], shot["move"], f'{c["visual_anchors"]["hair"]},{c["visual_anchors"]["face"]}', f'身穿{c["visual_anchors"]["outfit_main"]}', shot["action"], shot["visual"], style_anchor["lighting"], style_anchor["film_look"], "负面:" + ",".join(c["lock"]["negative"]), ] return ",".join(p for p in parts if p)style_anchor是一个全片共享的配置文件,里面固定写光线基调、色调、镜头质感。这个文件的存在是为了解决“五个 Skill 各说各话”的问题,我后面会专门讲。
5.3 节奏约束:每 15 秒必须有一个视觉变化
短剧的节奏比长视频紧得多。我给分镜定了个土规矩:每 15 秒必须出现一次视觉变化,可以是景别切换、机位变化、光线变化、或者人物位置变化。做法很简单,按时间轴累加dur,每满 15 秒检查一次上一个镜头的景别,如果连续三个镜头是同一个景别,强制插入一个特写或全景。
另一个规矩是对话场景用正反打。两个人说话,不要一个镜头拍完,拆成 A 说话、B 反应、A 再说。这样镜头数上去了,节奏也活了。但要注意别过度,我一般控制在每组对话三到五个镜头,太多了剪辑会碎。
6. Skill 5 投产包组装:交付的是一套能开工的文件夹
前面四个 Skill 产出的都是散件,最后这一步是把散件打包,并且做一次全局体检。这一步看起来最没技术含量,实际上最能体现专业度。下游拿到的东西能不能直接用,全看这一步。
6.1 目录结构与命名:让陌生人也能看懂
05_pack/ ├── 00_README.md # 一页纸说明:怎么用这个包 ├── 01_skeleton/ │ └── story.json ├── 02_characters/ │ ├── C01.yaml │ └── ref/ # 角色参考图或参考图编号 ├── 03_script/ │ ├── S01E01.md │ └── S01E02.md ├── 04_board/ │ ├── S01E01.csv │ └── S01E02.csv ├── 05_assets/ │ ├── scene_list.csv # 场景清单与复用统计 │ └── gap_report.md # 缺口报告 └── 06_style/ └── style_anchor.yaml # 全片风格锚点命名规则我固定成SxxExx加类型后缀,版本号用_v1_v2。不要用日期做版本,因为同一天可能改三版。00_README.md一定要写,而且要写得像个说明书而不是目录,把“先看哪个、哪些字段是必须对齐的、改动了要通知谁”写清楚。我见过太多交付包,打开一看全是文件,没有人知道从哪下手。
6.2 缺口检查:用脚本扫一遍比人眼靠谱
缺口检查我写成一个简单的扫描逻辑,跑一遍就能列出问题。
issues = [] for ep in episodes: script = load(f"03_script/{ep}.md") board = load_csv(f"04_board/{ep}.csv") # 1. 剧本里的每一场,分镜里都要有镜头 for sc in extract_scenes(script): if sc not in set(board["scene_id"]): issues.append(f"{ep} 场 {sc} 在分镜表中缺失") # 2. 分镜里出现的角色,角色卡里都要有 for code in set(board["char_code"]): if not exists(f"02_characters/{code}.yaml"): issues.append(f"{ep} 引用了未定义角色 {code}") # 3. 时长要对得上 total = sum(float(x) for x in board["dur"]) target = project_meta["episode_seconds"][ep] if abs(total - target) / target > 0.1: issues.append(f"{ep} 时长偏差 {(total-target)/target:.0%}") write("05_assets/gap_report.md", issues)三条检查覆盖了八成的返工原因。时长偏差我卡 10%,超过就说明分场阶段算错了,回去改剧本比分镜阶段凑更省事。
6.3 版本回溯:改一处要知道影响哪几处
投产包做完不是终点,客户改需求是常态。我的做法是每个产物文件头写三行元信息:版本号、依赖文件的版本、生成时间。这样一旦上游改了,能顺着依赖链往下找。
举个例子,主角发型从短发改成长发,角色卡从 v2 升到 v3。要做的不是全片重跑,而是:查04_board里所有char_lock是旧哈希的镜头行,重拼gen_prompt,标红等重生成;查03_script里有没有提到发型的台词,有就改。这样一次改动的影响面是可枚举的,不会变成“全部推倒重来”。
7. 整条流水线跑下来,最容易在三种情况下出问题
前面讲的是怎么做,这一段讲我实际踩过的坑。这部分内容在文档里基本看不到,但恰恰是最影响效率的。
7.1 上下文衰减:跑到第七集,模型忘了第一集
长篇改编最典型的问题。前五集还挺连贯,到第七集突然给主角加了个小说里没有的弟弟。根因是骨架文件太长,剧本 Skill 每次只读了一部分。
我的修法是骨架分层:story.json里再拆出series_bible.json,只放“不可变事实”,包括人物名册、称呼规则、世界设定、核心悬念。写每一集时,series_bible无条件全量注入,分集骨架才按需读取。
# series_bible.json 的核心结构 characters_locked: - code: C01 name: 主角代号 aliases: [“小周”, “周姐”] # 所有允许出现的称呼 forbidden: [“周女士”, “老周”] world_rules: - 故事发生在当代城市,无超自然元素 - 时间跨度为七天 open_threads: - 旧皮表的来历(第 3 集提出,第 8 集揭晓)forbidden这个字段特别有用。模型爱自由发挥称呼,把禁用的称呼列出来,能挡掉大部分。
7.2 风格漂移:五个 Skill 各写各的
第二个坑更隐蔽。剧本阶段的台词偏文艺,分镜阶段的画面描述偏写实,最后拼起来像两个项目。根因是每个 Skill 的提示词是独立写的,没有共享的“调性锚”。
解决办法是建一个style_anchor.yaml,所有 Skill 都注入。
tone: 冷峻、克制、少煽情 dialogue: 短句,口语,不用成语 visual: 低饱和,冷色调,自然光为主 pacing: 每 15 秒一次视觉变化 forbidden: [慢镜头抒情, 大段旁白, 华丽形容词]这个文件不长,但它把五个 Skill 的产出统一到一个基准上。我的经验是,风格统一靠文件,不靠提示词里反复强调。你在五个提示词里各写一遍“保持冷峻”,不如让它们读同一个文件。
7.3 返工定位:从分镜倒推剧本的三步法
出了问题要快速定位是哪一环的锅。我的三步法:
第一步,看分镜和剧本是否一致。拿分镜表对照剧本,看场号、台词、动作是否对得上。对不上就是 Skill 4 的问题,局部重跑那几镜。
第二步,看剧本和骨架是否一致。看这一集的情节点有没有偏离大纲,人物动机有没有变。偏离了就是 Skill 3 的问题,重跑这一集的第二稿和第三稿。
第三步,看骨架和原著是否一致。这一步最少出问题,但一旦出问题最麻烦,因为要重跑整条链。所以我在 Skill 1 完成后一定要人工确认一次,宁可多花半小时。
这三步的顺序是有讲究的,从下游往上游查。因为下游的产物文件小、结构清楚,查起来快;上游的产物体量大,一上来就查上游容易陷进去。
8. 关于成本和效率,几个我实测出来的数字
不写具体金额,因为不同模型和服务差异太大,写死了反而误导。但量级可以说。
一本 30 万字左右的小说,跑完整条链路,调用次数大约在80 到 120 次:拆解阶段占四成,因为要分批处理;角色卡占一成;剧本阶段按集数算,每集三稿三次调用;分镜阶段每集一次;组装基本不消耗调用。可以看到,成本大头在拆解和剧本,这两个环节优化收益最高。
时间上,纯机器跑一轮,一本 20 集的项目大概在一到两小时内能出初稿,但人工介入是跑不掉的:Skill 1 的结果要人工过一遍,Skill 3 的大纲稿要人工过一遍,Skill 5 的缺口报告要人工确认。三处人工加起来,我的经验是三到五小时。这个比例很合理,机器负责产出,人负责判断,不要指望全自动。
最后分享一个我一直在用的小技巧:给每个 Skill 的提示词末尾加一句“如果输入信息不足以完成这一步,直接输出 MISSING: 具体缺什么,不要自行编造”。这句话能挡掉大量的“模型自己脑补设定”,尤其在角色卡和骨架阶段特别有效。前期多拦住一次,后期少返工一轮,这个投入产出比在所有优化里是最高的。