
把产品宣传片交给代码来生成这个想法我惦记了快半年。去年做独立产品时预算紧张找外包报价最低也要四五千用模板站改来改去又总差口气。后来发现 AI Agent 兴起之后不少人开始把“生成宣传片”这件事拆成一条流水线只要搭好一个可复用的 Skill丢给 AI 一个产品信息它就能自动产出文案、配音、画面和成片。我干脆把这个整套方案整理成开源项目放了出来代码全部公开本地跑通后每部宣传片的成本几乎可以忽略。这篇文章就完整记录一下这个 Skill 的设计思路、核心实现和实操全流程包括我踩过的坑和排查经验。不管你是独立开发者、小团队负责人还是只对 AI 自动化工作流感兴趣这应该都是一份能直接抄作业的参考。1. 为什么选择用代码生成宣传片1.1 传统方案的成本痛点先算一笔最常见的账。找外包机构拍一条 30 秒的产品宣传片通常要经历脚本策划、分镜绘制、配音、动画包装、后期剪辑几个环节。一线城市报价一般是文案加配音三到五千加上动画包装基本就过万交付周期还常常拖到两周起步。如果是用 Canva 这类模板站自己拼虽然能省下外包费但默认模板的素材库有限产品调性和画面很难统一改来改去永远是“差不多但不够好”的感觉。还有一条隐藏成本就是改版成本。产品宣传片最怕的不是第一次制作而是三个月后产品迭代主功能变了宣传片就得推翻重来。外包团队未必还有档期模板站改起来也要重新核对所有文字、画面和配音时间和沟通成本全堆在内容更新上。1.2 代码方案的核心优势用代码生成宣传片本质上是把“制作过程”变成“可复用的构建流程”。适合做成流水线的环节全部自动化比如文案生成、配音合成、画面拼接、字幕压制、背景乐混音。这一套只要搭好每次新产品要出宣传片只需要更新产品信息配置脚本会重新拉取一遍内容跑完就是一条新成片。另外一个容易被忽略的优势是它天然适合版本管理。你完全可以把“昨天的宣传片 v1.0”和“今天的宣传片 v2.0”看成两个代码版本用 Git 追踪每次改动的 diff。产品经理说“把这段导语换成更简洁的说法”直接在配置里改一行字重跑管线几十秒后拿到新版成片这个效率绝对碾压外包协作。1.3 适合什么样的人和场景这套方案最匹配三类场景。第一类是产品快速迭代的团队尤其是 SaaS、App、开发工具这类需要频繁跟随功能更新而出宣传素材的项目。第二类是独立开发者和微型团队预算有限但需要一批基础宣传素材铺到官网、社交媒体和产品介绍页。第三类是 AI 工作流爱好者想研究 Agent、Skill、自动化脚本如何结合音视频处理的玩家。当然它也不是万能的。需要实拍、演员、复杂运镜的真实感宣传片代码方案做不了。但是 90% 的“介绍型宣传片”“功能亮点展示片”“产品背景故事片”完全可以用自动化管线生成而且效果能达到中等偏上的水准。2. Skill 是什么把“想法”变成“流水线”2.1 从 Skill 的流行说起最近这个 Skill 概念在开源社区非常火你搜一下相关热词就能看到一堆 agent 型 Skill 项目。它本质上是一个“技能包”由提示词模板、可执行脚本、配置文件、工具接口说明组成打包在一起后可以让 AI Agent 或本地脚本直接调用。更直观的理解是传统 AI 对话时你每次都要把需求说一遍比如请帮我写文案、请把文案拆成分镜、请生成配图描述但这些指令是零散的。Skill 就是把全套指令、参数、执行逻辑固定成一套标准协议。以后你只需要说一句话“用这个 Skill 帮我生成某产品宣传片”AI 就知道该按什么顺序调用哪些工具、传入哪些参数、产出什么格式的结果。2.2 Skill 的结构设计我开源的这个宣传片 Skill目录结构是这样的promo-skill/ ├── skill.md ├── config.yaml ├── scripts/ │ ├── generate_script.py │ ├── text_to_speech.py │ ├── generate_images.py │ └── compose_video.py ├── prompts/ │ ├── copywriter.md │ ├── storyboard.md │ ├── image_prompt.md │ ├── voice_settings.md │ └── background_music.md └── output/每个文件的职责都很清晰。skill.md 是技能说明描述这个 Skill 能做什么、需要哪些外部依赖、工具调用顺序config.yaml 保存核心参数例如输出分辨率、配音音色、背景乐风格、字幕格式scripts 目录里是具体执行脚本prompts 目录里是面向 LLM 的提示词模板output 目录存放生成结果。这种结构化拆分带来的好处是任何一个环节要替换方案只需要改对应的一个模块。比如你不想用默认的配音引擎只改 text_to_speech.py 的调用接口其他环节完全不动。2.3 Skill 的最佳运行方式这个 Skill 可以有两种运行模式。第一种是纯命令行直接执行一条 pipeline 脚本适合完全自动化的场景第二种是嵌入 AI Agent让 Agent 根据用户描述自动决定怎么调用比如豆包、Codex 这类平台都支持导入外部 Skill。我实际操作下来推荐大家在本地先把纯命令行模式跑通再去接入 Agent。因为命令行模式更容易追踪每一步的输入输出一旦出错可以直接看到日志排查效率高很多。接入 Agent 以后参数传错时定位成本会高不少新手容易一头雾水。3. 核心细节与管线设计3.1 整条流水线到底分几步宣传片生成的完整管线我拆成了七个节点产品信息解析、宣传文案生成、分镜脚本生成、配音合成、画面素材生成、视频合成、后期压制与封装。产品信息解析是最容易被忽略但最关键的环节。这里要维护一个结构化的产品信息文件比如产品名称、一句简介、核心功能列表、目标用户、差异化亮点。这个文件的质量直接决定后续文案和画面的上限。我调研过一些开源项目很多生成的宣传片看起来“很通用”就是因为这一步只给了 AI 一个模糊的产品描述没有结构化数据。宣传文案生成负责产出整片旁白文案一般控制在两条到三条短视频的体量每条 30 秒左右。分镜脚本生成要把文案拆解成一个个镜头单位标注每个镜头的时长、配图提示词、字幕文本。配音环节把旁白转成音频画面素材生成则根据分镜里的图像提示词产出静态图或动态背景视频合成环节将画面、配音、字幕、背景乐按时间线拼接最后做统一压制。3.2 镜头拆分的核心逻辑镜头拆分是整个管线里最有技术含量的一步。拆分方案决定了宣传片的节奏感也决定了后续配音、配图、合成环节能否顺利对齐。我的做法是按句子拆分。先让 LLM 把旁白文案按语法边界拆成短句每句对应一个镜头时长然后估算每个镜头的预计时长。一个关键参数是语速中文旁白正常语速大约是每分钟 240 到 260 字所以每句字数除以语速就能得到该镜头的基础时长。考虑到用户观看习惯每个镜头时长要控制在 2 到 5 秒之间太短会让人觉得一闪而过太长又会拖节奏。具体的计算逻辑是单镜头时长 句子字数 / 语速 缓冲时间。缓冲时间一般加 0.5 到 1 秒防止画面切换太频繁。整个分镜输出用 JSON 格式保存每个镜头包含 index、text、duration、image_prompt、transition 五个字段。transition 字段控制镜头切换方式比如淡入淡出、滑动、缩放不同的转场效果会让成片观感大不一样。3.3 画面提示词与视频参数的匹配画面提示词的质量决定了宣传片“看起来专业”与否。我这里给了 LLM 一套固定的模板要求每个镜头提示词必须包含主体、场景、光线、风格、构图、画面比例六个要素。例如画面比例必须与视频分辨率匹配。如果我配置的是 16:9 的 1920x1080那提示词里必须写明 wide shot 或 landscape composition否则生成的图像容易被裁剪。背景风格我会统一指定为“干净简洁的科技感 3D 渲染风格”这样 20 个镜头生成出来虽然有差异但在视觉上仍然是一个统一的系列。还有一个容易被忽视的是字间距和留白。宣传片要叠加字幕配图里就不能让主体元素占满整幅画面否则字幕一压就挡住了核心内容。我通常会在提示词里加一条 bottom safe area reserved让中下部区域尽量留白。这个细节看起来很小但实际成片效果差距非常明显。3.4 配音与字幕的同步机制配音环节我采用了分段合成方案每条分镜单独生成对应句子的音频文件而不是一次性合成整段旁白。这样做的好处是每个音频文件的时长可以直接与分镜 duration 对齐字幕压制时每一句字幕的起始时间就是对应镜头的起始时间天然不会错位。如果一次性合成整段音频虽然配音语气更连贯但后续做逐句字幕时需要依赖语音识别做时间戳对齐不但多一道工序识别误差还会导致字幕和旁白不同步。分镜级合成虽然可能在句间停顿上稍有生硬但在宣传片这种短句密集的场景里观感几乎不受影响。想优化停顿感可以在每句音频之间加 300 到 500 毫秒的静音缓冲转场时听起来就自然多了。4. 实操过程从零搭建一个宣传片生成 Skill4.1 环境准备先把基础环境搭好。操作系统 Linux、macOS 均可Windows 也可以但要格外注意 ffmpeg 的路径问题。Python 版本建议 3.10 以上方便用上较新的类型注解和异步特性。需要安装的依赖比较少openai 或其他 LLM SDK、edge-tts 或其他 TTS 库、Pillow 或 OpenCV 做图像处理、ffmpeg 做视频合成。这里有个小提醒edge-tts 是微软 Edge 浏览器的在线语音合成接口的封装库可以免费使用不需要注册 API Key很适合做本地快速验证。不过它依赖网络离线环境会失败。如果需要完全离线可以替换成 piper 这类本地 TTS 模型但音色丰富度会略差。我建议把 ffmpeg 装成系统级命令并检查一下是否能正常执行。ffmpeg 是视频合成的主力工具整个管线的最后一步完全依赖它版本太旧会导致某些滤镜参数不生效。4.2 Skill 目录与配置文件创建项目根目录比如叫 promo-skill然后按前面提到的结构把子目录建出来。config.yaml 里我放了这样一组参数product: name: 示例产品 tagline: 让协作更简单 features: - 实时协作 - 跨平台同步 - 数据安全 video: width: 1920 height: 1080 fps: 30 total_duration: 30 transition: fade voice: engine: edge-tts language: zh-CN rate: 0% pitch: 0Hz style: image_style: clean tech 3D render safe_area: bottom safe area reserved output: format: mp4 crf: 18product 节点是给 LLM 用的核心上下文video 节点控制输出规格voice 节点设定配音参数style 节点控制画面风格output 节点指定最终编码参数。CRF 18 是 x264 编码里画质很高的数值体积可能偏大但宣传片一般不长完全值得为画质多占一点空间。4.3 skill.md 的编写要点skill.md 是这个 Skill 的门面也是 Agent 接入时读取的说明书。我写的核心内容是这样的结构# 产品宣传片生成 Skill ## 功能 根据产品信息自动生成完整宣传片输出 MP4 文件。 ## 输入 config.yaml 中的 product 节点内容。 ## 处理流程 1. 读取产品信息 2. 生成宣传文案 3. 拆分为分镜 JSON 4. 逐镜配音 5. 逐镜生成配图 6. 拼接视频、添加字幕与背景乐 7. 输出最终 MP4 ## 依赖 - Python 3.10 - ffmpeg - edge-tts 或本地 TTS ## 调用方式 python scripts/generate_script.py python scripts/text_to_speech.py python scripts/generate_images.py python scripts/compose_video.py注意一个细节调用方式里我列的是四步命令但实际上中间会有配置文件传递。generate_script.py 会生成一份 product_script.jsontext_to_speech.py 读取这份 JSON 产出音频文件generate_images.py 读取分镜里的 image_prompt 生成配图compose_video.py 最后把所有素材汇总合成。如果接入 Agentskill.md 里的“调用方式”部分就是 Agent 的工具调用说明书它会根据这段文字知道什么情况下执行哪个脚本。所以写这段时一定不要含糊要把每一步的输入输出讲清楚。4.4 核心脚本实现精讲宣传文案生成脚本是整个 Skill 的起点。我采用的是两阶段生成策略。第一阶段让 LLM 根据产品信息写一版完整旁白文案要求字数限制在 90 到 110 字。这个字数是按 30 秒、语速 240 字每分钟算出来的留了一点余量给停顿。第二阶段是把文案交给 LLM 做分镜拆分输出 JSON。这里提示词里要特别强调两个约束一是每句字数控制在 10 到 20 字方便观众在短时间读完字幕二是每句语义完整不能把一个完整意思切断到两个镜头里。我用过一次自动断句结果把“跨平台同步”拆成了“跨平台”和“同步”画面和字幕都对不上非常别扭。配音脚本相对简单。edge-tts 的调用方式大致如下import asyncio import edge_tts async def synth(text, output_path): tts edge_tts.Communicate(text, voicezh-CN-XiaoxiaoNeural) await tts.save(output_path)逐镜合成时我会把分镜 JSON 里的每个 text 字段取出生成 clip_001.mp3 到 clip_0xx.mp3统一存放在 output/audio 目录。这里建议给每个文件名加上零填充的三位数字编号后面合成阶段排序时就方便了。画面生成脚本要看用的图像方案。如果你本地有 GPU可以考虑开源的稳定扩散模型通过 diffusers 库加载。没有 GPU 就调用云端图像生成 API返回的图片保存到 output/images。不出意外的坑在图像比例。API 默认生成的图可能是 1:1 正方形和宣传片 16:9 的画幅完全不匹配。所以我每次调用时都会显式传一个 width 和 height或者在提示词里强制写 wide aspect ratio。如果模型不支持横图那就只能先导出成图再中心裁剪但这样做会损失构图信息我不太推荐。视频合成脚本是整个管线的重心。我用 ffmpeg 命令完成多段画面拼接、配音混入、字幕渲染、背景乐混音四件事。画面拼接的核心是一张图片对应一个镜头每个镜头持续 duration 秒。命令形如ffmpeg -y -loop 1 -t {duration} -i clip_001.png -loop 1 -t {duration} -i clip_002.png -filter_complex concat out.mp4但实际操作中我更喜欢用 concat demuxer先写一个 filelist.txt把所有镜头文件的路径和持续时间列出来再让 ffmpeg 一次性读取并拼接。这样脚本逻辑更清晰也方便在运行时动态生成镜头列表。字幕渲染用的是 ffmpeg 的 subtitles 滤镜。每个镜头的字幕文本已经存在分镜 JSON 里了我写脚本生成一个 SRT 格式文件每句字幕的起止时间与该镜头时间轴对齐然后让滤镜直接渲染到画面上。这种方式比在画面上直接叠文本更灵活因为 SRT 天然支持时间轴而且导出后还能单独做翻译版本。背景乐混音需要额外准备一首无版权音乐放在 assets/background_music.mp3。合成时用 amix 滤镜将背景乐与配音混合同时通过 volume 参数控制背景乐音量一般压到 0.15 到 0.2 之间避免盖住旁白。4.5 跑通一次完整流程我把整个流程统进了一个 shell 脚本方便一条命令执行全部阶段。实际跑通前的准备只需要在 config.yaml 里填好产品信息和视频参数然后依次执行 generate_script.py、text_to_speech.py、generate_images.py、compose_video.py。我第一次跑通时最兴奋的是看到 output/final.mp4 生成出来打开播放时画面、配音、字幕竟然全部对齐。那期产品是一个任务管理小工具宣传片里 20 个镜头每个镜头 1.5 到 2 秒有功能展示画面有应用场景画面最后统一以产品 Logo 收尾。背景乐是电子风格节奏感跟旁白的短句很搭。当然第一次跑通时问题也不少比如有几张图明显走样一个“数据安全”的场景把盾牌元素画得让人看不懂还有一处字幕时间轴偏了大概 0.4 秒。这些都是后面要专门解决的问题。5. 常见问题与排查技巧实录5.1 高频异常速查表在使用过程中我汇总了最常遇到的五类问题这里整理成一张速查表方便大家按图索骥问题现象可能原因快速排查方法字幕与配音不同步音频缓冲时间与镜头时长不一致检查最近一次生成的 SRT 时间和分镜 JSON 的 duration 字段某张配图比例异常图像 API 未指定宽高比检查 generate_images.py 是否传了 width 和 height 参数拼接视频卡顿、掉帧ffmpeg 版本过旧或编码参数不当升级 ffmpeg检查 fps 参数是否与源图一致配音音色突兀TTS 引擎与旁白风格不匹配切换音色或调整 pitch、rate 参数背景乐音量盖过旁白混音时 volume 参数过高把背景乐音量降到 0.15 以下再试最关键的一点是问题定位必须先看中间产物。比如字幕不同步先检查 output/audio 里每个音频文件的时长再对比 SRT 里对应字幕的时间戳很快就能找出是配音环节还是字幕生成环节出了问题。5.2 配图走样反复生成不如约束提示词配图走样是我遇到最多的问题。比如要求“数据安全”主题模型可能画出锁、盾牌、数据流矩阵但如果产品是软件界面光有“锁”这个概念是不够的观众看了也想不到你的产品。后来我把 image_prompt 生成模板改成了这样主体必须是“产品界面在设备上的展示”场景必须是“办公或移动场景”风格统一为“简洁 3D 渲染浅色背景”再加上“底部安全区域留白”这条固定后缀。改完之后生成的图虽然不如纯创意海报惊艳但至少每张图都和产品相关成片整体协调性大幅提升。这里有一个经验宣传片配图追求的不是“单张惊艳”而是“整体一致”。单张图再好看风格跳跃太大观众会觉得是拼凑素材。所以宁可让所有画面都走同一种稳妥风格也不要让模型放飞自我。5.3 AI 输出不稳定用“结构化约束”代替“自由发挥”LLM 在生成文案和分镜时偶尔会出现格式不稳定的问题。比如要求输出 JSON它夹带了一些解释文字导致脚本解析失败。我的处理方式是两层保险。第一层在提示词里反复强调“只输出 JSON不要任何解释和 Markdown 代码块标记”第二层在脚本里写一个容错解析函数先尝试 json.loads失败就用正则把最外层的 JSON 花括号部分抓出来再解析。如果正则也失败就重新让 LLM 生成一次最多重试两次。重试逻辑也很重要。每次重试时在提示词末尾加一句“上次输出格式不符合要求请只返回合法 JSON”这种方法比直接重置上下文效果好得多。5.4 音视频时长的精准对齐技巧宣传片最怕的就是音画不同步。除了前面讲的分镜级合成之外还有一个容易被忽略的细节就是配音音频的实际时长可能和预估时长不同。edge-tts 实际合成出来每句话的音频时长往往比“字数除以语速”的估算值长一点。所以我在合成脚本里加了一步校验音频生成完成后用 ffprobe 读取每个文件的真实时长再用真实时长回写分镜 JSON 的 duration 字段。这样视频拼接和字幕时间轴都基于真实音频时长同步问题从根本上得到解决。具体命令是ffprobe -v error -show_entries formatduration -of csvp0 clip_001.mp3脚本里可以调用 subprocess 拿到这个数值四舍五入保留两位小数写回该镜头的 duration。这一步我实测下来是消除不同步问题的关键。5.5 节省成本与算力的几个招如果是接入云端图像生成 API每一次调用都是钱。为了节省成本可以先把所有分镜的 image_prompt 一次性批量发送有些平台支持 image batch 模式费用比单张逐次调用低。生成图片前也可以把分辨率降到 1024x1024 再放大视觉上差异不大费用差距却可能翻倍。本地跑 Stable Diffusion 的话可以考虑用 LCM-LoRA 这类加速采样方案能把单张图的生成时间从十几秒压到三四秒。宣传片总共 20 个镜头原本要等十几分钟加速后五分钟内就能全部出图。写在最后的个人体会折腾这个 Skill 的过程中我最深的感受是低成本的本质不是“免费用免费工具”而是“把制造过程变成可复用的构建流程”。当你能用代码把文案、配音、配图、合成全部串起来时每一部新宣传片都只是配置文件的更新和一次脚本执行。最后再分享一个小技巧。如果你想让宣传片开头更有记忆点可以在第一个镜头的提示词里加入产品 Logo 和“开场定格画面”的描述再把第一个镜头的 duration 调整为 3 秒以上。这个细节在社群发布时尤其有用前几秒抓不住用户后面内容再好也容易划走。我后来做每一支片都留了这样一个钩子实测完播率明显更高。