news 2026/10/10 6:57:29

开源本地AI短剧生成工具:从故事到成片的私有化工作流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源本地AI短剧生成工具:从故事到成片的私有化工作流

简介:一款开源本地AI短剧与漫剧生成工具,面向短视频创作者、编剧和团队协作场景,覆盖从故事梗概生成、角色发展、情节推进、对话创作到成片合成的完整流程,解决传统短剧制作周期长、数据隐私难保障等问题,对零基础用户同样友好。所有数据处理与生成均在本地完成,无需上传云端,兼顾隐私安全与离线创作;内置工作流管理平台,可有序管理脚本、素材、任务分配与进度跟踪,满足差异化创作需求。资源包共227个文件,压缩包约41.38MB,以JavaScript、Vue、JSON等代码文件为主,辅以SQL/YAML数据库配置、MD文档说明、PNG/JPG素材,另有ffmpeg.exe及bat启动脚本便于本地部署与二次开发,目录组织清晰。已有830人学习下载,是希望借助AI真人剧、漫剧合成功能提升创作效率的创作者可直接落地的本地化工具方案,个人快速出片或团队流水线创作均可从中获得完整支持。

1. 开源本地 AI 短剧生成工具:把「故事到成片」压缩成一条本机流水线

想做短剧、漫剧、有声剧,但又不想把剧本素材、角色设定、配音原声全交到别人服务器上,这是很多个人创作者和小工作室的刚需。标题里的这套「开源本地 AI 短剧 & 漫剧生成工具,数据不出本机」做的事,就是把「故事 → 脚本 → 分镜 → 配音 → 字幕 → 成片」这条链路,用一套本地部署的开源工作流管理平台串起来。它的核心卖点不只是「免费」,而是高灵活度和私密性:你可以随意换模型、改提示词、调画面比例,甚至把中间产物导出来二次剪辑。适合的人群很明确:会一点 Python、跑得动 ComfyUI 或 Ollama,想批量产出短视频内容的创作者。这篇笔记我会按整条工作流的落地顺序,把每一步的选型理由、最小可运行命令、参数边界和翻车现场都讲透。

2. 剧本转分镜脚本:本地大模型把「故事」拆成可渲染的镜头文件

2.1 为什么选本地 LLM 而不是云端接口

短剧生成的第一道工序,是把一段故事梗概改写成带镜头编号、时间码、画面描述、旁白和台词的结构化脚本。云端大模型接口确实方便,但你会发现三个问题:一是剧本内容本身就是核心资产,分批上传很别扭;二是短剧脚本通常要迭代十几版,每次都要微调模型输出格式,云端接口的 JSON 输出稳定性受网络和采样参数影响很大;三是你后面要接 ComfyUI 渲染和 TTS 配音,脚本的字段必须固定成一套 schema,本地模型反而更容易通过提示词模板去卡结构。

第二个选型理由是本地的「本地向量模型」和「embedding」能力可以顺手用上。我不止一次在脚本生成之后做一件事:把角色名、服装、场景关键词抽出来,做成 embedding 存到本地向量库里。这样后面生成角色图时,可以从库里检索到最接近的设定描述,减少角色在不同镜头里的漂移。云端接口虽然也能做 embedding,但数据不出本机这个边界就很难守住。

2.2 用 Ollama 跑通最小脚本生成流程

我一般用 Ollama 部署本地大模型,它属于那种「开箱即用」的方案,装完就是个本地 HTTP 服务。要注意的是,短剧脚本生成对中文指令跟随能力有要求,我比较常用的是 qwen2.5 系列或者 deepseek-r1 蒸馏版,显存紧张就选 7B 左右的量化版本,16G 显存跑起来基本不掉队。下面这个脚本,输入一段故事梗概,输出一份 JSON 数组。

