短视频流量没有消失,消失的是“手工剪片”的红利。过去大半年,身边几个做教培课程、连锁门店和自媒体代运营的朋友,几乎都撞上了同一堵墙:素材拍了一大堆,剪辑却卡在人工上,一条片子从选题到发布要三四个小时,日更三条根本撑不住。后来我搭了一套AI短剧创作系统,把选题、脚本、分镜、合成、字幕、排程全部串成一条自动流水线。这套系统真正解决的问题不是“有没有AI”,而是把人的角色从手动作业换成审核与调优。今天我把整套系统的链路设计、核心源码逻辑,以及它在教培、门店、媒体三个方向上的落地差异,完整摊开来讲。
这篇内容适合正在做矩阵号、本地生活代运营、或者想给机构搭内容中台的人。就算你没有任何技术背景,也可以直接跳到第4节看场景配置,代码部分我会解释每一块在干什么,不要求你懂编程。
1. 为什么需要一条“短剧流水线”:三家典型客户共同的产能瓶颈
1.1 某教培机构:课程卖不动,不是内容差,而是更新速度跟不上
我最早做这个系统,是因为一家做成人职业技能培训的机构。他们有十来个金牌讲师,口才和课程质量都不差,线下录课的素材库里躺着上千条原始视频。问题出在哪里呢?人工剪辑一条2分钟的课程切片,需要先听录音找高光片段,再上字幕、做标题、套片头,一个人一天最多出四到五条。而他们的竞品一天能发十几条,多数还是AI配音加图文轮播,虽然粗糙,但用户就是看到了,拿到了结果。
教培内容的核心矛盾是:知识密度高的片段往往没有经过“再编剧”处理,直接剪辑出来就是课堂录像,缺乏钩子。我们要做的不是把录像剪短,而是把“一个知识点”重新封装成一个有冲突、有结论、有引导的短剧。这件事靠人工太重,正好交给大模型来做第一稿。
1.2 连锁门店:同城流量的本质是高频上新
另一类客户是连锁饮品和餐饮门店。他们需要的不是品牌大片,而是每天围绕“新品、套餐、营业时间、门店地址”反复打点的同城内容。这类内容单条看起来很简单,但它有一个致命要求:要快。今天的新品,最好今天就发出去。如果是季节性水果饮品,拖到明天热度就没了。
门店的内容重复度极高,几十家分店共用一套素材模板,只是把定位、门头、套餐详情换一下。人工做这种活最大的问题是枯燥,剪辑师剪到第十条就开始复制粘贴,最后连错误也一起复制。把这类高重复度工作交给系统来组装,才是合理的用法。
1.3 媒体代运营:矩阵号的规模被剪辑人力锁死
第三种是给企业做新媒体代运营的团队。他们手里同时管着七八个账号,每个账号都要稳定的周更甚至日更节奏。你会发现一个很尴尬的情况:写手不缺,策划不缺,缺的是能把文案快速变成成片的剪辑。外包一条片子几百块,一周下来光内容制作成本就顶得上一个月服务费。
媒体号的批量需求是“标准品”。他们不需要每条都独一无二,反而需要可复用的片头、固定的栏目形式、统一的字幕风格。这正好是模板化生产的强项。有了系统之后,策划只要审核文案和分镜,剩下的交给流水线,一个月多接一倍账号都不需要加人。
这三类客户的共同点,其实是同一个词:内容供给侧的速度。AI短剧创作系统本质上不是创意系统,它是一个把成熟创意高速复制到不同载体上的工程系统。
2. 五环流水线:从选题到最终分发的全链路设计
这套系统的核心不是某一个AI模型,而是把内容生产拆成了五个互相独立又互相咬合的环节:选题池、脚本生成、分镜与素材组装、成片合成、排程分发。
2.1 第一环:选题池与标签系统
第一步不是生成,而是输入。系统维护了一个选题池,每个选题挂在某个“业务线”下面,带着一堆标签,比如行业、卖点、受众情绪、内容形态。教培机构可以进入“考证焦虑”选题,门店进入“新品上新”选题,媒体代运营进入“行业观点”选题。
这几个标签不是给人看的,是后面所有Prompt的上下文来源。你会发现,同样的模型,有没有这套标签系统,产出质量差别极大。因为大模型不知道你的业务背景,只有给它足够清晰的业务上下文,它才能生成不跑偏的脚本。
2.2 第二环:结构化脚本文案生成
从选题池捞出一个选题之后,系统会把业务标签、品牌调性、视频时长上限、平台偏好一并打包,发给大模型接口。这里的输出不是自由文本,而是一份强制性的JSON结构,里面包含开头的钩子、两三句故事旁白、分镜列表、结尾引导。
为什么要强制JSON?因为后续的每一环都要基于结构化数据才能做自动化。如果模型输出的是散文,机器就没法稳定地把文案对应到画面、旁白和字幕上去。这一步是整个流水线的质量命脉,Prompt的写法我在下一节会给到完整示例。
2.3 第三环:分镜、素材与配音的映射关系
拿到JSON剧本之后,系统开始分配素材。素材库里有三类东西:一是实拍片段,二是AI生成的背景图,三是纯文字排版画面。系统根据分镜里的scene_type字段,自动决定用哪类素材。
比如口播镜头就去找该讲师的正脸视频切片,空镜镜头就去素材库匹配关键词,没有合适素材就自动生成一张风格统一的背景图和文字卡。同时旁白文本会被送到TTS接口生成配音。这一环做好了,后面合成才有东西可用;这一环如果断料,整个任务就直接进入人工处理队列。
2.4 第四环:成片合成与自动质检
合成器拿到画面序列、配音文件、字幕文本之后,用FFmpeg按镜头顺序拼接,再叠加字幕条、背景音乐和片尾引导。合成完不是直接发,而是过一遍自动质检:时长是否在设定范围内、字幕是否和口播文本一致、有没有黑帧片段、音频有没有爆音。
这一步是容易被忽略却最容易翻车的环节。十次发布失败,有八次是素材比例不对或者音频轨速率不匹配。自动质检能在发布前拦住大部分低级错误,但它拦不住内容本身的好坏,所以我保留了人工抽检节点。
2.5 第五环:排程分发与数据回流
成片通过审核后进入排程队列。系统按各平台建议的发布时间自动排序,但分发动作需要接平台官方接口或者由运营手动批量上传。我不会把“自动上传发布”做成完全无人的功能,实际业务里平台规则和账号安全优先级更高。
数据回流是指发布后的播放量、互动率回传到选题池,给选题打上效果分。效果好的选题会被标记为“高潜选题”,下次生成时会优先复用相似结构。这一个闭环才是让系统越用越聪明的原因。
2.6 人工干预点:在哪里留审核闸门
我在这套系统里留了三个强制人工节点:脚本完成后需要业务负责人确认,成片合成后需要审核人看一眼,发布前运营要核对平台要求和内容合规性。全自动化不等于无人化,而是把人的时间集中到最有价值的判断环节上。这个原则后面第6节还会再展开讲。
3. 核心源码逻辑:生成、合成与调度三端的落地写法
现在进入源码部分。我会按模块来拆,代码是简化过的可运行逻辑,但保留真实系统的骨架。你要部署到自己服务器,照着这个思路扩就行。
3.1 剧本数据结构:先有Schema,再谈创作
先给短剧定义一个标准数据结构。这一步是整个系统的地基,代码里所有模块都依赖这个结构。
from dataclasses import dataclass, field from typing import List, Optional @dataclass class Shot: shot_id: str duration: float # 单个镜头时长,单位秒 scene_type: str # "talking" 口播 / "broll" 空镜 / "card" 文字卡 visual: str # 画面内容描述 subtitle: str # 当前镜头要显示的字幕 tts_text: str # 当前镜头要朗读的旁白 material_path: str = "" # 实拍素材路径,留空则自动生成背景图 @dataclass class ShortScript: task_id: str industry: str # 教培 / 门店 / 媒体 brand_tone: str # 品牌调性标签 hook: str # 开头钩子台词 story_lines: List[str] # 旁白列表,和 shots 一一对应 shots: List[Shot] cta: str # 结尾引导台词 platform: str = "general"为什么要用dataclass而不用字典?因为字段固定之后,后续的生成、合成、校验逻辑都能做类型检查,不容易出现某个分镜缺了subtitle导致字幕合成崩溃的情况。团队里新来的工程师接手也快,看一遍数据类就懂整个系统交换的数据格式。
3.2 脚本生成端:用Prompt锁定剧本的高质量边界
接下来是调用大模型生成脚本。我这里用一个占位函数load_llm_client(),实际接入时换成你们自己的云端或本地大模型服务即可。
import json def generate_script(task_id: str, topic: str, industry: str, brand_tone: str, max_seconds: int) -> ShortScript: prompt = f""" 你是{industry}行业的短视频编剧,擅长把枯燥信息编排成有冲突、有转折的剧情化短视频。 请围绕主题「{topic}」创作一条{max_seconds}秒以内的短剧脚本。 硬性要求: 1. 前3秒必须有钩子,可以从反常识结论、扎心提问、前后反差中选择。 2. 全片只围绕一个核心痛点展开,并用一个解决方案完成闭环。 3. 结尾必须有明确的引导动作。 4. 输出JSON对象,只包含以下key:hook, story_lines, shots, cta。 5. shots是数组,每个元素包含scene_type, duration, visual, subtitle, tts_text。 6. 每个shot的subtitle不要超过20个字,tts_text不要超过35个字。 禁止输出任何解释性文字,直接输出JSON。 """ messages = [{"role": "system", "content": "你是一个严谨的结构化内容生成器。"}, {"role": "user", "content": prompt}] raw = load_llm_client().chat(messages=messages, temperature=0.8) data = json.loads(raw) # 注意:实际要加异常重试,见3.4 shots = [ Shot( shot_id=f"shot_{i:03d}", duration=float(s["duration"]), scene_type=s["scene_type"], visual=s["visual"], subtitle=s["subtitle"], tts_text=s["tts_text"], ) for i, s in enumerate(data["shots"]) ] return ShortScript( task_id=task_id, industry=industry, brand_tone=brand_tone, hook=data["hook"], story_lines=data["story_lines"], shots=shots, cta=data["cta"], )这里的代码里有两个细节值得注意。一是temperature调到0.8,比默认的0.7稍微高一点点,让脚本多一些转折变化,但仍然保持稳定。二是title字段和tts_text字段分开。很多脚本第一次跑出来画面字幕和配音不一致,就是因为在Prompt里没区分这两个概念。分开之后,字幕可以精简,而旁白可以口语化完整,效果立竿见影。
3.3 合成端:从文字卡到视频帧的拼装
有了JSON剧本后,最繁琐的是生成画面。采用一个务实的方案:不是硬用大模型生成视频,而是用PIL库生成高质量的1080x1920竖版画面,配上动态字幕与装饰元素,然后交给FFmpeg转成视频。等于说,成片是以“动态图文卡+配音”为主要形态,少量穿插实拍素材。
from PIL import Image, ImageDraw, ImageFont def render_text_card(shot: Shot, output_png: str, bg_color=(30, 30, 45)): width, height = 1080, 1920 img = Image.new("RGB", (width, height), bg_color) draw = ImageDraw.Draw(img) # 头部装饰条,用来承载栏目信息 draw.rectangle([0, 0, width, 220], fill=(220, 40, 40)) draw.text((60, 60), "一图看懂", font=load_font(48), fill="white") # 主体区域:大号字幕 y = 620 for line in wrap_subtitle(shot.subtitle, max_chars=12): draw.text((80, y), line, font=load_font(72), fill="white") y += 130 # 底部引导条 draw.rectangle([0, 1650, width, 1920], fill=(40, 40, 40)) draw.text((80, 1710), shot.tts_text[:18], font=load_font(40), fill=(200, 200, 200)) img.save(output_png)这段代码看似简单,但有几个隐藏坑。字体文件一定要指定中文字体路径,PIL默认字体在中文环境下会直接变方块。wrap_subtitle函数需要按标点和字数切行,不要用简单的字符串切片,不然会把一个词横着截断。画面设计上也要控制颜色不超过三种,纯AI生成的配色容易花。
渲染好每一帧图片之后,再用FFmpeg把图片和音频合成视频片段。下面是单镜头合成的核心命令:
ffmpeg -y \ -loop 1 -t {shot.duration} -i {shot_png} \ -i {voice_mp3_path} \ -filter_complex "[1:a]aformat=sample_rates=44100:channel_layouts=stereo[voice]" \ -map 0:v -map "[voice]" \ -vf "scale=1080:1920,fps=30" \ -c:v libx264 -c:a aac -shortest \ {output_shot_mp4}这里最关键的是加了一行aformat=44100。很多TTS工具生成的音频采样率不一样,直接和视频拼接会导致整片音画不同步或者部分播放器不兼容。统一转成44100Hz立体声之后,出问题的概率大幅下降。另外-shortest参数保证视频画面时长和音频时长一致,不会出现画面结束了音频还在播的情况。
镜头全部合成完毕,再用concat协议把多个镜头拼接成一条草稿片:
ffmpeg -f concat -safe 0 -i concat_list.txt -c copy draft.mp43.4 调度端与重试机制:不稳定的不是代码,是大模型
最后是调度逻辑。我建议把整条流水线放在异步队列里跑,任务状态机从 pending、generating、rendering、reviewing 一直到 published。一旦某个环节失败,不要整条重跑,只重跑失败的环节。
def run_pipeline(task_id: str, topic: str, industry: str): script = generate_script(task_id, topic, industry) save_to_db(script) # 对每个分镜并行生成画面和音频 for shot in script.shots: render_frame(shot) synthesize_tts(shot) # 内部会做重试 compose_scenes(script) # 按序拼接 run_quality_check(script) # 自动质检 notify_reviewer(task_id) # 通知人工审核大模型接口偶尔会返回非法JSON,这是跑量之后最容易遇到的现象。我的处理方式是解析失败之后自动加一条纠正信息重新请求一次,如果连续三次失败才把任务标记为异常。不要简单地把异常抛出去,要在异常里存储当时的Prompt和响应原文,方便工程师复查究竟哪类Prompton总是诱发坏格式。
def safe_json_parse(raw_text: str, retries: int = 3): for i in range(retries): try: return json.loads(raw_text) except json.JSONDecodeError: if i < retries - 1: raw_text = load_llm_client().chat(messages=[ {"role": "system", "content": "把下面的内容修正为合法JSON,只输出JSON。"}, {"role": "user", "content": raw_text} ]) raise RuntimeError("连续三次大模型输出非法JSON,需人工介入")4. 同一套工厂、三种出货口径:教培、门店、媒体的差异化配置
代码跑通只是第一步,真正决定这套系统有没有商业价值的,是它能不能适应不同行业的不同出片要求。我同一套底层流水线,在三类客户那里分别做了完全不同的Prompt策略和画面包装策略。
4.1 教培方向:密度优先,30秒内给足知识点钩子
教培的内容落点是“让用户觉得这里有一套值得学的知识”。所以Promthon要求脚本在三秒内提出一个反常识说法,比如“考证不需要等到毕业之后”,然后在二十秒内给出一个有信息增量的观点,最后落到课程体验引导上。
画面风格固定为“讲师口播加文字卡”,不用花哨转场,因为教培用户看的是内容不是视觉。我们实测下来,教培口播类视频的信息密度越高,完播之后私信咨询率越好。反而那些加了花哨特效、分段过碎的视频,看起来精致但转化一般。
配置差异在于:不需要实拍空镜,全部镜头都用talking和card类型,因为对应的学员群体只想听“干货”。时长故意控制在40秒以内,正好是刷兴趣的最短耐心阈值。
4.2 门店方向:转化信息前置,团购链接是主角
门店类短剧的配置完全是另一个思路。脚本生成的Prompt里我写死了几个必带要素:套餐名称、折扣力度、使用限制、门店可核销。这些信息在脚本里必须出现在前15秒,不允许最后才讲。用户刷到门店视频时的心理状态是“今天是顺便刷到,过两秒就划走了”,你不把利益点提前,连看完的机会都没有。
画面风格则用大号价格标签、门店环境实拍和显眼的营业信息。我用的策略是:字幕除了旁白之外,再叠一行固定的“团购信息条”,这条信息来自结构化字段而不是AI生成,彻底避开大模型把价格写错的情况。门店视频还特别强调结尾的地图引导,所以CTA全部统一成“点击下方位置图标”。
顺带说一句,门店的素材复用率最高。一条实拍的产品视频可以拆成营销短剧、日常短视频、活动公告三种内容,本地上传一次素材,系统自动产出多条不同形态的成片,这才是降低边际成本的大头。
4.3 媒体方向:栏目化优先,把固定片头变成品牌资产
代运营客户最大的痛点是账号内容不成系列,今天一个风格、明天一个风格,用户根本记不住。所以我在媒体业务的配置里加入了“栏目包”概念。
每个媒体账号进入系统时,先绑定一个栏目模板,这个模板包含固定的片头动画、主持人口播开场词、统一的字幕条样式、固定的背景音乐。AI生成的只是中间的“文案肉”,壳永远是那套。坚持两周之后,账号的辨识度就起来了。
这一类的脚本Prompt要多加一条约束:“观点需要有两个递进层次,不要平铺直叙”。因为媒体号的内容竞争最激烈,只有信息密度或者情绪强度足够才能让人愿意划到下一个视频。
三种场景的配置差异可以汇总成一张表:
| 配置维度 | 教培 | 门店 | 媒体代运营 |
|---|---|---|---|
| 核心目标 | 建立专业信任 | 促进到店核销 | 打造栏目心智 |
| 时长策略 | 30-40秒 | 15-30秒 | 45-90秒 |
| 钩子类型 | 反常识知识 | 利益点价格 | 行业观点反差 |
| 画面风格 | 讲师口播+字卡 | 实拍+价格标签 | 固定片头+字幕条 |
| 结尾CTA | 私信咨询引导 | 地图位置引导 | 关注下期预告 |
| 素材复用率 | 低 | 高 | 中 |
| 人工介入频次 | 高 | 低 | 中 |
5. 部署与成本控制:并发、缓存和素材复用的实测经验
很多第一次做类似系统的人都低估了两件事:一是长视频合成的计算量,二是大模型的调用量。这两块成本控制不好,单条视频成本能高到让你怀疑这套系统到底省了哪门子钱。
5.1 资源参数与并发上限的参考
合成端对CPU性能比较敏感,尤其是1080x1920的逐帧渲染。我们实测下来,一台8核16G的云服务器,跑一条60秒、12个分镜的片子,纯渲染时间大约在90秒到180秒之间。瓶颈主要出在FFmpeg转码和PIL逐帧绘图上。
如果每天只出十条以内,单机加一个队列就完全够用,不需要上GPU,成本能压在很低。如果每天要出五十条,建议把合成服务拆出来,用两台同配置服务器做负载均衡。需要强调一点:不要用大模型接口来生成图片。这里的背景图用程序化渲染就足够,纯AI生图不仅贵,而且每张图风格还不统一,放一起反而别扭。
5.2 省钱的真正大头:素材切片复用
我踩过最大的成本坑,是把同一个口播素材反复输入TTS然后重新渲染。比如某讲师说过一句关于考证周期的金句,系统在十条视频里都引用到了,如果每次引用都重新调一次大模型生成文案、重新合成一次语音,成本就白涨上去。
解决办法是给素材库加一层指纹缓存。每一段原始素材录入时就计算一个哈希值,生成脚本时优先从素材库里检索“语义相似”的片段直接引用,只在没有匹配素材时才触发新的TTS生成。缓存命中率从0提升到60%之后,单条成片的综合成本直接下降了接近一半。
5.3 成片画质与生成时间的平衡
还有一个妥协要提前想清楚:画面精度和时间成本的平衡。刚开始我把所有画面都渲染成4K,结果一条片子合成要十来分钟。后来统一降到1080P,肉眼在手机上根本分辨不出明显差别,合成时间却缩短到一个合理范围。短视频平台对分辨率也没有强需求,1080P完全说得过去,没必要为画质自嗨。
字幕渲染也有讲究。PIL一次渲染一帧画面,如果背景图和字幕是分两个图层处理的,会多出一倍的磁盘IO。我把字幕和背景直接合成为一张图再送进FFmpeg,性能提升很明显。尤其当某个片段的字幕要重复叠加动态高亮时,合并渲染是更可控的方案。
6. 不保证“完全无人”:系统边界与上线后踩过的坑
这套系统上线到现在,我经常被问一个问题:“真的全自动了吗?”我的诚实回答是:生产动作全自动,但决策环节必须留人。系统真正的价值是把一个人一天只能做出五条片子的效率,放大到一个人一天能审核三十条片子。后面这些坑,每一处都是拿真金白银换来的教训。
6.1 审核不是系统的敌人,而是系统的一部分
第一版我把审核节点设计得过于宽松,脚本生成之后如果字段完整就直接进合成。结果有一天跑出来一条门店视频,开头稳稳的,到中间突然出现一段完全没意义的抒情文案,跟套餐毫无关系。原因是大模型抽风,把“打造品牌温度”理解成了写散文。从那天起,我强制加了脚本审核放行闸门,运营必须逐条确认脚本才能进入合成,虽然多了一步,但再没出现过内容方向漂移的事故。
6.2 反复出现的“AI味”:过拟合的背后是Prompt缺少约束
高频词是最顽固的问题。系统生成的前五十条视频里,十条里有六条会出现“在这个快节奏的时代”“你是否也曾经”这类空话。后来我在Prompt里加了“禁止使用以下开头:随着时代的发展、在当今社会、你是否也曾经”,并补充了一条“每个分镜的台词必须包含一个具象名词或动词”。加了这条约束之后,脚本质量肉眼可见地提升。
这条经验值得单独说一句:AI脚本的最大问题不是不流畅,而是太流畅了,流畅到没有一个具体画面和一个让人记住的细节。让prompt去逼模型写出具象的词,是成本最低但效果最明显的做法。
6.3 版权与素材合规:纯自动分发在绝大多数场景是禁区
如果你和我想法一样,想把发布动作也做成全自动,我的建议是在做成之前先想清楚两个底线问题:素材版权和平台规则。背景音乐和实拍素材如果没有授权,AI又不会帮你判断版权,自动发布流程反而会放大侵权风险。我现在的做法是分发动作停留在“生成排程清单和配套文案”,由运营在平台后台或者借助官方工具统一发布,账号安全比省几分钟重要得多。
6.4 拆机之后的最终反思:什么是不能自动化
流水线化之后,看起来一切都在变快,但真正值钱的其实不是速度,而是你对业务的理解。选题标签体系、品牌调性定义、分镜审美、审核标准,这些决定内容基调的东西仍然是人做的。系统能做的是把“对的内容”用更快的方式发出去,但它不能替你判断“什么是对的内容”。
我很喜欢一个比喻:AI短剧创作系统像是一条工厂流水线,它能24小时用同一套标准生产出合格品,但研发合格品标准的人,永远是工厂真正的竞争力。产品生产线的意义不在于让工程师失业,而是把工程师的时间释放出来,去设计下一条更好的产线。
最后分享一个我保持至今的习惯:每周抽半天,把系统生产出来且数据最好的十到二十条片子翻出来,一条条看,找出它们共通的结构,然后把这个结构写进Prompt模板里。系统不会自己进化,进化它的人,还是你。