自从我把这条“每日技术新闻视频”流水线搭完,每天早上到工位的第一件事,变成了打开日志看一眼昨晚的视频有没有跑挂。再次之前,这件事是我一天里最不想干但又必须干的活儿。
先说结论:我用蓝耘元生代做AI文案生成和配音合成,用 Remotion 做视频渲染编排,写了一条命令,现在每天自动产出1条技术新闻短视频。整个过程从采集新闻、生成口播稿、文字转语音,到渲染字幕、合成背景、导出成片,全部自动化。我只需要在偶尔跑挂的时候修一下脚本。
这篇文章我会把整个设计思路、工具选型、关键代码、踩坑记录全部拆开讲,希望能给同样想做“内容自动化生产”的朋友一些可以抄作业的参考。
1. 先说我为什么决定“给AI打工”
1.1 传统手工制作技术新闻视频的低效循环
我最初做技术新闻视频的方式,和大多数内容创作者没什么区别:早上刷十几二十个技术网站、公众号、论坛,挑选当天值得讲的新闻,手动整理成文字稿,然后录音、剪辑、配字幕、做封面、调时间轴。一条3分钟的视频,顺利的话也要两个小时起步,如果中途发现某条新闻理解错了或者素材不够,重头再来,一上午就没了。
坚持了一个月之后,我意识到一个核心问题:这条流程里,我的时间全部花在“重复劳动”上,而不是花在“内容和观点”上。素材永远是那些新闻源,视频结构永远是“标题+正文+字幕+背景”,导出永远是一样的参数。真正需要我判断的,其实只有“哪些新闻值得讲”和“怎么把逻辑讲通”,而这些恰恰被大量重复的体力活淹没了。
于是我给自己定了一个目标:把这条生产线交给机器,我只需要在机器的产出里做最后一道质检。
1.2 自动化流水线的目标和需求清单
我给这个项目列了一个明确的需求清单,所有的选型和代码都围绕这些需求展开:
- 每天能自动抓取多个技术新闻源,去重、过滤、排序,形成一个当天的候选新闻池。
- 调用大模型接口,把新闻标题和正文转成适合口播的中文脚本。
- 使用文本转语音生成配音,同时拿到每句话的时间戳,用于后续的字幕对齐。
- 用代码渲染视频,将标题、正文、字幕、配音、背景动画全部“画”出来。
- 一条命令完成从“原始新闻”到“成片MP4”的全部流程,中间不需要任何人工点击剪辑软件。
- 即使某些环节出错,系统也要能自动跳过或重试,而不是直接崩溃。
需求定了之后,后面的工具选型就变得清晰了。
2. 工具选型:蓝耘元生代 + Remotion 为什么能搭在一起
2.1 Remotion 不是剪辑软件,而是“用代码拍视频”
大部分人听到“视频渲染”,第一反应是 Premiere、剪映、Final Cut,但我要做的不是“剪辑”而是“生成”。剪辑的前提是你已经有一段段素材,而我的情况是:素材根本不存在,我需要先把文字变成画面,再把这些画面串成视频。
Remotion 解决的就是这个问题。它本质上是一个 React 应用——你写组件,组件里的每个 prop、每个样式、每个变量的变化,在时间轴上都被映射为某一帧的画面。渲染时,Remotion 从头到尾逐帧生成图片,最后合成为视频。
打个比方:传统剪辑软件像是你用手在稿纸上写字,一笔一画都得自己来;Remotion 像是你写了一个排版程序,程序按你的规则自动把每一页排好、装订成册。第一次写排版程序很累,但一旦写好,批量出书就只是按一下按钮的事。
2.2 蓝耘元生代在流水线里的职责
光是会渲染还不够,视频里真正的内容——文案、配音、逻辑组织——需要有AI来扛。我把蓝耘元生代在这条流水线里当作“AI能力底座”,负责两件事:
第一,调用大模型服务生成口播稿。我把当天采集到的新闻标题和正文塞进提示词,让它输出“主持人播报风格”的新闻解说词,并且是以结构化的方式返回,方便程序直接解析。
第二,提供语音合成能力。文本转语音之后,我不光拿到一个音频文件,更重要的是拿到每个字或每句话的时间点。字幕能不能卡在正确的画面上,全靠这些时间点。
为什么选蓝耘元生代而不是自己折腾本地模型?原因很简单:本地部署大模型对显存要求高,而且每天跑一次,电费和硬件损耗不划算。我更希望它像一个 API 一样被我调用——传一段文本进去,拿到一段稳定、高质量的文本或音频返回。平台的方式恰好满足,且不需要我自己维护推理环境。
2.3 为什么不直接用剪映或FFmpeg脚本
很多朋友问我:这东西用剪映的图文成片功能不就行了?用FFmpeg拼几个图片加MP3不也能成片吗?
我用一张表来说明区别:
| 方案对比 | 批量控制 | 时间轴精确对齐 | 动态生成元素 | 可编程 | 适合自动化程度 |
|---|---|---|---|---|---|
| 剪映等GUI工具 | 弱,要靠模拟点击 | 弱 | 弱 | 基本无 | 低,适合人工精修 |
| FFmpeg拼接 | 强 | 弱,所有元素都靠手动算时间 | 弱,图片文字要提前生成 | 一般 | 中,适合简单幻灯片 |
| Remotion | 强 | 强,帧级控制 | 强,组件随数据变化 | 完整React生态 | 高 |
| Remotion+AI平台 | 强 | 强 | 强 | 完整,内容也可AI生成 | 极高 |
FFmpeg并不是不行,但它的核心能力是“转封装”和“滤镜”,而不是“根据数据生成画面”。如果我要做的是“当天新闻标题动态渲染到背景上”、“字幕逐句弹出”、“每句话对应一张配图”,用FFmpeg手动算时间轴会非常痛苦。Remotion 则完全不一样,它的全部渲染逻辑都是代码,数据一变,成片自动变。这也是我选择它作为视频骨架的根本原因。
3. 整条流水线的核心设计
3.1 从 RSS 到新闻池
整个流水线的第一环是“获取当天新闻”。我用的是最稳的方案:RSS 订阅 + 热榜接口。
先维护一个 RSS 订阅源列表,覆盖综合技术媒体、几个主流开源社区、若干大佬博客。每天定时任务触发,拉取每个源的条目,解析出标题、链接、发布时间、正文摘要。然后做一次统一处理:
- 过滤掉标题和正文里明显无关的内容(规则,包含指定关键词就丢弃,避免AI生成时被噪音干扰)。
- 对“标题+正文摘要”做简单去重,同一个事件不同来源的报道只保留最早或最权威的一条。
- 按时间排序,选出当天最新的前10条作为候选池。
热榜接口作为补充,专门处理“突发新闻”和“已经在社区刷屏的消息”。有些高质量的内容藏在搜索引擎排不到的地方,如果只看RSS会漏掉。
这个阶段我特别注意一件事:不直接拿原始标题去生成新闻稿,而是让AI基于“标题+正文摘要”理解事件本身。因为很多新闻标题是标题党或省略句,AI只看标题容易一本正经地胡说八道。
3.2 AI 写稿:从“新闻列表”到“口播稿”
拿到候选新闻池之后,下一步是让蓝耘元生代平台的大模型接口把这些内容改写成口播稿。
我写了一个固定的提示词模板,核心逻辑是:
- 把每条新闻的标题、来源、时间、正文摘要拼成一段上下文。
- 要求模型按“导语-展开-总结”的结构组织语言。
- 明确限定篇幅:单条新闻60字左右导语 + 150字左右展开。
- 要求输出为 JSON 数组,每个元素包含
title、content、summary三个字段,方便程序解析。
提示词里还会固定这样一句:“你是技术新闻主播,语言要口语化,避免学术腔,不要在新闻里添加你没有依据的推测。”
这一步是整条流水线里最需要调优的地方。模型输出质量的好坏,直接决定观众愿不愿意把视频看完。早期我的提示词写得非常随意,导致AI经常输出“首先”“其次”“总之”这种摘要式语言,听起来毫无可看性。后来我把“给朋友讲一条新闻”的口吻直接写进了提示词,输出质量明显提升。
3.3 配音与字幕:时间轴的中间层
口播稿生成之后,文本会交给 TTS 模块。蓝耘元生代的语音合成接口返回的不仅是音频文件,还有每句话的时间戳。这个时间戳是整条流水线的关键——Remotion 渲染时,每一句字幕的入场、停留、退场,完全由它驱动。
这里有一个设计细节:字幕不是按“字符数均匀分布”来排的,而是按 TTS 实际朗读的起止时间来排。因为一个人说话不是匀速的,停顿时长、语速变化都会影响字幕要不要等。早期我试过按字数估算时间,结果视频里经常出现“声音还在讲上一句,字幕已经跳到下一句”的尴尬情况。后来改用 TTS 返回的真实时间戳,这种问题基本消失。
音频拿到手之后,还要做一次“标准化”。我会在代码里统一限制单条新闻音频的时长上限:如果某条新闻配音超过90秒,就裁剪掉后面多余的部分;如果少于40秒,则自动补一段空白音,避免视频节奏太快让观众来不及看画面。
3.4 渲染与发布:一条命令怎么把链子串起来
所有中间产物准备完毕,最后一步是渲染。Remotion 会去读取一个 JSON 文件,里面存着每条新闻的标题、正文、字幕、音频文件路径、时间戳。通过renderMedia这个 API,它能自动逐帧渲染并合成视频。
我最终的“一条命令”是用 npm 脚本跑的,大致长这样:
npm run build:videos这个命令内部依次执行了四个步骤:
node scripts/fetch-news.js node scripts/generate-script.js node scripts/generate-voice.js npx remotion render src/index.ts dist/news-video.mp4fetch-news.js:拉取新闻源,输出候选池。generate-script.js:调用AI完成写稿,输出 JSON。generate-voice.js:调用 TTS 生成配音,输出音频和时间戳。remotion render:渲染最终成片。
整条链子串起来之后,每天凌晨2点由定时任务触发,跑完直接推送到视频平台。我早上只需要打开后台看一眼播放数、标题是否合适、有没有敏感词,有需要就手动调整一下。
4. 核心环节的实操实现
4.1 新闻采集模块的稳定性处理
新闻采集看起来简单,实际全是坑。反爬、超时、编码、结构变更,任何一个都可能让整条流水线断掉。
我采新闻用的不是无头浏览器,而是直接请求 RSS 的 XML 接口。RSS 本身是标准格式,没有复杂的页面渲染,解析非常稳定。唯一要注意的是有些站的 RSS 输出格式不规范,<description>里有大量 HTML 标签,直接拿正则清标签是最省事的做法:
function cleanHtml(raw) { return raw .replace(/<script[\s\S]*?<\/script>/g, '') .replace(/<style[\s\S]*?<\/style>/g, '') .replace(/<[^>]+>/g, ' ') .replace(/ /g, ' ') .replace(/&/g, '&') .replace(/\s+/g, ' ') .trim(); }网络请求统一加了超时控制,单个源请求超过10秒就跳过;连续3次失败,就把这个源临时拉进“黑名单”,第二天再恢复,防止某一个源挂了拖垮整体任务。
去重逻辑我放在内存里做,用一个 Map 记录“标题的汉语拼音首字母缩写”作为 key。实现很简单但不失有效:把标题里的字母和数字提取出来转小写,当作指纹,完全相同就跳过。这个方法对大多数新闻源有效,而且没有额外依赖。
4.2 提示词模板与结构化输出
写稿的提示词我是这么组织的:
你是一个技术新闻视频节目主持人。下面会给你若干条当日技术新闻,每条新闻包含标题、来源、时间和正文摘要。 请为每条新闻写一段口播稿,要求: 1. 导语用一句话交代事件核心,像一个朋友在聊天,不要用“据报道”。 2. 展开部分解释这件事为什么重要、影响什么人群。 3. 结尾用一句简短总结。 4. 全文口语化,不要出现书面语连接词。 5. 不要编造事实,不要加入新闻中没有的依据。 输出要求: 只输出 JSON,格式为: [ { "title": "新闻标题", "content": "口播稿全文", "summary": "20字以内的一句话总结" } ] 新闻列表如下: ...这里有个特别重要的技巧:一定要用 JSON 作为输出格式。如果没有它,AI 可能输出大段 Markdown 或口语废话,程序解析起来非常难受。而且 JSON 一旦被破坏,整条链子就会断掉,所以我还在代码里加了 JSON 重新正则提取的容错逻辑——如果模型返回的外面有多余文字,就只截取第一个[到最后一个]之间的内容。
另外,模型偶尔会“上头”加一条不存在的新闻。我的策略是:生成完之后做一次“原文回查”,把生成的每条新闻标题跟当天新闻池做关键词匹配,匹配度太低的直接剔除。
4.3 Remotion 里的字幕与背景排布
Remotion 的核心概念是“组件即画面”。我把一条新闻的视频结构设计成三部分:开头标题页、中间字幕滚动、结尾总结页,它们分别封装成三个组件。
字幕组件的关键代码如下:
import { useCurrentFrame, interpolate } from 'remotion'; export const Subtitle = ({ text, startFrame, duration }) => { const frame = useCurrentFrame(); const opacity = interpolate(frame, [startFrame, startFrame + 5, startFrame + duration - 5, startFrame + duration], [0, 1, 1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( <div style={{ opacity, transform: `translateY(${(1 - opacity) * 10}px)` }}> {text} </div> ); };这段代码做的事情是:根据当前帧是否落在字幕的startFrame到startFrame + duration区间内,控制字幕的透明度从0到1再回到0,同时加一点点位移动画,让字幕有“浮入浮出”的效果,而不是生硬地出现消失。
背景部分我用的是一组渐变色块加一个旋转的几何图形。颜色和图形由小组件循环渲染,这样看起来像是“不同的场景”,其实底层只有三四个组件在换参数。多种背景特效我通过Sequence组件来控制时长,每个序列的持续时间对齐对应的音频段落。
4.4 渲染时长控制和成片节奏
单条新闻音频长度一般控制在40到90秒之间,配上标题和结尾页,一条新闻的视频段大概是70到110秒。每天我选前8条新闻,最终成片总长控制在8到12分钟。
太长观众看不完,太短内容单薄。最重要的是不要让渲染时间失控,因为视频越长,渲染成本越高。我统计过,在云端渲染10分钟左右的1080P视频,耗时大约在20到30分钟,这已经是可以接受的范围。如果哪天新闻特别多,我会在脚本里只取前8条,避免一次跑太久。
这里我还加了一个“兜底动画”:如果音频时长小于40秒,Remotion 会在字幕结束后插一段“今日速览”的过渡画面,配个音效再进下一条新闻,不然画面会冷场。
5. 踩过的坑,写给你们
5.1 字幕断句和朗读不一致
这是我在早期踩的最大的坑。TTS 播报时,“尤其是”“也就是说”这类词会连读,而字幕如果是按标点断开的,就会出现“字幕显示的是整句,声音已经读到下一句”的错位感。
后来我做了两处改动:一是在生成字幕时,严格按 TTS 返回的句级时间戳切分;二是在文案生成阶段就直接要求模型“一句话不要超过30个字,尽量用句号结尾”。这两个改动同时生效之后,字幕和声音才真正做到同步。
5.2 中文字体与特殊符号渲染问题
Remotion 默认不会自动加载系统字体。我第一次在服务器上渲染时,所有中文全部变成了方框。解决方法是:把字体打包进项目里,通过@remotion/google-fonts或引本地字体文件的方式载入。
还有一个坑是特殊符号。新闻标题里经常出现⭐🔥这类 emoji,但服务器渲染环境没有对应字体,最终画面就是一个个方块,非常难看。后来我在生成字幕前统一做了一层过滤,把不支持的符号直接替换成文字描述,比如🔥换成“热门”。
5.3 渲染排队导致内存暴涨
最开始为了加快速度,我把渲染并发数设置为4,结果渲染到第3条新闻时内存直接爆掉。原因是每条字幕/背景组件都会预先加载视频帧,并发越多,占用的内存越多。
最终我把并发数改成了1,虽然慢了一点,但稳定优先。如果你也想提速,更稳妥的方案是分成多个小视频并行渲染,最后再拼接,而不是单进程内并发。
5.4 音频前后有静音导致时间对不齐
TTS 返回的音频经常在开头和结尾各带一小段静音,直接放进时间轴会导致画面和声音错开半秒到一秒。虽然看着不多,但很有违和感。
我在代码里用音频分析库做了一个“去静音”处理:截掉前导静音和尾部静音,再把剩余音频对齐到字幕的startFrame。这样不仅对齐了,还能节省几帧的渲染时间。
5.5 某天新闻池为空
不是每天都有足够的新闻量。最初遇到空新闻池时,整个 pipeline 会报错退出,第二天视频自然就没发出来。我后来加了一个判断:如果候选新闻不足3条,就自动生成一个“今日技术圈无事发生?其实是这些值得关注”的汇总封面视频,文案由 AI 生成,至少保证当天的产出没有断。
6. 跑了一周之后的实际数据
这套系统连续运行一周之后,我统计了一些数据:
| 指标 | 数据 |
|---|---|
| 每日平均产出视频数 | 1条,约9分钟 |
| 从新闻抓取到成片完成平均耗时 | 约35分钟 |
| 云服务单日成本 | 约几元(主要来自模型调用和渲染时长) |
| 人工介入次数 | 一周内2次,均为AI生成了不合适的标题 |
| 平均字幕错位事件 | 0,改用句级时间戳后彻底解决 |
整个系统跑下来,最让我满意的不是“生成速度快”,而是“确定性高”。之前手工剪辑,每一条视频的时长、节奏、字幕风格都可能有偏差;现在代码统一控制,输出质量非常稳定。
如果后续继续扩展,我会把同一套新闻池同时生成一个“竖屏版短视频”和一个“英文版”,用相同的组件,改一下布局和文案提示词就能出片。这套流水线的核心资产已经沉淀在代码里了,后续衍生内容只是改配置的问题。
说句心里话,整个项目里最有价值的反而不是 AI 生成视频的那一刻,而是你把流程拆成“采集-生成-渲染-发布”四个稳定的接口,让每个环节都能独立升级。我给 AI 打工,但真正让 AI 好好打工的,是我先把工作拆成了它擅长干的样子。