import requests import json story = "落魄厨师林远在夜市捡到一只会说话的猫,猫说它是美食界的仲裁者,能让他做出让人流泪的菜,但代价是每晚要替它完成一个食客的委托。" prompt = f""" 你是一个短剧编剧。把下面的故事改写成适合 AI 分镜渲染的脚本。 要求: 1. 输出 JSON 数组,不要输出别的文字。 2. 每个镜头对象包含:shot_id, scene, duration, camera, content, subtitle, voiceover 3. camera 用固定词表:中景/近景/特写/俯拍/跟拍 4. duration 单位为秒,每个镜头 3 到 8 秒 5. 台词写入 subtitle,旁白写入 voiceover 6. 总共设计 6 个镜头 故事:{story} """ resp = requests.post( "http://localhost:11434/api/chat", json={ "model": "qwen2.5:7b", "messages": [{"role": "user", "content": prompt}], "stream": False, "options": {"temperature": 0.3, "top_p": 0.7}, }, timeout=120, ) data = resp.json() content = data.get("message", {}).get("content", "") try: shots = json.loads(content.strip("```json").strip("```").strip()) except json.JSONDecodeError: print("解析失败,原始输出:") print(content) raise with open("shots.json", "w", encoding="utf-8") as f: json.dump(shots, f, ensure_ascii=False, indent=2) print(f"成功生成 {len(shots)} 个镜头,写入 shots.json")

这段代码的关键点有三个:第一,Ollama 的接口地址默认是http://localhost:11434,如果你把服务装在了别的机器上,把地址换成对应 IP 就行;第二,options里的temperature我压到了 0.3,短剧脚本需要稳定的结构,温度太高会出现镜头数量飘忽、camera 字段乱写的情况;第三,最后一步json.loads做了格式化清理,因为本地模型偶尔会输出带 ```json 标记的内容,这个剥离逻辑不能省。

2.3 让输出稳定的三个参数和一个校验开关

用本地模型跑脚本生成,很多人第一次都会翻车:生成一半变成自问自答,或者 shot_id 从 2 直接跳到 5。我的经验是三个参数要焊死。

第一,temperature控制在 0.2 到 0.4,不要把 top_p 绑得太狠,top_p留在 0.7 到 0.9 之间,给生成留一点多样性。第二,num_ctx要开到 4096 以上,短剧脚本虽然单个镜头短,但整体上下文长,模型需要记住前面写了什么才能保证剧情连贯。第三,repeat_penalty调高一点,我一般用 1.1,防止模型在镜头描述里反复出现同一个形容词。

校验开关是最后一道防线。我会写一个简单的validate_shots()函数,检查 shot_id 是否连续、duration 是否在 3 到 8 秒之间、camera 是否在词表里、subtitle 和 voiceover 是否至少有一个非空。这四类问题用正则就能处理,校验不通过就重新请求一次。网络不稳定的时候,重试两次是常态,三次以上就说明提示词模板有问题,不是参数的问题。

3. 角色一致性与本地配音:数字人形象和声音克隆的参数设计

3.1 角色一致性:先解决「脸崩」再谈表情驱动

短剧生成里最让新手头疼的不是脚本,而是角色一致。同一个角色第一镜头是年轻女性,第三个镜头变成圆脸,这就是「脸崩」。开源社区常用的做法,是在本地 ComfyUI 里用 SDXL 或者更轻量的模型生成角色立绘,然后用 IPAdapter 或者 LoRA 锁定特征。本地跑的时候,数据不出本机这条线是能守住的。

我的经验是:不要直接生成带表情的「剧照」,先做一张纯正面、无表情、固定背景的角色设定图,跑通以后再叠加表情和景别。这样做的好处是,你可以把这设定图作为 IPAdapter 的 reference 图,喂给后续每个镜头,模型才会知道「这个角色长什么样」。否则你每次生成都在赌扩散模型的随机性,那不是工作流,是抽卡。

import json with open("shots.json", "r", encoding="utf-8") as f: shots = json.load(f) character_profiles = { "林远": { "image": "output/characters/linyuan_base.png", "ref_prompt": "young male chef, black apron, short hair, determined eyes", }, "猫": { "image": "output/characters/cat_base.png", "ref_prompt": "chubby tabby cat, golden eyes, wearing a tiny red scarf", }, } for shot in shots: char_name = shot.get("character", "林远") profile = character_profiles[char_name] shot["ref_image"] = profile["image"] shot["ref_prompt"] = profile["ref_prompt"] shot["seed"] = 1000 + shot["shot_id"] * 17 with open("shots_enriched.json", "w", encoding="utf-8") as f: json.dump(shots, f, ensure_ascii=False, indent=2)

