资讯动态

AI短剧创作教程源码包:从剧本到成片的自动化流水线

发布时间:2026/10/20 18:10:38 来源:尧图企业网站定制
简介AI短剧创作教程源码包专为希望借助AI工具快速产出短剧的内容创作者与开发者设计。资源围绕AiPy工具覆盖从故事主题设定、提示词生成剧本到旁白与分镜头视频制作、人物一致性维护直至音视频合成出片的完整流程配有可直接套用的提示词模板零基础用户也能一步步做出连续、连贯的短剧。包内共3个文件以HTML格式的交互式教程为主体并附带inscode工程配置与gitignore辅助文件压缩包仅7KB结构精简、上手成本极低。已有1283人学习。通过源码可直观查看分镜头示例、剧本大纲写法及工程运行配置既能当作速成教程也可作为AI短剧生成工具的二次开发参考帮助理解AI在剧本创作、场景构建与自动剪辑中的实际落地方式。1. AI短剧创作教程源码包它到底帮你做了什么AI短剧创作这件事绝大多数人卡住的地方不是“不会写”而是“写出来之后怎么把它变成一条真正的视频”。我之前接过一个模拟项目X一天内要出一段60秒短剧样片写剧本只花了半小时剩下六个半小时全在解决“AI生成的音频和画面怎么对上、怎么导进剪辑轨道”。这套AI短剧创作教程源码包给我的感觉就是有人先把这套流水线配好了。它以剧本拆分为起点覆盖TTS配音、分镜画面生成、时间轴对齐、最终渲染适合两类人一类是刚入行的开发者想看看一条短剧pipeline到底要分几段另一类是已经在手搓工具但整条链路断断续续的人拿来对一对自己的接口设计。下面我把骨架拆给你看。2. 先立骨架拆目录、配角色卡把“拍戏”变成数据2.1 源码包目录入口、配置与产物分开拿到源码包第一步不要急着跑先看目录。短剧和单点AI工具不同它是一条强流程的流水线剧本拆分、配音生成、画面生成、视频渲染四段各自独立又互相依赖。源码带的目录结构是这样project_x/ ├── config/ │ ├── settings.yaml # 全局参数分辨率、帧率、输出路径 │ └── characters.json # 角色卡音色、语速、外观描述 ├── scripts/ │ ├── 01_prepare.py # 剧本md拆分成分幕JSON │ ├── 02_gen_tts.py # 逐条对白生成音频 │ ├── 03_gen_images.py # 逐分镜生成画面 │ └── 04_render.py # 合成视频 ├── data/ │ ├── script.md # 原始剧本 │ └── scenes/ # 拆分后的中间数据 ├── output/ │ ├── audio/ # TTS产出的音频文件 │ ├── images/ # 分镜图片 │ └── final/ # 渲染成品这个结构值得沿用的地方在于四个阶段通过文件系统通信而不是通过数据库或服务调用。音频生成完落盘为一个mp3文件画面生成完落盘为一张png图片渲染脚本只认目录不认内存里的对象。好处是任意阶段翻车你都能直接看产物排查不用在内存里打日志追变量。坏处也很明显中间文件会占大量磁盘空间但短剧项目单条时长短一张1080x1920的图也就几MB一百张图完全能接受。入口顺序是01到04靠文件名天然排序。settings.yaml里最值得改的参数是分辨率默认1080x1920竖屏如果做横屏版本要同时改文件里的width和height不然渲染阶段会拿竖屏参数切横屏素材画面上下一截黑边。2.2 角色卡与剧情分幕把“拍戏”翻译成结构化数据整套源码的数据源头是config/characters.json它把“角色”抽象成一组固定键值。我习惯把它理解成给AI演员写档案同一角色在剧本里出现十次每次生成配音和画面都要读这张卡而不是让模型自己回忆上一场长什么样。{ role_01: { name: 角色A, voice_profile: { engine: tts_a, voice: female_calm, speed: 0.95, pitch: 1.02, lang: zh-CN }, style_hint: 深色短发灰色外套室内灯光, scene_range: [scene_001, scene_008] }, role_02: { name: 角色B, voice_profile: { engine: tts_a, voice: male_deep, speed: 1.0, pitch: 0.95, lang: zh-CN }, style_hint: 高个子浅色卫衣左侧柔光, scene_range: [scene_001, scene_003] } }voice_profile里的speed是语速倍数0.95表示比标准语速略慢短剧对白通常语速偏快但TTS在1.0以上容易吞字尤其“了、呢、吗”这类语气词所以我一般压到0.9到1.0之间。pitch是音调偏移拉到1.1以上会明显发“电子音”不是所有角色都适合。style_hint这行是给画面生成用的描述要具体到什么发型、什么衣服、什么光位后面生图阶段会逐场拼进提示词模板。01_prepare.py做的事是把原始剧本md拆成结构化的场次数据核心就是一个正则切分# scripts/01_prepare.py import json, re from pathlib import Path def split_scene(md_text): # 按二级标题切分剧本里每场戏用 ## 标记 blocks re.split(r^## , md_text, flagsre.M) scenes [] for i in range(1, len(blocks)): content blocks[i].split(\n) title content[0].strip() dialogue [] for line in content[1:]: if : in line: role, text line.split(:, 1) dialogue.append({ role: role.strip(), line: text.strip() }) scenes.append({ scene_id: scene_%03d % i, title: title, dialogue: dialogue }) return scenes if __name__ __main__: md Path(data/script.md).read_text(encodingutf-8) scenes split_scene(md) out Path(data/scenes/scenes.json) out.parent.mkdir(parentsTrue, exist_okTrue) out.write_text(json.dumps(scenes, ensure_asciiFalse, indent2), encodingutf-8) print(f拆分完成{len(scenes)}场)拆分规则只认##和冒号两个约定。如果你的剧本不是这种格式比如用数字编号或者-列表改re.split那行就行。拆完的scenes.json是所有后续脚本的输入配音脚本按场次遍历画面脚本按场次生成分镜渲染脚本也用它来确定时长。我建议你在这一步跑完后打开scenes.json确认一条台词都没丢这一步检查得越仔细后面重跑的代价越低。2.3 启动检查依赖、配置与第一条日志源码包里带了一份requirements.txt使用前先建干净环境路径和依赖错了会一路错到渲染结束。我的习惯是这样启动cd project_x python -m venv venv source venv/bin/activate python -m pip install -r requirements.txt python scripts/01_prepare.py用python -m pip而不是直接pip是为了避免多版本Python环境下装错包。装完依赖后先只跑01_prepare.py它是最轻量的步骤能看到拆分日志就算环境通了。如果这一步报ImportError大概率是依赖没装上回到上面重装如果报编码错误把script.md转成UTF-8编码而不是去改读取逻辑。全局参数集中在config/settings.yaml这里放的是不经常改但影响全链路的配置scene_dir: data/scenes audio_dir: output/audio image_dir: output/images final_dir: output/final fps: 30 resolution: width: 1080 height: 1920fps我固定用3060会让渲染时间翻倍对短剧来说观感提升有限。resolution决定了后面所有画面的长宽比中途改会让已生成的图片白做所以第一步就定死。3. 让角色开口TTS选型、脚本驱动与对白时间轴对齐3.1 TTS选型两个边界条件源码里TTS这块给了两套接法一套接系统级TTS服务一套接本地模型。做短剧选哪套我只看两个条件一是音色稳定性二是批处理吞吐。系统级服务接入成本低几句代码就能出声但同一句话重跑两次音色会有细微漂移单条对白听不出问题串成一部片子就会觉得角色“忽老忽年轻”。本地模型第一次要下模型文件之后全程离线跑参数锁死后音色稳定得多代价是显存占用量和更慢的生成速度。对比项系统级TTS服务本地模型接入成本低配好密钥即可中需要处理模型文件与依赖音色稳定性一般多次调用有漂移高锁参数后基本不变批处理速度快并发接口慢串行为主可控参数少通常只有语速和音色多pitch、停顿、重音都能调短剧的台词量不大一条60秒成片一般就20到30句对白吞吐量不是瓶颈音色稳定才是。所以我在这个项目里选了本地模型路线并且把参数全部写在角色卡里任何一场生成都读同一套配置。3.2 从剧本JSON到对白音频驱动脚本02_gen_tts.py的作用很简单遍历scenes.json里的每一条对白读取角色卡配置调TTS接口生成音频文件落盘到output/audio/下。# scripts/02_gen_tts.py import json, subprocess, time from pathlib import Path def gen_tts(role_profile, line, out_path): vp role_profile[voice_profile] cmd [ tts_cli, --model, vp[engine], --voice, vp[voice], --speed, str(vp[speed]), --pitch, str(vp[pitch]), --lang, vp[lang], --text, line, --out, str(out_path) ] for attempt in range(3): # 失败重试3次避免网络抖动直接断掉管线 r subprocess.run(cmd, capture_outputTrue, textTrue) if r.returncode 0: return True print(f[retry {attempt1}] {line[:20]}) time.sleep(2) print(f[FATAL] {line} - {r.stderr[-300:]}) return False def main(): scenes json.loads(Path(data/scenes/scenes.json).read_text(encodingutf-8)) roles json.loads(Path(config/characters.json).read_text(encodingutf-8)) out_dir Path(output/audio) out_dir.mkdir(parentsTrue, exist_okTrue) timeline [] for scene in scenes: for idx, dlg in enumerate(scene[dialogue]): role roles.get(dlg[role], roles[default]) filename f{scene[scene_id]}_{idx:02d}.mp3 if gen_tts(role, dlg[line], out_dir / filename): timeline.append({ scene: scene[scene_id], index: idx, role: dlg[role], file: filename, text: dlg[line] }) Path(output/audio_map.json).write_text( json.dumps(timeline, ensure_asciiFalse, indent2), encodingutf-8) print(f已生成 {len(timeline)} 条对白) if __name__ __main__: main()文件名规则scene_001_00.mp3是后面所有步骤的索引依据场次号、对白序号都编码在里面。渲染阶段拿到时间轴直接按文件名找音频不依赖任何数据库字段。audio_map.json是附加索引如果你要把台词打印成字幕文件直接用这份数据。参数上注意speed字段它不是越快越好短剧虽然节奏紧但语速到1.2以上TTS合成的口型会跟呼吸感脱节听起来像赶场。3.3 对白时间轴为什么字幕要等音频生成后再算整条流水线最玄学的部分就是对白时长估算。一开始我也图省事按“每120字约等于3秒”去估每句台词长度然后把画面时长按这个估拉好对完字幕才发现一堆对不准。后来改成等所有音频生成完用ffmpeg工具读真实时长回填时间轴ffprobe -v error -show_entries formatduration -of csvp0 output/audio/scene_001_00.mp3输出是一个秒数精确到小数点后三位。把每条音频的时长读出来累加得到每一场的总时长再反推画面需要补多少秒。这个顺序不能反过来画面先定死了音频时长偏长就只能快放偏短就得补空镜头怎么弄都是凑合。短剧一共就几十句对白跑一次ffprobe循环不到一分钟却能省掉后面人工对齐字幕的一两个小时这笔账值得算。标记时间轴时还有个容易忽略的细节TTS生成的音频首尾可能有一段静音如果直接拿全长去拼接画面会有一个顿挫感。常见做法是生成后裁掉首尾静音比如用ffmpeg的silenceremove滤镜或者在做对白拼接时统一叠一个短促淡入淡出。4. 画面进棚分镜提示词模板、批次生成与一致性设置4.1 分镜提示词模板固定结构比自由发挥稳定进入画面生成阶段之前先把分镜拆清楚。分镜拆分的依据是对白音频的时长一条对白短于4秒配一张画面就够超过8秒还只有一张静止图观众会觉得画面“冻住”了。源码里的03_gen_images.py支持给一条长对白配两到三张图切换点落在音频时长的中间位置再用画面转场补过去。提示词这块源码给的是固定模板思路不是放开让模型自由发挥def build_prompt(scene_meta, role_style, seed): # 模板固定先定画幅和氛围再定角色外观最后定镜头参数 return ( 短剧截图竖屏9:16电影感布光浅景深。\n f角色{role_style[style_hint]}\n f场景{scene_meta[title]}情绪{scene_meta.get(emotion, 中性)}。\n 景别中景镜头调度轻微仰拍。\n 负面提示词模糊、变形、文字、水印、多余肢体。\n fseed:{seed} )固定结构的好处是AI模型对有序的输入更稳定你把“角色外观”“场景”“镜头”三个信息放在固定位置跑一百条也就只有这三个区域在变。如果每次都换一种句式描述同一个角色画面风格会跟着漂。style_hint这一段要在每一场都出现之前有人偷懒只在第一场写了角色穿着到第三场AI给角色换了件衣服后续一致性直接崩掉这是典型的人工漏填字段导致的翻车。4.2 批次落盘文件名就是场景标识生成脚本遍历分镜记录把每张图写进output/images/命名规则和音频对齐scene_001_00.png这个序号对应audio_map里scene_001_00这条对白。# scripts/03_gen_images.py import json, subprocess from pathlib import Path def gen_image(prompt, out_path, size(1080, 1920), seed2024): cmd [ image_gen_cli, --prompt, prompt, --size, f{size[0]}x{size[1]}, --steps, 30, --cfg, 7.0, --seed, str(seed), --out, str(out_path) ] r subprocess.run(cmd, capture_outputTrue, textTrue) return r.returncode 0 def main(): audio_map json.loads(Path(output/audio_map.json).read_text(encodingutf-8)) scenes json.loads(Path(data/scenes/scenes.json).read_text(encodingutf-8)) roles json.loads(Path(config/characters.json).read_text(encodingutf-8)) out_dir Path(output/images) out_dir.mkdir(parentsTrue, exist_okTrue) for entry in audio_map: role roles.get(entry[role], roles[default]) scene next(s for s in scenes if s[scene_id] entry[scene]) prompt build_prompt(scene, role, seed2024) shot entry[index] * 2 # 每句对白预留 2 张图位 out_path out_dir / f{entry[scene]}_{entry[index]:02d}_A.png ok gen_image(prompt, out_path) if not ok: print(f[image failed] {out_path}) if __name__ __main__: main()参数steps是采样步数30是一个性价比比较高的位置低于20会出现细节崩塌高于40改善很小但耗时明显变长。cfg控制在7附近太高画面会过度锐化人脸容易出塑料感太低则主体边缘发糊。seed这里固定是因为同一分镜要出备选图时只改这个字段能保证构图一致不是为了保证跨场一致性。4.3 批次一致性种子、风格词与跨场复用真正决定角色跨场一致性的不是seed而是角色卡里的style_hint。种子只能保证同一段提示词下的构图稳定改一个词构图就会变。所以跨场一致的组合打法是这样外观描述固定、镜头模板固定、负面提示词固定、种子逐场递增但保持同奇偶性。具体操作是给每场分配一个基准seed比如第1场用2024第2场用2026两个seed相差不超过10画面主体位置和景别最接近跳着用seed反而容易出现上一场近景、下一场远景的割裂。目标做法不建议统一人物外观style_hint逐场照抄临场发挥统一光照方向模板固定“左侧柔光”每次重写光位统一构图seed递增且步长小随机乱设seed统一画面质感cfg、steps全片锁死中途调整参数另一个人物一致性手段是参考图把第一场生成的角色图作为后续场次生成时的参考输入注意这里说的参考图是局部重绘那一类做法对短剧批量生产来说把第一张图复制进后续提示词输入即可但要在每张图生成后检查一遍因为参考图会把构图偏好也带进去导致所有分镜都一个视角看起来非常“模板化”。5. 避坑指南5条让成片翻车的现场记录5.1 音量忽大忽小像换了个人配音现象台词单句听都正常拼进成片后这一段音量明显偏大下一段又偏小连起来听刺耳。原因TTS接口对长文本和短文本的响度归一化策略不一致短句偏安静长句偏响拼接时没有做统一响度处理。解决所有对白生成后先跑一遍响度归一化我习惯用ffmpeg的loudnorm处理到统一目标响度再进拼接环节。处理时注意不要对整段成片一次性归一化那样画面和音轨会一起被推高而是按每条对白单独归一最后拼接时加入淡入淡出感官上会更顺滑。5.2 字幕与对白错位先估时长就吃亏现象生成的字幕文件里话音已经结束了字幕还挂在画面上。原因按字数估算对白时长属于经验值每句话的实际时长波动很大标点、语气词、多音字都会影响。解决严格走“先生成音频、再读时长、最后算字幕”的顺序。写个小循环遍历audio_map.json逐条读真实时长再累加得到时间轴任何一条对白换过文案都要重新跑一遍这一步不手动改字幕时间戳。5.3 角色换了衣服中途突变现象前一场还是深色外套后一场变成了浅色T恤发型也变了。原因style_hint没有逐场写入提示词只有某一场提了外观模型在后续场次默认自己发挥。解决把角色外观字段写死在提示词模板里每次生成都强制带上。更保险的做法是把第一场产出的正面图作为后续场次的参考图传入生图服务但要注意参考图权重调低一些只约束长相和衣着不约束构图和景别。5.4 渲染卡死或内存溢出现象渲染到一半内存占满进程被系统杀掉前面积累的音频和画面全部作废。原因一次性把全片的分镜图片全部加载到内存里合成短剧分镜多时内存直接爆掉。解决改成按场渲染每场合成一个小片段最后再用一次拼接命令把各场视频连起来。这样即使某一场崩溃也只需要重跑那几秒的渲染任务。源码里的04_render.py支持传--scene scene_005之类的参数字段原来是空着的目的就是方便单场重跑。5.5 画面偏灰发绿调参数调不过来现象所有生成图都蒙着一层灰绿滤镜改提示词加“色彩鲜艳”也没效果。原因负面提示词没有排除常见色调偏移同时cfg设置偏高模型把部分色彩描述吞掉了。解决负面提示词里显式加上“偏绿、偏灰、低饱和、色彩断层”这类描述词并把cfg降到7以下重跑一遍。先跑3张试点图确认色调正常再全量生成不要在参数未验证时直接铺开跑一百张那样发现翻车就要全军覆没。6. 交付前再快一点渲染缓存、失败续跑与成片一致性校验6.1 增量渲染与失败续跑全流程跑一次后每次改一条台词就要重跑全链路的代价非常笨重。源码脚本里预留了--skip-existing参数重跑时主动跳过已存在的音频和图片文件。我重跑的典型场景是改了角色语速只需要重新生成音频画面素材不需要动但如果改了角色的style_hint音频保留、图片删除后重生成render阶段再增量拼接。把路径交付文件独立管理是整套流水线能持续迭代的前提。python scripts/02_gen_tts.py --skip-existing python scripts/03_gen_images.py --skip-existing --scene scene_005 python scripts/04_render.py --scene scene_0056.2 成片一致性校验渲染完不要直接拷走花三十秒做一道校验用ffmpeg确认成片时长与音频地图总长误差在正负0.5秒以内再记录一个文件哈希方便后续确认交付的文件没有被二次转码。ffprobe -v error -show_entries formatduration -of csvp0 output/final/final.mp4 md5sum output/final/final.mp4时长偏差超过0.5秒说明转场或音画对齐出问题哈希值每次渲染都会变但如果别人发回来的文件哈希和你的记录对不上就说明被人转过码画面质量可能已经受损。我从那次内存炸掉重跑三遍之后每次跑短剧流水线都强制先做增量再校验交付宁可慢一分钟也不赌全链路一次成功。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