你刷短视频的时候,一定见过那种:一个震惊标题,一段机械感十足的配音,配上循环的背景画面和满屏花花绿绿的字幕,三分钟讲完一个所谓“惊天真相”。看多了甚至想自己动手搞一个“营销号视频生成器”,把这种重复劳动彻底自动化。我在本地跑通了一整套流程:输入一段文本,自动生成配音、背景视频、字幕、封面,最后批量吐出成品视频。这东西本身不复杂,关键是把套路拆清楚,再把模块拼起来。这篇就把我的完整方案、踩过的坑和调参经验全部写出来。适合想做短视频工具的技术爱好者、自媒体运营,以及所有想把“剪视频”这件事批量化的朋友。
1. 营销号视频的套路拆解与生成器设计思路
1.1 营销号“标准配方”到底是什么
先说结论:绝大多数营销号视频,信息密度很低,套路高度统一。拆开看,就是四层:
- 标题层:用最大号字体放标题,文字必须带悬念和情绪词,比如“震惊”“竟然”“幕后”“真相”。标题字号要大,配色要红黄配,最好再加个白色描边。
- 配音层:一个稳定的TTS声音,语速偏快,把文案逐句念完。文案结构一般是“抛出问题→举例子→反转→总结”,每句话尽量短。
- 画面层:背景视频基本不承载信息,只是让画面不静止。常见做法是拍城市车流、街道漫步、风景空镜,或者干脆是模糊处理的横屏视频。
- 字幕层:每一句配音对应一行字幕,字幕字号大、位置偏下,关键句还会变色或放大。
这套配方的可怕之处在于,它不依赖任何原创画面和深度文案,只要素材够多就能无限量产。所以如果要做一个生成器,本质上就是把上面四层用代码自动拼起来。
1.2 生成器的模块划分与技术选型
我的实现没有用什么重型框架,全部基于Python脚本加命令行工具。整条流水线拆成六个模块:
| 模块 | 负责内容 | 我的选型 |
|---|---|---|
| 文案模块 | 根据关键词生成脚本文本 | Python规则模板,可选接大模型API |
| 素材模块 | 准备背景视频和图片 | 本地素材库 + ffmpeg裁剪 |
| 配音模块 | 把文本转成音频 | 开源TTS引擎 / 云TTS |
| 字幕模块 | 生成字幕文件和样式 | Python写SRT + ASS样式控制 |
| 合成模块 | 把音频、视频、字幕封装成成品 | ffmpeg命令行 |
| 封面模块 | 根据标题生成视频封面图 | Pillow |
选择这套组合的原因很直接:ffmpeg本身是最稳定的视频处理工具,几乎不需要额外开发就能完成裁剪、拼接、混音、压制字幕;TTS选型灵活,可以先本地离线跑通再切换商用音色;Pillow生成封面比用PS手动做快得多,而且代码一跑就是几十张。
1.3 为什么我选择本地脚本而不是在线工具
一开始我也考虑过用在线平台,比如找现成的视频生成网站,把文案粘进去就能出片。实际试下来有三个问题:
- 单条生成没问题,批量生成很痛苦。在线平台通常有次数限制,而且每生成一条都要等队列。
- 素材上传和字幕格式受平台限制,根本没法做精细控制。
- 最关键的是,在线工具等于把你的文案脚本和素材全部交给第三方,涉及隐私和版权风险。
所以我把整个流程做成本地脚本,原料都在自己手里,最终产物也是自己硬盘上的MP4。这样既能反复调参,又能随时扩展功能,后续想接入不同的TTS、字幕模板或视频素材源都很容易。
2. 文案与素材模块:先把“米”备好
2.1 模板化文案生成:不靠灵感靠规则
营销号文案不需要多深刻的创作,关键是短句、有转折、情绪递进。我先写了一套基础模板,核心思路是“关键词替换 + 段落结构拼接”。
我用一个Python字典定义段落结构:
templates = { "震惊型": [ "你知道吗?{topic}的背后,竟然藏着这样的秘密。", "很多人都在问,{topic}为什么会突然爆火?", "今天我用一分钟,带你看看{thing}的真实面目。" ], "反转型": [ "所有人都以为{false_view},其实真相并不是这样。", "这件事表面上看起来很正常,但是仔细分析就会发现不对。", "专家不会告诉你的,其实才是重点。" ] }调用时,先从热点词表里随机选一个主题,再按顺序抽句式,拼成一段约60到120字的文案。然后拆句列表,每句控制在20字以内,方便后续配音和字幕。
如果你手上接了大模型API,也可以让模型根据主题生成文案,但我的经验是纯模板生成的结果更可控。因为模型偶尔会写出太长的从句,或者用词太书面,反而不符合营销号的“口语短句”风格。所以我的最终方案是:模板打底,可选大模型二次改写,但改写后仍然要做“短句拆分”。
2.2 背景视频素材:素材库、裁剪与循环处理
背景视频是整个流水线里最容易翻车的地方,因为剪辑软件里随手拖进来的素材,到了ffmpeg里往往尺寸不对、时长不够、码率奇葩。
我建了一个本地素材目录,按“城市”“街道”“风景”“室内”等标签管理。优先使用自己拍摄的素材,其次是CC0授权素材。然后把每个素材都统一处理成项目需要的格式,避免合成时出错。
处理素材的第一件事是裁剪时长。如果原素材只有5秒,而我需要30秒的底视频,就得循环拼接。ffmpeg有专门的loop参数,但是直接loop再截断有些讲究:
ffmpeg -stream_loop 5 -i original.mp4 -t 30 -c:v libx264 -r 30 temp_loop.mp4这里-stream_loop 5表示把输入流多循环5次,-t 30限定总时长30秒。如果只写-stream_loop不限时长,文件会一直往下编码,最后可能变成几十分钟的大文件,非常浪费磁盘。
第二个关键是竖屏适配。成品平台主要是手机播放,所以我输出1080x1920竖屏。但素材大多是1920x1080横屏,直接拉伸会变形,直接裁剪又可能丢掉重要内容。我选了常见处理方式:背景用模糊放大的横屏原视频,前景再叠一层竖屏裁剪版。这样既保底清晰,又能让画面保持动态感。
# 生成模糊背景层 ffmpeg -i original.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20" -r 30 bg_blur.mp4 # 生成前景层 ffmpeg -i original.mp4 -vf "scale=540:960" fg.mp4最后在合成阶段用overlay把前景叠到模糊背景上,视觉上就很像手机竖屏视频的处理效果。这个方案比单纯裁横屏到竖屏要耐看很多,而且代码量不大。
2.3 字幕文件自动生成与时间轴预估
字幕是营销号视频的视觉重心,但很多人会忽略它的时间轴问题。配音还没生成的时候,字幕时间怎么定?
我的做法是:先用TTS把整段文案合成为一条音频,同时拿到音频总时长。然后把文案按句子列表切分,根据每个句子的字符数占全文字符数的比例,去分摊总时长。这里假设TTS语速稳定,实际误差通常在0.5秒以内,基本可接受。
接下来把字幕写成SRT格式:
def gen_srt(sentences, timings, output_path): with open(output_path, "w", encoding="utf-8") as f: for idx, (sent, (start, end)) in enumerate(zip(sentences, timings), start=1): f.write(str(idx) + "\n") f.write(f"{start} --> {end}\n") f.write(sent + "\n\n")SRT的时间格式是HH:MM:SS,mmm,需要自己封装一个转换函数。后面压制硬字幕时,ffmpeg会自动读取SRT,按照时间显示字幕。
这里有个经验:字幕不要平分时间,因为中文句子的字数差很大。更准的办法是按字数比例分配,也可以先给每个字估算0.35秒,再根据整段音频时长做缩放修正。这样至少不会出现“字幕都播完了,语音还没说话”的尴尬。
3. 配音与视频合成:打通音画链路
3.1 TTS选型与效果调优
配音是决定生成视频“像不像营销号”的核心环节。营销号配音有两个特点:快、平。音调起伏不大,语速比日常说话快一点,听感上有点“念稿子”的感觉。
我建议分两步走。第一步先用系统自带的离线TTS跑通全流程,比如开源TTS引擎,快速验证逻辑。第二步再切换到音质更好的云TTS服务,获得更自然的中文合成音。两种方式在脚本里可以做成一个抽象层,传入配置项切换。
TTS参数上我最常调的是语速和音调。离线引擎里语速单位是words_per_minute,我一般设置在180到200之间;云服务则用百分比调节,通常设置在110%到120%。音调不要调太高,否则会显得“油”,机器感反而更强。
还有一个细节:配音前要把多余空格和换行压缩掉,因为TTS会把换行当成断句,产生异常停顿。我的处理是先调用split_sentences切句,再把每句内部的空白字符全部正则合并,最后按句列表传给TTS。
3.2 音画同步与自动剪辑实现
素材和配音都有了,接下来是让视频画面跟着音频走。其实营销号视频的剪辑节奏很简单:一句话匹配一个画面段,画面之间用硬切,偶尔加点缩放或转场。为了减少转场的编码复杂度,我选择硬切。
具体做法是:先根据每个句子的时间点,把背景视频切成对应长度的多个小片段,然后用ffmpeg concat拼接成总视频。这里我踩过坑:如果直接用不同来源的素材拼接,分辨率、帧率、编码参数不一致,concat会直接报错。所以我事先把所有素材统一成1080x1920、30帧、H264编码。
切片的命令模板:
ffmpeg -ss {start} -i bg_processed.mp4 -t {duration} -c:v libx264 segment_{i}.mp4全部拼接后再叠加音频:
ffmpeg -i concat_list.txt -i audio.mp3 -c:v copy -c:a aac -shortest output.mp4我在实际测试中发现,concat_list.txt里的路径不能有空格和特殊字符,否则ffmpeg会把文件路径解析成多个输入。稳妥做法是先把所有切片素材放到同一个目录,用相对路径或者纯英文文件名。
3.3 ffmpeg合成参数详解
如果你也想复现,可以直接用这条主合成命令:
ffmpeg \ -i bg_total.mp4 \ -i voice.mp3 \ -i subtitle.srt \ -vf "subtitles=subtitle.srt:force_style='FontName=Microsoft YaHei,FontSize=16,PrimaryColour=&H0000FFFF,OutlineColour=&H00000000,Outline=2,MarginV=80'" \ -map 0:v -map 1:a \ -c:v libx264 -preset medium -crf 23 \ -c:a aac -b:a 192k \ -tune stillimage \ -shortest \ final.mp4解释几个关键参数:
subtitles=subtitle.srt:把SRT字幕烧进视频。如果不想硬编码,想保留可切换字幕,可以用-c:s mov_text,但手机端播放兼容性不如硬字幕。FontName必须使用系统里已安装的字体名。我之前在某个精简环境里写Microsoft YaHei,实际字体没装,ffmpeg直接报错,后来改成系统里确定存在的“Noto Sans CJK SC”才正常。crf 23是质量和码率的平衡点。对纯色背景和字幕类视频,23足够。要更清晰可以把CRF降到20,但文件体积会变大。-shortest保证输出时长和短的输入流一致,避免画面或音频多出一大截。
如果要做多条视频,建议把这段命令封装成函数,只改输入路径。ffmpeg的命令行参数非常多,但真正有用的就这几个,属于“二十条命令精通80%场景”的那类。
4. 批量生产流程与封面生成
4.1 用Pillow快速生成标题封面
营销号视频的封面和标题往往是点击率的关键。我自己最常用的封面是:红色渐变背景、白色加粗大字、文字底部加影子,局部放一两个强调词。
用Pillow实现:
from PIL import Image, ImageDraw, ImageFont def gen_cover(title, output): img = Image.new("RGB", (600, 800), "#cc0000") draw = ImageDraw.Draw(img) font = ImageFont.truetype("bold.ttf", 48) # 逐行拆分标题,最多两行 lines = split_title(title, max_chars=8) y = 250 for line in lines: draw.text((300, y), line, font=font, fill="white", anchor="mt") # 画个阴影增加立体感 draw.text((302, y+2), line, font=font, fill="black", anchor="mt") y += 90 img.save(output)注意中文长标题一定要按字数自动换行,否则就被图片边缘切掉了。我的split_title方法会在第8个字符处断行,如果某行刚好有标点符号,则优先在标点后断行。字体文件建议使用开源的思源黑体或阿里巴巴普惠体,不要打包来路不明的字体,避免版权风险。
4.2 批量任务编排:文本进,视频出
单个视频能跑通后,批量生产就顺理成章了。我在项目根目录放一个tasks.csv,每一行代表一个视频任务,用英文逗号分隔标题、文案、风格标签、背景素材标签。
脚本流程大概是:
for task in read_tasks("tasks.csv"): text = generate_script(task["topic"]) gen_cover(task["title"], f"covers/{task['id']}.png") tts(text, f"audios/{task['id']}.mp3", voice=task["voice"]) gen_srt(sentences, timings, f"subs/{task['id']}.srt") render_video(f"videos/{task['id']}.mp4", ...) log.info(f"完成: {task['id']}")每个环节都加了log,方便断点排查。我建议把所有中间产物都保留,不要想着只保留最终MP4,因为后面改风格、改字幕、换配音都还要重新合成,中间文件删了就得重新跑一遍TTS,特别浪费时间。
批量处理还要注意磁盘空间。一条30秒视频的中间文件,包括切片、音频、字幕、封面,可能占用几百MB。我一般每处理完一个任务就清理该任务的临时目录,只保留最终MP4和SRT、封面。可以写个cleanup(task_id)函数,定时或手动调用。
4.3 发布前的内容合规自查
老实说,这个工具太容易用来生产垃圾内容了。所以我在脚本里加了一个强制自查环节:每次生成完视频,都会在终端打印一份清单,让操作者逐项确认。
清单包含这几项:
- 标题是否夸大事实或虚构信息
- 文案是否包含未经证实的医疗、投资、政策类断言
- 素材是否涉及肖像权、商标、他人版权画面
- 是否通过搬运、洗稿等方式窃取他人劳动成果
- 生成的视频是否会在平台上造成误导或诈骗风险
我的原则是:这个生成器只用于技术学习、创意演示、内部测试,以及你完全有权利处理的素材。如果你把“营销号风格”当成一种视频剪辑风格模板,用于自己的原创内容,那完全没问题;但如果拿去批量洗稿、造谣、引流到非法产品,那工具就是帮凶了。这个边界必须自己守住。
5. 常见问题与排查技巧实录
5.1 配音机械感严重怎么办
这是最容易遇到的问题。离线TTS声音就是“机器人”,尤其长句子更明显。我的处理顺序是:
- 检查是不是语速太慢。营销号配音语速放到120%以上,机械感会被“一带而过”降低一部。
- 换音色。开源TTS通常提供多个音色,我们测试后选最接近新闻播报的那一个。
- 在音频合成后加一点混响或EQ。用ffmpeg就能做:
ffmpeg -i voice.mp3 -af "equalizer=f=200:t=q:w=1:g=-2,equalizer=f=2000:t=q:w=1:g=3,aecho=0.8:0.9:20:0.3" voice_enhanced.mp3去掉200Hz左右的低频浑浊,提升2kHz附近的声音亮度,听感立刻会“精神”很多。注意aecho参数不要开太大,否则就像在峡谷里说话,更假。
5.2 音画不同步与导出失败排查
出现音画不同步,我第一步先检查音频和视频的实际时长:
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 voice.mp3 ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 bg_total.mp4如果视频比音频长,可能是背景视频的循环拼接没有在精确时间点截断,导致多出零点几秒。如果音频比视频长,多半是TTS生成的音频比预估时间长,字幕时间轴完全对不上。这时候要去调整SRT生成时的“字符时间系数”,而不是手动挪字幕。
导出失败一般看ffmpeg的错误日志。最常见的是Non-monotonous DTS in output stream,这个警告多半是输入视频文件本身有损坏或时间戳错乱,重新跑一遍素材预处理就能解决。如果真的不行,就把视频先解码成无压缩帧序列,再重新编码输出,绝对能绕过去。
5.3 视频合成太慢、内存占用过高
营销号视频任务一多,ffmpeg CPU占用会一直拉满。我这里总结出三个有效优化手段:
- 使用更快的预设。把
-preset medium改成-preset veryfast,速度提升明显,对字幕和简单画面来说画质损失肉眼不可见。 - 启用硬件编码。如果你的电脑有NVIDIA显卡,用
-c:v h264_nvenc,编码速度是软编码的好几倍。命令行示例:
ffmpeg -i bg_total.mp4 -i voice.mp3 -c:v h264_nvenc -preset p4 -cq 30 -c:a aac -shortest output.mp4- 避免过度拼接切片。如果视频结构是“一句一画面”,不要切成几十个MP4再concat,那样会反复编码,特别慢。更好的做法是直接生成一个带时间点的concat滤镜,或者用
select滤镜在单次ffmpeg调用里完成剪辑。
内存占用过高的原因通常是-stream_loop次数太大,或者输入素材分辨率超过4K。营销号视频1080p足够,不用用4K素材硬压,否则时间全花在转码上。
5.4 字幕样式与位置不理想
字幕的坑在字体和位置。ffmpeg的force_style里,字体名必须用系统已安装字体。中文字体如果缺失,ffmpeg会改用默认字体,中文全部显示成方块。
检查字体是否可用:
fc-list :lang=zh | head -20如果没有任何中文字体,先装一个。字幕位置常用MarginV,单位是像素,表示距离画面底边的距离。竖屏视频建议MarginV=120左右,不要太贴底,否则会被手机播放器的进度条挡住。
字号建议不用固定像素,而是按画面高度比例算。1080x1920竖屏,字幕高度大约在60到80像素比较合适。如果字幕压完还是太小,就把FontSize调到20以上,同时加粗字幕轮廓,这样在手机小屏幕上也能看清。
5.5 素材来源不清导致的版权隐患
最后的提醒是关于素材。我早期跑测试时,随手从网上下了一堆视频当素材,结果某条生成出来的视频被平台识别出重复内容,直接限流。后来我全部改成自己的实拍+CC0素材库,再用本地脚本统一归档,每条视频的tasks.csv里都记录了素材来源标签。
千万别小看这一步。营销号视频最大的法律风险不是技术,而是你用了不该用的素材。如果你要长期用这套生成器,一定要建立自己的素材来源台账,至少要知道每个背景视频从哪里来、有没有授权。宁可画面单调一点,也不要让自己陷入版权纠纷。
我自己跑完这个项目以后,最大的体会是:营销号视频看似粗制滥造,但背后那套“情绪标题+短句文案+循环画面”的组合逻辑,其实非常精准地抓住了人的注意力。你把它做成生成器,反而能更清楚地看到内容生产中的重复劳动到底有哪些。最后再分享一个小技巧:如果你不想让生成出来的东西“一眼营销号”,只需要把语速调回正常、字幕样式改成干净的白底黑字,删掉震惊标题,同一个流水线就能变成一个非常实用的“口播视频工具”。这套工程化思路的扩展空间很大,后面完全可以继续接热点词、多语言配音,甚至做成一个带简单界面的本地工具。工具本身是中性的,怎么用,取决于你。