这段代码的思路是给每个镜头打上ref_image和固定的seed。固定 seed 是让角色不蹦的第二个关键,你几乎可以把它当成角色的「指纹」。同一个角色、同一个模型、同一个 seed,生成的画面风格和脸型会高度接近;换 seed 等于换脸。参数上,seed的间隔我故意选了质数步长,避免镜头之间画面出现规律性闪烁。IPAdapter 的权重我一般调在 0.75 到 0.85,太低等于没参考,太高会让角色完全复制参考图的姿态,失去镜头张力。

3.2 声音克隆:用少量素材拟合音色,注意说话速率与停顿

配音环节,本地方案里常见的是 GPT-SoVITS 一类的开源声音克隆工具,你准备 30 秒到一分钟的干净人声就能微调出一个可用音色。所谓「AI真人剧」的质感,很大程度取决于这一层:TTS 输出的语气太平,整段短剧就像新闻联播。所以我不建议直接用默认参数。

我一般会改三个参数:speech_rate下调到 0.9,让语速慢一点,短剧对白需要留喘气的空间;pause_interval拉开句子之间的停顿,默认值听起来太赶;temperature保持在 0.7 左右,给语气一点起伏。这里有个不容易发现的坑:配音是逐句生成的,单句听都不错,拼起来就怪。解决办法是用旁白把每一句的上下文带住,而不是只给 TTS 一句孤零零的台词。

source ./venv/bin/activate python tts_infer.py \ --text "我今晚一定要吃掉那碗红烧肉,谁拦我都没用。" \ --ref_audio "output/audio/linyuan_ref.wav" \ --ref_text "一个落魄厨师,蹲在夜市角落,眼神倔强。" \ --speech_rate 0.9 \ --temperature 0.7 \ --output "output/audio/shot_001.wav"

注意这里的--ref_audio不能随便截一段环境音很重的录音。参考音频的底噪越干净,克隆出来的音色越稳定。另外,--ref_text一定要写清楚参考音频里的原话,否则模型可能把语音内容和目标文本搞混,生成结果会出现「读错字」的怪问题。如果你换了角色,记得连参考音频一起换,只换参考文本是偷懒,出来的声音会有「夹生感」。

3.3 本地渲染的显存分配与批次大小参考

整条工作流最吃硬件的是 ComfyUI 渲染阶段。我本人在 16G 显存的环境下跑过一条 6 镜头、每个镜头 4 秒、总长约 24 秒的短剧片花,用的是 SDXL 加 IPAdapter,每镜头单帧渲染控制在 2 秒内。如果你的显存只有 12G,算法要改成「先生成首帧,后续帧用 camera 参数做运动控制和图生图」,不要直接整段视频生成,那种方案的 VRAM 需求会直接顶爆。

批次大小的参考值我给你列一个表,按显存档位配:

显存渲染分辨率批次大小采样步数推荐模型
12G1024x576120SD1.5 微调模型
16G1280x720224SDXL + IPAdapter
24G1920x1080428SDXL / SD3 类

这里的批次大小是 ComfyUI 里EmptyLatentImage的 batch_size 参数。批次越大,同一角色连贯性越好,因为模型一次性看更多的连续帧,但显存压力也线性上涨。踩坑经验是:先把 batch_size 设成 1,单帧质量调到满意再做批量,别一上来就追求大批次,否则很容易出现「模型里全是马赛克、显存也没了」的尴尬局面。

4. 镜头组装成片:FFmpeg 批量拼接与音画同步的完整命令

4.1 先按镜头号整理素材清单

有了分镜 JSON、角色图和配音音频,接下来就是「后期合成」这一道工序。很多人以为直接把视频片段丢进剪辑软件就完了,但本地工作流讲究的是「可复现、可重跑」。所以我会先用一个脚本,把 shots_enriched.json 与渲染出来的视频片段、配音音频建立一一对应关系,生成一个 manifest 列表。

