简介:这是一个基于Pixelle-Video的AI全自动短视频创作引擎源码包,面向希望快速批量生成解说、科普、故事类短视频的开发者或内容创作者。用户只需输入一个主题,工具即可自动完成文案、配图、语音、背景音乐和视频合成等全流程,并支持GPT、通义千问、DeepSeek等大语言模型以及Edge-TTS、Index-TTS等语音方案。在ComfyUI架构下,各原子能力可自由组合,便于替换生图模型或TTS服务。压缩包共284个文件,约8.4MB,其中95个Python脚本为核心源码,43个Markdown文档提供配置说明,31个HTML为可视化界面模板,另有启动脚本、Dockerfile与示例素材,方便本地快速部署和二次开发。资源按启动入口、Web模板、工作流配置与核心模块分层组织,便于按需裁剪和复用。目前已有453人学习,适合具备一定Python基础、希望搭建自动化短视频流水线的开发者参考。
1. AI 全自动短视频创作引擎:它自动了哪一段,又留了什么给你
做了几年短视频自动化,我的判断很直接:批量做号的人不缺剪辑手,缺的是把“今天发什么、文案怎么写、配什么画面、最后怎么拼”这套决策链串起来的人。这正是“AI 全自动短视频创作引擎”这类源码工程想解决的问题——你丢一个选题进去,它把大模型生成脚本、语音合成、字幕对齐、素材匹配、渲染切片打包成一条流水线,出来后就是一条能发的成片。它适合三种人:批量运营账号的内容团队、接短视频外包的独立开发者、想搭内部素材测试管线的技术人。但“全自动”不等于无脑,你真把它跑起来才会发现,自动的是重复劳动,真正要人盯的是素材质量和检查点设置。下文我按这类工程最常见的源码组织方式讲,从流水线拆到部署,再落到调试参数和踩过的坑。
2. 流水线拆解:从一句选题到成片的五个环节与中间件设计
绝大多数“AI 全自动短视频创作引擎”跑起来以后,内部也就是五个环节:文案生成、分镜解析、素材检索、语音与字幕对齐、渲染封装。这五个环节环环相扣,但真正决定整个系统好不好改的,是它们之间传递的数据格式。很多自研引擎把文案直接塞给渲染模块,后面想换文案风格就得改渲染代码,这是最典型的翻车设计。
2.1 文案与分镜:大模型只负责产出“中间件”
大模型在这类引擎里并不直接生成视频,而是生成一份结构化的分镜 JSON。这份 JSON 是整条流水线的中间件,所有下游模块都只依赖它,不依赖大模型本身。
{ "title": "为什么你的短视频没人看", "voice": "zh-CN-XiaoxiaoNeural", "scenes": [ { "index": 1, "duration_hint_sec": 4, "narration": "很多账号做不起来,问题根本不在剪辑。", "visual": "城市夜景车流,慢速延时摄影", "effect": "fade" }, { "index": 2, "duration_hint_sec": 5, "narration": "而是你的开头三秒留不住人。", "visual": "手机屏幕下滑,划走视频的画面", "effect": "cut" } ] }用 JSON 做中间件有三个实际好处。第一,它可校验,渲染前用 JSON Schema 检查字段是否齐全,能挡掉大模型偶尔漏字段导致的空指针。第二,它可缓存,同一个选题文案不变,重跑时能跳过整个文案生成环节,省一次 API 调用。第三,它可人工改,运营不想动代码时,可以直接改 JSON 里某一镜的画面描述,优先级比自动素材检索高。
分镜 JSON 里有几个字段是后来才补上的,但很值得注意。duration_hint_sec是预估时长,实际要以语音音频的时长为准,它只是给素材检索模块一个“这一镜大概多长”的参考。visual是画面描述词,素材检索全靠它。effect是转场类型,我一般只保留 fade 和 cut 两种,复杂的转场在批量渲染时极其容易翻车。
每段文案生成时,我会在大模型调用里强制输出 JSON,并且要求每个 scene 的 narration 不超过 60 个字。原因很朴素:短视频单镜头的停留时间一般在 3 到 6 秒,60 个字按正常语速已经接近 6 秒的朗读上限。如果生成器吐出一段 200 字的长台词,渲染出来的画面就会“一个镜头撑到天荒地老”,观感很差。
2.2 素材检索与抽帧:直接决定画面能不能对上词
分镜 JSON 里的visual只是描述词,真正要变成画面,得靠素材检索模块去本地素材库里找匹配片段。常见做法是素材库按语义标签组织,每个文件在入库时打上一组关键词标签,检索时把visual里的词和标签做加权打分匹配。
打分规则看起来简单,但有个容易被忽略的维度:素材时长。一个 20 秒的长素材可以被裁成多段重复使用,而一个 2 秒的短素材如果被塞进 5 秒的镜头,渲染时就只能慢放,画面会明显卡顿。我一般会在打分公式里加一个时长惩罚项——素材时长与目标镜头时长偏差超过 20% 时直接扣分。
素材检索还有一个必须加的逻辑:兜底。无论打分怎么调,总会出现“库里确实没有匹配画面”的情况。这时候如果强行选一个低分素材,成片里就会出现画面和文案完全无关的尴尬镜头。正确做法是,当最高分低于某个阈值时,不选素材,改用“标题大字 + 纯色背景”渲染一镜静态画面。这个兜底动作成本极低,但能把成片的观感下限兜住。
2.3 渲染合成:字幕、配音、转场在哪一步做
渲染合成的顺序是固定的:先对齐语音和文本的时间轴,再生成字幕文件,最后把字幕、配音、素材一起封装成视频。顺序不能反过来。如果先渲染视频再压字幕,文案一改就得重新渲染整条片子,纯属浪费算力。
分段渲染再接回是批量产片的主流做法。每个分镜单独渲染成一小段无字幕视频,最后用 FFmpeg 的 concat demuxer 拼接,再统一烧录字幕。字幕烧录的正确姿势是用 subtitles 滤镜,而不是 drawtext——drawtext 只能一行一行手动排,srt 文件里的时间轴它无法直接解析。
ffmpeg -y \ -f concat -safe 0 -i clips.txt \ -vf "subtitles=final.srt:force_style='FontName=Noto Sans CJK SC,FontSize=18,PrimaryColour=&H00FFFFFF,OutlineColour=&H00101010,Outline=2'" \ -c:v libx264 -preset medium -crf 23 -pix_fmt yuv420p \ -c:a aac -b:a 128k \ output.mp4这里每个参数都值得解释。-f concat -safe 0从clips.txt读取片段列表,-safe 0允许文件列表里出现相对路径之外的路径。subtitles=final.srt是把字幕烧进画面,force_style里FontName=Noto Sans CJK SC必须指向系统里真实存在的字体,否则字幕渲染成方块。-crf 23是 H.264 的恒定质量参数,数值越小码率越高画质越好,批量产片我常用 23,预览用 20,错不了太大。-pix_fmt yuv420p则是兼容性关键,不写的话某些播放器会出现绿色画面或无法播放。
分段渲染的另一个关键约束是,所有分段视频的编码参数必须完全一致。分辨率、帧率、编码器、profile 只要有一个不一致,concat 拼接后就会出现音画不同步。这也是很多引擎干脆不用 concat、而是把所有分镜用同一组滤镜参数一次渲染完的原因——省心,但改单镜头的代价就变高了。
3. 用源码包本地部署:环境、依赖与三组必调配置参数
拿到源码包之后,第一步不是读代码,而是把环境装到“能跑”的状态。这类引擎的源码包里一般会带上requirements.txt、配置文件模板和启动脚本,但系统级依赖常常不写在里面。装环境踩坑的性价比极高——一次装好,后面能省出几十次排查时间。
3.1 依赖清单与 Python 虚拟环境
我先说结论:用 Python 3.10 或 3.11 建虚拟环境,别直接用系统自带的 Python。3.12 以上版本在安装部分深度学习依赖时可能没有预编译 wheel,得现场编译,一等就是半小时起步。
python3.10 -m venv .venv source .venv/bin/activate pip install --upgrade pip pip install -r requirements.txtrequirements.txt里大约会覆盖这几类:大模型 SDK 用来调用文案生成接口;语音合成库生成配音;OpenCV 和 moviepy 做图像与视频处理;pydub 处理音频切片;torch 和 transformers 这类是可选的,只有本地跑语音模型或 CLIP 素材打分时才真正用上。
有一个依赖需要单独提一下:FFmpeg。很多库在 pip 安装时会自动带一个ffmpeg-python包,那只是命令行封装工具,它本身不提供 FFmpeg 可执行文件。如果系统没装 FFmpeg,引擎会在调用 ffprobe 那一步直接报FileNotFoundError,而报错信息极容易让人误以为是 Python 包没装好。
装完依赖后做的第一件事,是在虚拟环境里跑一下ffmpeg -version和python -c "import cv2",确认二进制和关键 Python 包都正常。这一步只要 10 秒,但能把“环境没装好”和“代码有 bug”两类问题彻底隔离开。
3.2 FFmpeg、字体与素材目录的约定
系统级依赖里,FFmpeg 是硬性要求,而且必须带 ffprobe。ffprobe 在渲染引擎里的作用很核心:读取每个素材视频的分辨率、时长、帧率,资源检索和分段渲染都要靠它拿元数据。安装方式按对应操作系统的包管理器装即可,装完确认版本高于 4.x 就行,太旧的版本对 concat demuxer 和 subtitles 滤镜支持不完整。
字体是另一个经常被忽略的系统级依赖。短视频渲染必然要烧字幕,中文字幕需要系统里存在一个完整的 CJK 字体文件,否则字幕全是方块。常见做法是把一个.ttf或.otf字体文件直接放进项目的fonts/目录,并在配置里指定字体路径——这样部署到服务器时不会受系统字体库影响。
目录结构通常遵循一个固定约定,源码包里的config.example.yaml会写得很清楚:
| 目录 | 作用 | 注意事项 |
|---|---|---|
raw/ | 原始素材视频库 | 入库时最好做语义打标和查重 |
voice/ | TTS 生成的配音文件 | 建议按任务 ID 建子目录,方便重试 |
subtitle/ | 对齐后的字幕文件 | 中间产物,渲染完可保留备查 |
output/ | 最终成片 | 按日期归档,便于批量产片管理 |
素材目录的命名和归档逻辑值得在一开始就定好,而不是等素材多了再收拾。引擎检索素材时,如果raw/里混入了损坏的视频文件或非视频文件,ffprobe 读不出元数据,轻则跳过、重则整个任务崩溃。我习惯在入库阶段用脚本对每个文件做一次 ffprobe 探测,读不出来的直接丢进raw/_broken/隔离,不让它进检索池。
3.3 配置文件里的三组关键参数
这类引擎的配置基本都集中在 YAML 文件里。源码包一般会给config.example.yaml,你需要复制成config.yaml再改。重点关注的参数就三组,每一组都能直接决定成片效果。
llm: provider: openai base_url: http://localhost:11434/v1 model: qwen2.5:7b temperature: 0.7 max_tokens: 2048 tts: voice: zh-CN-XiaoxiaoNeural rate: +10% volume: +0% render: width: 1920 height: 1080 fps: 30 crf: 23 preset: medium font_path: fonts/NotoSansCJK-Bold.ttf第一组是大模型参数。base_url写本地推理服务的地址就是完全本地化的部署,写云端 API 地址就是用在线模型。temperature直接影响文案的稳定程度——批量产片时我建议把 temperature 压低到 0.6 到 0.7,不建议为了“更有创意”调到 1.0 以上,温度一高文案就开始跑题,生成的 JSON 结构也更容易出错。
第二组是 TTS 语音参数。rate: +10%表示语速加快 10%,这是短视频常用的设定。短视频前 3 秒要快速给信息,语速太慢观众直接划走;但语速超过 +20%,语音识别对齐时就会频繁出现错字,字幕和语音对不上。voice参数选哪个人声,要看本地环境有没有安装对应的语音模型,不是所有 voice 名称都能直接用。
第三组是渲染参数。width、height、fps决定分辨率和帧率,短视频平台主流是 1080p 30 帧,竖屏就写 1080x1920,横屏写 1920x1080。注意分辨率不要写反,写反了渲染不会报错,但成片会被平台判定为低质内容。crf和preset是质量和速度的权衡,本地批量渲染可以开preset: fast加速,画质损失肉眼几乎看不出。
这三组参数里的每一项,配置模板里都会有默认值。默认值能跑,但不一定适合你的场景。我拿到一个新源码包的第一件事,就是逐个确认这三个部分是否匹配本机资源和目标分发平台,而不是直接跑示例命令。
4. 核心代码走读:跑通一条最小成片的命令与两个关键函数
环境装通、配置改好之后,就该真正跑一条最小成片了。所谓最小,就是不追求效果惊艳,只求用最短路径把“文案 + 语音 + 素材 + 字幕 → 视频文件”这条链路跑通。下面两个函数是所有同类引擎里最核心的公共部分,理解了它们,你看任何一个具体源码包的入口脚本都会快很多。
4.1 字幕生成与波峰对齐:拿到语音的逐字时间轴
字幕不能直接用文案按固定间隔切。正常人的语速不恒定,停顿、重音都会让固定切分对不上。常见做法是先用 TTS 合成语音,再用语音识别模型把这段音频转写一遍,拿到每个词出现的时间戳,用这个时间戳去生成字幕。
import subprocess, json, os def text_to_speech_and_align(text: str, voice: str, rate: str, task_id: str) -> dict: os.makedirs(f"voice/{task_id}", exist_ok=True) voice_path = f"voice/{task_id}/speech.mp3" subprocess.run([ "edge-tts", "--voice", voice, "--rate=" + rate, "--text", text, "--write-media", voice_path ], check=True) from faster_whisper import WhisperModel model = WhisperModel("small", device="cpu", compute_type="int8") segments, _ = model.transcribe( voice_path, language="zh", word_timestamps=True, vad_filter=True ) words = [] for seg in segments: for w in seg.words: words.append({ "word": w.word, "start": round(w.start, 3), "end": round(w.end, 3) }) return {"voice_path": voice_path, "words": words}这段代码的逻辑是:先调用 edge-tts 命令行工具合成语音,再用 faster-whisper 对语音做带时间戳的转写。faster-whisper相比原版 whisper 速度更快、内存占用更低,在 CPU 机器上也能跑。这里有两个参数值得注意:word_timestamps=True让识别结果细化到词级时间戳,这是后面生成准确字幕的关键;vad_filter=True会滤掉音频开头的静音段,避免一条配音在最前面留出 1 秒空白,让字幕和声音无法对齐。
实际跑的时候你会发现,whisper 转写出的中文字幕和原文案的字不完全一致。这是正常的,因为 TTS 生成的语音里数字、标点会被读成不同的形式。我的处理策略是“字幕以转写结果为准,而不是以原文案为准”。因为字幕最终要跟声音对得上,哪怕字幕里有个别字的差异,也比字幕和声音明显不同步要好。
4.2 用配置驱动渲染的入口脚本:把时间轴写进 srt
拿到词级时间戳之后,下一步就是按分镜边界把它切成分镜字幕文件,再渲染拼接。这一步的入口函数是整条流水线的汇总点:它读分镜 JSON、读词级时间戳、调 FFmpeg 分段渲染、最后拼接输出。
import subprocess, json, glob def render_clip(video_path: str, srt_path: str, output_path: str, cfg: dict) -> None: cmd = [ "ffmpeg", "-y", "-i", video_path, "-vf", ( f"scale={cfg['width']}:{cfg['height']}:force_original_aspect_ratio=decrease," f"pad={cfg['width']}:{cfg['height']}:(ow-iw)/2:(oh-ih)/2:color=black," f"subtitles={srt_path}:force_style=" + ( f"FontName={cfg['font_name']},FontSize=18,Outline=2" ) ), "-c:v", "libx264", "-preset", cfg["preset"], "-crf", str(cfg["crf"]), "-c:a", "aac", "-b:a", "128k", output_path ] subprocess.run(cmd, check=True) def run_pipeline(scene_json: dict, cfg: dict) -> str: clips = [] for scene in scene_json["scenes"]: video_path = fetch_best_material(scene["visual"], scene["duration_hint_sec"], cfg) srt_path = build_scene_srt(scene, cfg) clip_path = f"output/clips/scene_{scene['index']}.mp4" render_clip(video_path, srt_path, clip_path, cfg) clips.append(clip_path) with open("output/clips.txt", "w", encoding="utf-8") as f: for p in clips: f.write(f"file '{os.path.abspath(p)}'\n") return "output/final.mp4"渲染单个分镜时,scale和pad必须一起用。force_original_aspect_ratio=decrease让画面等比例缩放到目标分辨率以内,pad再把缩放后的画面居中放到黑底上。这两个滤镜缺一不可的原因在于:素材库里的视频必然有横屏有竖屏,不缩放直接拉伸会变形,只缩放不 pad 会导致输出分辨率达不到配置要求。
subtitles滤镜里传的是 srt 文件路径,路径里有特殊字符时需要用冒号转义或者换用filename参数,否则 FFmpeg 解析滤镜字符串会断掉。拼接时clips.txt里我写了绝对路径,因为 concat demuxer 对相对路径的解析依赖当前工作目录,而定时任务脚本经常在别的目录下被拉起,相对路径一错就拼接失败。
整个入口脚本跑完后,建议立刻检查output/final.mp4三件事:时长是否接近分镜 JSON 里duration_hint_sec的总和,字幕是否铺满关键片段,音频和画面起始点是否同步。这三项只要有一项异常,都说明上游某个环节的中间数据出了问题,此时看日志定位比瞎调参数高效得多。
5. 安装部署避坑指南:这五个高频翻车点最值得先看
把源码包部署到新机器上的那几小时,是踩坑密度最高的时候。下面五条是我在多个环境里反复遇到的高频问题,每一条都值得在动手前先看一遍。
5.1 现象:字幕变成方块,或者只有英文字母正常、中文全是□□
原因:系统里没有安装中文字体,或者dfs_font、force_style里指定的 FontName 和系统字体名不匹配。FFmpeg 的 subtitles 滤镜在找不到字体时会用默认字体代替,而默认字体通常不含中文字形。
解决:把 Noto Sans CJK 这类完整中文字体放进项目fonts/目录,并在配置里明确指定绝对路径。不要只验证“系统有宋体”就认为字体没问题,要验证 FFmpeg 进程能否读到。我习惯在部署后用一条极简命令渲染一张带中文字幕的测试图,确认字体链路通,再跑完整任务。
5.2 现象:成片有的片段被拉变形,有的分辨率不对
原因:素材源的分辨率和目标分辨率不一致,滤镜里只写了scale=1920:1080,没有配合force_original_aspect_ratio=decrease和pad。纯scale会粗暴拉伸画面,横屏素材在竖屏任务里会被横向压扁。
解决:统一用第 4.2 节那组scale + pad组合。核心思路是先等比缩小,再补黑边到目标分辨率,宁可留黑边也不要变形。这组滤镜参数在渲染行业里几乎是标准答案,没必要自己发明新写法。
5.3 现象:语音和字幕对不上,越到后面偏差越大
原因:字幕是用原始文案按字数均分时长生成的,没有考虑 TTS 语音的实际停顿;或者是 TTS 音频开头有静音段,而字幕时间轴从 0 开始算。
解决:字幕必须来自语音识别的时间戳,而不是文案本身。用第 4.1 节的转写思路拿到词级时间戳,配合vad_filter=True滤掉头尾静音。如果偏差是整体平移,在渲染时给字幕加一个–0.2 秒的偏移量即可,但如果是逐步漂移,就说明时间轴来源有问题,只能回源头修。
5.4 现象:批量任务跑到第 N 个视频时卡死,CPU 占用掉到接近 0
原因:很可能是显存或内存不足,进程被系统 OOM 杀掉但 Python 的异常没被正确处理,导致调用方一直等不到子进程返回。另一个常见原因是 TTS 服务接口超时,网络重试逻辑写成了无限等待。
解决:给所有 FFmpeg 和网络调用加上明确超时与重试次数。FFmpeg 子进程调用加timeout=600,超时就杀掉进程重试;API 调用用指数退避,最多重试 3 次,仍失败就把任务标记为失败并跳下一个,而不是卡住整条流水线。
5.5 现象:素材库里文件很多,但成片来来回回就那几个素材
原因:素材检索打分逻辑里没有加随机扰动,或者素材去重没做。同一批素材语义标签相近,打分结果完全相同,每次自然选同一个高分文件;更隐蔽的是服务器上存在同一视频的多个副本,入库脚本给它们打了不同标签,检索时被当作不同素材轮番选中。
解决:在打分公式里加入一个小的随机偏移:final_score = score + random.uniform(0, 0.1),让相近素材有概率被选中。入库脚本必须做感知哈希去重,同画面的视频文件只保留一份。这个去重环节能同时解决“素材重复率高”和“磁盘空间被垃圾副本吃满”两个问题。
6. 进阶用法:提示词模板与多 AI 协作怎么控住成片质量
当一条流水线能稳定产出成片后,下一个瓶颈一定是内容质量。批量跑出来的几十条片子里,总有几条文案逻辑不通、画面和台词对不上。我的处理方式是用提示词模板约束生成,再引入一个独立的“审片”模型做二次把关。
提示词模板的思路是把“类型 → 风格前缀”做成映射。比如美食类模板强制要求开头一句钩子、中间三个步骤、结尾一个反转;知识类模板强制要求“问题 + 反常识结论 + 证据 + 行动建议”。类别的数量控制在五到八个之间,太多会让大模型在分类边界上反复摇摆。
多 AI 协作是当前这类引擎提升质量的常见方案:模型 A 负责依据模板生成分镜 JSON,模型 B 以审片身份对成片评分,并输出需要修正的具体位置。这里的关键是审片模型的评分标准要可量化,画面与台词匹配度、开头三秒留存率预估、总时长是否在阈值内,每项打分后给出“通过”或“打回重改”的结论。循环最多跑三轮,超过三轮直接用最后一次结果,避免死循环。整个链路跑完后,我还会每天抽查三条成片,重点看素材重复率和字幕错字率,这两项指标是批量内容翻车的预警线。
我自己的运维习惯是,把所有任务参数、生成结果、审片分数写进一个独立的日志表,每周挑出高分数和低分数各看一遍,反推素材池和模板哪里需要调。时间长了你会发现,素材库质量对成片观感的影响,比大模型参数大得多。这条经验希望帮到你——把注意力放在数据和素材上,远比沉迷调 prompt 更划算。
本文还有配套的精品资源,点击获取