
简介面向短视频创作者、自媒体运营者及内容团队的全自动视频生产工具包只需输入一个主题或关键词即可自动完成视频文案生成、素材匹配、字幕生成、背景音乐选取与高清视频合成省去剪辑与配音环节同时可将音视频一键转换为小红书、公众号、知识笔记、思维导图、视频字幕等风格的文档适配多平台分发。压缩包共291个文件以98个py脚本为核心调度实现、42个md说明文档记录配置与使用流程、31个html页面提供不同风格的预览界面、30个json文件存放提示词与参数配置另附启动脚本、Dockerfile部署文件和少量图片音效素材整体仅8.35MB结构紧凑便于快速部署调试。目前已有71人学习下载。通过阅读源码和配置可掌握从文案策划到多平台输出的完整链路既能二次开发前端模板也可调整提示词与参数生成更具个人特色的内容非常适合希望搭建自动化内容生产流水线的运营者和开发者。1. AI全自动短视频引擎:不是剪辑软件,是一条生产流水线第一次跑通 AI 全自动短视频引擎有点难以置信——一条 40 秒带配音、字幕、转场的短视频从输入一个选题标题到成片落盘不到 3 分钟。这个 zip 包里装的不是传统剪辑软件的工程模板而是一条将「脚本 → 素材 → 配音 → 字幕 → 合成」串起来的自动化流水线。你喂一个关键词进去它会自己生脚本、配画面、配音、渲染成片真正需要做的是一次配置和一次试跑。适合做批量口播、带货素材和矩阵号的运营也适合想把 AI Agent 编排方式学走的工程师。接下来我会把它拆开讲清楚。2. 流水线三大模块脚本生成、素材匹配与合成渲染整个引擎的处理链路其实是老套的「中间产物递进」脚本是文本素材是媒体文件字幕是文本最终统一交给一个合成器。难点不在单个环节而在环节之间的接口约定。我拆过不少类似工程最容易出问题的往往不是模型能力而是上游产出的东西下游根本没法消费所以这一章不单讲每个模块做什么更讲它们之间怎么衔接。2.1 脚本生成大模型怎么把关键词扩写成口播脚本是整个流水线的「剧本」。这一环节的选型理由很直接——模板化脚本库早就被证明没有竞争力平台对同质化内容会压流量人工写文案又撑不起批量测选题。所以引擎在这个位置接了大模型接口输入一个选题关键词输出带开头钩子、中间陈述、结尾引导的口播稿。常见做法是维护一个系统提示词模板相当于把「编剧人格」固定下来# scripts/prompt_builder.py SYSTEM_PROMPT 你是一位短视频口播编剧。 根据用户提供的主题产出一段 30~60 秒的口播稿。 要求 1. 前 15 字必须是一个能留人的悬念或反常识结论 2. 正文给出 2~3 个信息点每个信息点不超过两句话 3. 结尾给一句行动引导不要出现“感谢观看”之类的客套话 4. 输出为纯文本不要 Markdown 标记。 def build_prompt(topic: str, tone: str 口语化) - dict: return { model: gpt-4o-mini, # 根据你手里的 API 渠道改 messages: [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: f主题{topic}\n语气{tone}}, ], temperature: 0.9, # 温度越高越“敢写”也越容易跑偏 max_tokens: 800, # 口播稿 300~500 字足够留一点余量 }逻辑说明我用一个字典来拼接口请求参数而不是在业务代码里散落字符串这样以后换模型、调参数只需要改这一处不会被到处复制粘贴的旧参数带偏。参数说明temperature 设为 0.9因为口播稿需要随机性不同选题之间的风格差异才拉得开如果做新闻稿或严谨类内容我会压到 0.3 以下。max_tokens 定到 800不是越大越好给模型的发挥空间过大反而容易出现前后矛盾的内容调整的重心应该放在 prompt 而不是 max_tokens。脚本生成完还有一个容易被忽略的输出字段——「关键画面提示」。它不参与口播但会传给素材匹配器比如「展示一摞现金」「背景是夜晚城市」。我拆到的版本里脚本是以 JSON 落盘的口播文本和画面提示分开存。这里埋了一个很深的坑如果脚本模型不稳定输出 JSON后续模块就会连锁失败所以 prompt 里必须写明类似「输出为纯文本」的硬约束。2.2 素材匹配本地素材库优先网络兜底反而是坑素材这一环是整个流水线里最容易翻车的地方。我见过不少项目先让引擎去网络抓素材结果版权、稳定性、审核全出事。合理的选型是「本地素材库优先 网络兜底」。原因很好理解本地库你能控横屏竖屏、控时长、控清晰度还能保证版权干净。所以引擎里通常先扫素材目录建索引再根据脚本里的画面提示去匹配。给你看一个本地素材索引的简化实现# modules/material_indexer.py import json import os from pathlib import Path from PIL import Image def index_material(library_path: str) - list: items [] for ext in (.mp4, .mov, .jpg, .png): for fp in Path(library_path).rglob(f*{ext}): size os.path.getsize(fp) if ext in (.jpg, .png): with Image.open(fp) as im: width, height im.size items.append({ path: str(fp), type: image, width: width, height: height, aspect: round(width / height, 2), duration: None, size_mb: round(size / 1024 / 1024, 2), }) else: items.append({ path: str(fp), type: video, aspect: None, duration: None, size_mb: round(size / 1024 / 1024, 2), }) with open(material_index.json, w, encodingutf-8) as f: json.dump(items, f, ensure_asciiFalse, indent2) return items逻辑说明先按扩展名遍历素材库图片直接用 PIL 读宽高比视频留了 ffprobe 的位置。宽高比是后面合成模块的关键输入横竖屏混用是成片最明显的硬伤。参数说明aspect 保留两位小数匹配时用这个字段做硬性筛选——目标视频是 9:16 竖屏素材就只允许宽高比 0.5~0.6 的进候选池。视频的 duration 需要用 ffprobe 补全因为剪辑模块要按秒切素材时长短于 2 秒的片段基本不可用。匹配逻辑本身我常用的策略是标签订阅而不是拿脚本整句做语义检索。素材入库时人工或自动打标签匹配时用画面提示命中标签。这么做不是因为它新而是批量生产场景下它稳定可解释。AI 语义检索很多时候匹配出来的画面和文案对不上审核素材的人会疯掉标签方案虽然糙但每一条都能说出「为什么选它」。2.3 合成渲染FFmpeg 一肩挑最后合成都绕不开 FFmpeg几乎没有替代方案。不是因为它是唯一选择而是生态成熟调音轨、画字、拼接、转场、导出全都能用一条命令说清楚。引擎的合成模块一般会把前面产出的中间文件拼成一条 ffmpeg 命令来执行ffmpeg -y \ -loop 1 -i bg.png \ # 背景图循环成视频流 -i voice.mp3 \ # 配音文件 -i subtitle.srt \ # 字幕 -filter_complex [0:v]scale1080:1920,crop1080:1920,fps30[bga]; [bga][2:v]overlay0:1600[vout]; [1:a]apadpad_dur0.5[aout] \ -map [vout] -map [aout] \ -t 40 -r 30 \ -c:v libx264 -preset medium -crf 23 \ -c:a aac -b:a 128k \ output.mp4逻辑说明背景图先由-loop 1变成静态视频流再统一缩放到 1080x1920字幕作为单独一条输入流通过 overlay 贴在画面下方音频用 apad 补了 0.5 秒空白避免语音结束得太过突兀。参数说明-crf 23是画质与体积的平衡点发短视频 23 足够想更清晰可以压到 18但文件体积会明显变大。-preset medium是编码速度档批量跑建议留 medium用 faster 会牺牲压缩率。音频码率 128k 是口播场景的标准值歌曲类素材才需要提到 192k。合成这一步输出的成片不是终点。引擎一般还会跑一次「回检」用 ffprobe 检查成片时长、分辨率、音轨是否存在这是防止批量跑出 100 条坏片的关键习惯ffprobe -v error -show_entries formatduration:streamcodec_name,width,height \ -of defaultnoprint_wrappers1 output.mp4逻辑说明这条命令读出来的四个值引擎会拿去和预期参数对比任何一个对不上就重新合成而不是把坏片直接交付。参数说明-v error表示只在出错时输出避免刷屏-show_entries限定只取时长和编码信息-of defaultnoprint_wrappers1去掉格式外层包装方便后续脚本按行解析。3. 本地复现解压、装依赖、配密钥、跑通第一条成片这一章把环境搭起来让 zip 里的代码真正在你机器上转起来。先说结论只要 Python 和 FFmpeg 是干净的半小时以内能跑通。如果你解压后的入口文件不叫main.py以项目里的 README 为准核心配置项大差不差。3.1 解压与依赖安装先确认压缩包没解丢东西项目压缩包拿到手第一件事不是急着重命名而是看压缩包完整性。源码包常有带中文名的素材目录和长路径文件解压工具处理不当会丢文件。我一般这样操作unzip -l AI_ShortVideo_Engine.zip | head -50 # 先看清单 unzip -q AI_ShortVideo_Engine.zip -d ./AI_ShortVideo_Engine cd AI_ShortVideo_Engine ls -la逻辑说明先列清单确认包内有 README、配置文件、入口脚本再解压。-q是安静模式防止大量小文件刷屏。参数说明-l只列出清单不解压适合先确认结构和是否存在空目录-d指定解压目标目录避免文件散落当前目录。如果在 Windows 用系统自带右键解压出现中文乱码换成 7-Zip 或 Bandizip按 UTF-8 编码解压即可这是 zip 包场景里的老问题。依赖安装是另一个常见翻车点。项目一般带requirements.txt但裸装容易和系统里现有包冲突我习惯新建虚拟环境python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install -r requirements.txt ffmpeg -version逻辑说明venv 把项目依赖和系统 Python 隔离避免以后装别的包把引擎的依赖顶掉。ffmpeg -version 这条出门检查能省掉后面所有合成报错的排查时间。参数说明如果requirements.txt里某个版本装不上先看 pip 报错。找不到版本大概率是 Python 版本不匹配比如项目要 Python 3.9你用的是 3.12那就换解释器而不是强行改版本号。3.2 配置文件里的关键项路径、密钥、模型名跑通之前先把配置文件读一遍。引擎一般会用config.yaml或.env收拢参数而不是让人在代码里到处改。核心配置项就三类文件路径、API 密钥、模型名。# config.yaml engine: working_dir: ./work # 中间产物目录跑批前清空一次 output_dir: ./output # 成片输出目录 length_seconds: 40 # 目标成片时长秒 llm: provider: openai-compatible # 兼容 OpenAI 协议的都可以 api_key: ${OPENAI_API_KEY} # 从环境变量读不要写死 model: gpt-4o-mini temperature: 0.9 tts: provider: edge-tts voice: zh-CN-XiaoxiaoNeural # 中文女声语速适中 material: library_path: ./material_library allow_network_fallback: false # 网络兜底默认关掉 min_duration_sec: 2.0逻辑说明api_key写${OPENAI_API_KEY}是让引擎从环境变量读取而不是硬编码在 yaml 里。配置文件会被 git 提交、会被同事拷贝密钥一旦进去就能从任何环节泄露出去。参数说明allow_network_fallback默认关掉这是版权和稳定性的双保险。min_duration_sec: 2.0是素材过滤条件短于两秒的片段切进成片只会造成画面跳动。提示环境变量在 Linux/macOS 用export OPENAI_API_KEYxxxWindows 用set OPENAI_API_KEYxxx不要写进 config.yaml。3.3 单条试跑一次把链路问题全暴露出来配置完成后第一次跑批不要直接上 100 条先跑一条。这一步是为了把「脚本接口」「素材匹配」「合成渲染」三个模块的联调错误一次性暴露出来。python main.py --topic 为什么你的存款利率一降再降 --output ./output/test_001.mp4逻辑说明脚本生成正常工作目录会出现script.json素材匹配成功会出现shotlist.json合成完成会输出test_001.mp4。三个文件都在链路就是通的。参数说明--topic是必填选题文本--output指定成片路径路径不存在时引擎会自动创建。故意只跑一条是为了让任何报错能直接定位到模块。我的判断顺序是先看script.json是否合法 JSON再看shotlist.json里的素材路径是否有效最后看test_001.mp4能否被 ffprobe 正常解析。如果中途失败不要反复重跑打开logs/engine.log找到第一个报错模块日志里记录着每个环节的耗时和错误上下文。4. 参数调优时长、配音、字幕与素材匹配策略跑通只解决「能跑」接下来的问题才是运营关心的生成的东西能不能发出去完播率能不能扛住。这一章的参数调整要拿真实数据说话不要凭感觉。4.1 时长、配音和字幕三个影响完播率的参数短视频数据的核心矛盾是完播率 vs 信息量。时长越长完播率必然越差。我在批量生产场景下的经验值是口播 25~40 秒最稳妥超过 60 秒的选题除非极其硬核否则基本被划走。参数推荐值说明成片时长30~40s口播完播率最好的区间信息密度低就往下压语速1.0~1.1x1.0 自然语速1.1 微紧凑不推荐超 1.2字幕字号竖屏的 5%~8% 宽字号太大挤压画面太小手机看不清字幕底边距15% 高避开平台底部交互区配音这一项最容易出现「机器味」。edge-tts 这类合成引擎在 1.0 语速下句与句之间的停顿偏生硬。我一般做两步语速调到 1.05再让脚本生成时在关键信息句前自然使用破折号或「注意」这类强调词停顿感会弱很多。字幕这关还有一个隐藏的坑字体。FFmpeg 绘制字幕依赖系统字体库Windows 里的中文字体名和 Linux 完全不同。常见做法是先fc-list :langzh查系统中文字体然后在 filter 里显式指定字体文件而不是写「SimHei」这类字体名。这一步不处理好字幕渲染出来就是方框和你素材画质多好没关系。4.2 脚本风格与素材匹配策略不同内容类型用不同权重口播、种草、资讯三种内容脚本模块和素材模块的权重完全不一样。引擎里有一个content_type字段它会同时改变 prompt 和素材匹配的行为。口播型脚本权重高素材只需要两三个空镜千万别做「素材逐句同步」。种草型素材权重高脚本反而要短重点看产品细节的画面匹配度。资讯型两者都要压缩脚本给结论素材给数据截图。实现层面我的做法是在config.yaml里加一组strategy_weightscontent_type: 口播 strategy_weights: script_creativity: 0.7 # 口播类脚本创意权重高 material_relevance: 0.4 # 素材只需不出戏 subtitle_prominence: 0.9 # 字幕突出口播依赖字幕补充信息这组权重落到代码里素材模块的打分函数大致长这样def rank_materials(shotlist, material_index, weights, target_aspect, top_k3): scored [] for m in material_index: if m[aspect] and abs(m[aspect] - target_aspect) 0.1: continue relevance sum(weights.get(k, 0) * shotlist.get(k, 0) for k in weights) scored.append((relevance, m)) scored.sort(reverseTrue) return [m for _, m in scored[:top_k]]逻辑说明硬性筛选在前宽高比不匹配的直接淘汰然后按权重点乘打分排序取前 top_k 个候选素材。参数说明target_aspect来自引擎输出设置比如竖屏是 0.56硬性过滤阈值 0.1 是我试出来比较舒服的值太严会筛掉可用素材太松会把横屏素材混进来。top_k3表示每条视频只保留三个候选减少合成阶段的渲染时间。这样同一个引擎主体不用改只调配置就能切内容赛道。4.3 人工介入点让引擎停在半路改完再继续全自动不是非得一口气跑到底。我自己的使用习惯是保留三个介入点脚本生成后改文案素材挑选结束、未合成前检查版权成片回检后做人工质检。在工程上这对应引擎的「指定断点」命令行参数python main.py --topic 理财新规 --pause-at shotlist --resume-from shotlist --replace-shot 123.mp4逻辑说明--pause-at shotlist让引擎在合成前停下--resume-from shotlist表示从 shotlist 断点继续--replace-shot手工替换某段素材。这个参数组合就是为了「机器批量干活人只处理敏感点」而不是把人塞进流水线里当一节电池。5. 避坑指南路径、同步、乱码与限流问题排查这一章是血泪账。把我在复现和生产里遇见过的高频问题按「现象 → 原因 → 解决」写出来你在自己机器上遇到同款时能少走弯路。5.1 现象一运行就报模块找不到、解压后目录不全现象python main.py一执行就ModuleNotFoundError或者提示找不到config.yaml。原因八成是解压工具丢了文件或者没有按 README 要求的目录结构放置。部分解压工具对中文文件名和超长路径处理有截断问题导致包内模块没被完整落地。解决先ls -la确认config.yaml和main.py在同一级。再用python -m pip install -r requirements.txt重装依赖。如果 Windows 下中文文件名乱码用 7-Zip 按 UTF-8 重新解压。路径里也不要出现中文FFmpeg 对路径编码的兼容性一言难尽。5.2 现象二成片音画不同步语音对不上画面现象生成出来的视频里口播声音和画面切换明显错位成片超过 40 秒时尤其严重。原因素材拼接时用了-loop和-t的循环机制音频流没有准确对齐。常见于把不同帧率素材混剪或者音频在拼接时被apad填充后没有重新计算时长。解决在合成命令里把视频和音频统一映射到一个时间基准在-filter_complex里加settb固定时间基。更省事的方案是保证所有素材导入前转成同一帧率。我在命令里会强制加-r 30和音频aresample44100这样原始素材再乱成片也能稳定。5.3 现象三开网络兜底后素材不是版权存疑就是画质差现象把allow_network_fallback打开后成片里出现带水印、模糊、或者闪变画面的片段。原因网络素材站点没有统一质量约束缩略图和低码率流都混在里面而且很多站点本身不可商用。解决在没有可靠授权素材库之前网络兜底直接在配置里关掉。本地素材不够用就补充正版素材包或自己拍摄。宁可少出几条片也不要在版权上留隐患。5.4 现象四字幕乱码现象成片字幕出现「口口口」或「」等异常字符部分中文字显示为方框。原因字幕文件编码与 FFmpeg 读取编码不一致。srt 文件常见 UTF-8 无 BOM 和带 BOM 两种状态FFmpeg 在部分环境下默认按本地编码读取导致中文乱码。解决在合成前强制转字幕编码。我的固定做法是生成 srt 时明确写encodingutf-8如果 FFmpeg 读取还有问题在字幕输入路径后加-sub_charenc utf-8显式指定。如果字幕含破折号等特殊标点检查 srt 时间轴和正文之间是否有异常换行。5.5 现象五批量跑一半被 API 限流现象前面 30 条正常后面越来越慢最后直接报 429 或超时整批任务中断。原因批量场景下请求并发太高触发了大模型接口限流。这种间歇性失败最玄学很多人会怀疑是素材问题其实大概率是并发频率撞线。解决在脚本生成循环里加指数退避重试并控制并发数。我的配置是max_retries5、backoff_factor2也就是第一次失败等 2 秒第二次 4 秒直到 32 秒封顶。批量任务按 20 条一组分片每组之间间隔 60 秒。还有一个容易被忽略的磁盘空间。100 条 1080x1920 成片加中间产物轻松超过 20GB跑批前df -h看一眼空间不足时 FFmpeg 会静默产出损坏文件那个排查成本比限流还高。6. 进阶用法批量选题、人工质检与日志留痕到此为止单条流水线已经跑通剩下的是把它变成日常工具的小技巧。6.1 批量喂选题一行 txt 顶 20 条命令运营每次开会要测 20 个选题手动一个个敲确实浪费时间。我的习惯是把选题维护在topics.txt里一行一个关键词while read topic; do python main.py --topic $topic --output ./output/${topic}.mp4 --quiet done topics.txt逻辑说明循环逐行读入选题每条跑一次引擎--quiet只在报错时打印日志批量跑不会把终端刷爆。参数说明${topic}直接拼到输出文件名如果选题里带空格或斜杠建议先做清洗再拼路径。实际跑的时候我会加一个计数器每 10 条强制 sleep 60 秒把 API 限流概率直接压到零。6.2 人工质检用 ffprobe 把坏片挑出来批量跑完不要急着传。写一个极简质检脚本把音轨缺失、时长不符的坏片改名标出# qc.py import subprocess, os for f in os.listdir(output): if not f.endswith(.mp4): continue p os.path.join(output, f) probe subprocess.run( [ffprobe, -v, error, -show_entries, formatduration:streamcodec_type, -of, csvp0, p], capture_outputTrue, textTrue) rows [line for line in probe.stdout.strip().splitlines() if line] has_audio any(line.startswith(audio) for line in rows) has_video any(line.startswith(video) for line in rows) duration rows[0].split(,)[0] if rows else 0 if not (has_audio and has_video) or float(duration) 20: os.rename(p, p.replace(.mp4, _BAD.mp4))逻辑说明循环遍历输出目录用 ffprobe 提取每个文件的时长和流类型判断是否同时有音轨和视频轨时长是否过短不合格文件改名标记。参数说明-show_entries限定只输出时长和流类型避免全量输出拖慢批量处理-of csvp0让结果变成清爽的 CSV 行Python 按行取第一个字段就是时长跑 100 条文件时差异很明显。6.3 日志留痕跑批不记日志等于白跑如果只留一个习惯我留日志。批量跑 50 条第 17 条 API 超时、第 33 条素材匹配为空没有日志根本没法定位。我每次跑批都生成带时间戳的日志文件python main.py --topic 存量房贷 --output out.mp4 21 | tee logs/run_$(date %Y%m%d_%H%M).log逻辑说明21把标准错误合并到标准输出tee同时写入终端和日志文件跑完随时可以回看。这个习惯成本极低但能让你三天后复查「当时到底配了什么参数」时不靠记忆。从那以后我每次跑批不管是 10 条还是 100 条都强制走一遍「解压 → 依赖 → 单条 → 批量 → 日志 质检」的顺序这个流程帮我挡掉过至少五次批量翻车。希望帮到你。本文还有配套的精品资源点击获取