我在工程里习惯用manifest.json来记录每个镜头的输入输出路径、生成时间、模型参数、seed、音频时长。这样万一哪个镜头渲染翻车,我能精准定位到是哪个模型、哪个 seed、哪段音频出了问题,而不是靠肉眼一条条找。这比你用剪辑软件导出工程文件里的时间轴更可控。

mkdir -p output/clips output/audio output/final for i in 001 002 003 004 005 006; do ffmpeg -y \ -i output/renders/shot_${i}.mp4 \ -i output/audio/shot_${i}.wav \ -c:v libx264 -preset medium -crf 18 \ -c:a aac -b:a 192k \ -shortest \ output/clips/shot_${i}_with_audio.mp4 done

这里面有个容易忽略的参数:-shortest。它决定输出文件的时长以视频和音频里较短的那一个为准。如果 TTS 配音生成的音频长度超过视频时长,不加-shortest的话,视频播完音频还在说话,音画就错位了。反过来,如果你想要完整的音频而不是截断,那就先统一视频时长,用户在用这套命令时要自己权衡好。

4.2 音频对齐与字幕烧录

音画对齐的问题在本地合成阶段最容易翻车。我整理过一个很反直觉的经验:TTS 生成的音频时长往往比你预期的短。因为脚本里写了 4 秒的镜头时长,但 TTS 念完台词可能只要 2.5 秒,剩下 1.5 秒画面里就是一个人闭嘴的画面,很尬。常见的做法是把音频尾部再拉长一点静音,用 FFmpeg 的 apad 参数补齐,保证每条音轨长度等于镜头时长。

for i in 001 002 003 004 005 006; do ffmpeg -y \ -i output/clips/shot_${i}_with_audio.mp4 \ -vf "subtitles=output/subs/shot_${i}.srt:force_style='FontName=Microsoft YaHei,FontSize=18,PrimaryColour=&H00FFFFFF,Outline=1'" \ -c:v libx264 -preset medium -crf 18 \ -c:a copy \ output/final/shot_${i}_final.mp4 done

字幕烧录这一步的force_style参数里,FontName=Microsoft YaHei是关键,中文环境下的短剧字幕不用中文字体就会变成方框乱码。PrimaryColour=&H00FFFFFF的写法是 BGR 顺序,白字是00FFFFFF,黄字是00FFFF00,很多新手直接照抄白色结果用了默认颜色,在浅色画面上根本看不清。字幕文件的编码必须另存为 UTF-8,否则 SRT 里的中文在烧录时会变成乱码。

4.3 用 manifest.json 管理整条工作流的产物

最后一步是整个 pipeline 的「后悔药」。这一步不需要写复杂程序,一个 JSON 字段是「工作时间戳」,另一个是「完整命令参数」,第三是「文件 hash」。为什么需要 hash?因为短剧成片经常要改一两句字幕重新烧录,但渲染出来的视频文件一样,你又不想重新渲染画面,这时候只有 hash 能告诉你「哪个文件改过,哪个文件得重新生成」。这个习惯能救你很多次。

{ "project": "the-cat-chef", "generated_at": "2025-01-17T22:10:00+08:00", "shots": [ { "shot_id": 1, "video": "output/final/shot_001_final.mp4", "audio": "output/audio/shot_001.wav", "subtitle": "output/subs/shot_001.srt", "seed": 1017, "md5": "9b5b3e7a..." } ], "render_params": { "model": "sdxl_base", "ipadapter_weight": 0.8, "batch_size": 2 } }

参数说明里最重要的不是md5那个长字符串,而是render_params这个嵌套对象。我发现很多人在两周后回看自己生成的片子,根本说不清当时的 IPAdapter 权重是多少、seed 是多少。没有 manifest,就等于没有可复现性。如果哪一天要批量重渲镜头,你可以直接写脚本读取manifest.json里的seed和model设置,加进新的 prompt 里,不需要人工翻文件夹。

5. 短剧本地生成的避坑手册:从显存溢出到角色漂移的 5 个排查案例

5.1 生成到一半显存崩溃

现象:ComfyUI 渲染到第三个镜头时,显存直接 OOM,整个程序卡死,前面的工作白做。

原因:最常见的是批次大小设得过高,或者把多个大模型同时加载了。比如你一边挂着 Ollama 的 chat 模型,一边在 ComfyUI 里加载 SDXL,再开一个 TTS 的 GPU 加速,显存肯定不够分。

解决:批次大小先调到 1,跑通流程再说;Ollama 用 CPU 推理或者直接关掉,TTS 尽量用纯 CPU 版本;ComfyUI 里把不需要的模型从内存里卸载,让出显存给渲染进程。检查命令用nvidia-smi,看到显存占用持续在 90% 以上就说明这里有问题。

5.2 同一角色换了几个镜头后脸变了

现象:第一个镜头是圆脸,第四个镜头变成瓜子脸,连衣服颜色都不一样了。

原因:生成第二个镜头时没有复用角色参考图,或者用了参考图但 seed 换了。另一个隐蔽原因是提示词里对角色外观的描述不够一致,比如第一个镜头写black apron,第二个镜头写成dark apron,模型会认为这是两个不同角色。

解决:把角色外观的关键词从提示词中抽出来,固定成一个ref_prompt,放在每个镜头的 JSON 里。还要固定 seed,不要用随机 seed。如果这样还漂移,就把 IPAdapter 的权重从 0.75 往上加到 0.85,代价是角色的姿势会变得很呆,所以只适合特写和中景。

5.3 音画不同步

现象:视频画面已经切到下一个镜头了,上一句台词还没说完;或者台词说完了,画面还停在那里。

原因:两种。一种是我前面说的没加-shortest或者没把音频补到镜头等长。另一种是 TTS 生成的音频采样率和视频轨道的音频参数不一致,导致 FFmpeg 拼接后时间轴偏移。

解决:统一所有 TTS 音频的输出参数,导出时强制设定为 44100Hz、16bit、单声道;拼接命令里给音频加-ar 44100 -ac 1,强制对齐采样率。别信经验里的「加一个延时就能对上」,时间轴一错,后面所有镜头全跟着错。

5.4 字幕乱码

现象:字幕烧录到视频里,中文全变成带音标的字母,有些是方块,有些是乱码。

原因:SRT 文件编码不是 UTF-8,或者 FFmpeg 的FontName指向了系统里不存在的字体。Windows 环境下最容易发生:你的 SRT 是从 Excel 或者 Windows 记事本另存出来的,编码是 ANSI 或者 UTF-16,FFmpeg 就认错。

解决:统一把 SRT 文件另存为 UTF-8 without BOM,把FontName改成Microsoft YaHei(微软雅黑)或者SimHei(黑体)。别用默认的Arial,它就是中文乱码的元凶。

5.5 ComfyUI 工作流导入后节点全红

现象:从网上下载了一个现成的短剧工作流 JSON,拖进 ComfyUI 界面,所有节点都报红色错误。

原因:缺自定义节点、模型路径不对、版本不匹配。短剧渲染工作流通常需要 IPAdapter、FaceDetailer、VideoHelperSuite 这些插件,你本地的 ComfyUI 没装,节点自然报错。

解决:先看红色节点提示缺哪个custom node,去 ComfyUI Manager 里搜索安装;再把工作流里引用的模型文件路径改成本地的绝对路径,比如models/checkpoints/sdxl_base.safetensors。记住一个原则:开源社区分享的 workflow 永远不能直接双击使用,必须走一遍「模型路径体检」和「插件体检」。

6. 进阶:把 ComfyUI 工作流挂进整条 pipeline,用元数据驱动批量重跑

如果你已经跑通了「故事 → 分镜 → 渲染 → 配音 → 成片」这条手动工作流,下一步值得做的是把 ComfyUI 工作流接入 pipeline,用元数据驱动批量生成。很多人以为 ComfyUI 只是「一个画节点的工具」,但实际上它的 API 模式可以完全脱离界面运行。你只需把工作流导出为 JSON,然后通过 HTTP 请求向 ComfyUI 的 API 提交 prompt,就能脚本化批量跑镜头。这样,你改一句台词、调一个 IPAdapter 权重,不需要一张张重新生成图,而是把所有镜头的渲染任务丢进队列,睡一觉起来收成片。

我最常用的方式,是把 manifest.json 里的每个镜头拆成一次 ComfyUI API 调用。用 Python 读取镜头里的ref_image、seed、prompt,替换掉工作流 JSON 里的inputs字段,然后 POST 到http://127.0.0.1:8188/prompt,轮询history接口等渲染完成。这一步跑通以后,短剧生成才真正算是「工作流管理平台」而不是「套了几个脚本的工具」。

还有一个值得投入的增强技巧:给整条 pipeline 出口加一道超分。如果目标平台需要 1080p,但本地渲染只出了 720p,千万不要直接拉伸,那会糊成一片。用 Real-ESRGAN 一类的本地超分模型做一次 2 倍放大,参数上denoise_strength我会控制在 0.3 到 0.5,太低会强化噪点,太高会把皮肤磨成塑料。这个动作放在字幕烧录之前,而不是之后,否则字幕会被超分模型当成噪点处理,边缘出现白边。

最后说一个我自己的教训:最初我把整条工作流压在一个 ComfyUI 大 JSON 里,想一步到位,结果每次调试都要等十几个镜头全部跑完才发现问题。后来我把文本生成、图像生成、音频生成拆成三个独立阶段,每阶段产出一个中间文件,再用 manifest 串起来。改提示词时只重跑第一阶段,改角色时才重跑第二阶段。这套「单阶段重跑」的理念比任何具体工具都值钱。

工具链会一直换,模型也会越来越强,但「数据不出本机、过程可复现、产物可追溯」这三个原则不会变。希望这篇笔记能帮你在本地把第一条短剧流水线跑通,少踩几次我踩过的坑。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 6:56:44

微积分PPT课件工程化:从PPTX到可维护教学资源库的解析与入库

简介:这是一份面向高校理工科学生的高等数学专业课件,聚焦空间解析几何入门章节,适合正在学习微积分、需要同步梳理课堂重点或期末复习的读者使用。课件围绕空间直角坐标系展开,系统讲解三条数轴按右手规则构成的坐标系、八个卦限…

作者头像 李华
网站建设 2026/10/10 6:56:31

Copula二维建模实战:边缘分布拟合与蒙特卡洛模拟

如果你是做金融风控、可靠性分析或者气象数据建模的,Copula这玩意儿你应该不陌生。它有一个特别朴素的作用:把多个随机变量的依赖关系和各自的分布拆开,单独建模。这篇文章就围绕Copula二维场景最常见的三件事——边缘分布拟合、联合分布拟合…

作者头像 李华
网站建设 2026/10/10 6:56:29

自动复用Token:实现“只登录一次”的高效认证方案

做开发这么多年,最烦的一类事就是反复登录。尤其是做数据采集、自动化测试、调用第三方接口的时候,明明自己的账号权限没问题,可每次脚本一跑就报 401,一看日志,token 又过期了。早期我的做法很笨:手动去页…

作者头像 李华
网站建设 2026/10/10 6:55:50

SQL Server备份与恢复实战:从原理到演练避坑指南

备份这事,我见过太多“平时无所谓,出事两行泪”的现场。就在去年底,某客户的核心业务库误删了一张订单明细表,结果发现他们所谓的“每日备份”从来只做了完整备份任务,事务日志备份没开、恢复模式还是简单模式&#xf…

作者头像 李华
网站建设 2026/10/10 6:55:49

Flink状态管理与Exactly-Once语义:从Checkpoint到端到端精确一次

1. 生产事故开场:状态用错了,睡觉都不踏实1.1 那个凌晨两点半的告警先讲一个我真实踩过的坑。凌晨两点半,手机里的监控群突然连环告警,一个常跑的实时计算作业在重试了几次之后进入了 restarting 状态。爬起来一查,问题…

作者头像 李华
网站建设 2026/10/10 6:55:45

Elasticsearch日志分析实战:从集群规划到性能调优的落地指南

聊到日志分析,Elasticsearch 几乎是绕不开的主角。无论你是刚接触大数据的运维新人,还是已经被告警轮番轰炸的资深老兵,只要跟日志打交道,最终都会走到这一套技术栈面前。Elasticsearch 的全文检索、聚合分析能力,加上…

作者头像 李华