第 15 章 视频处理:ffmpeg 与 Whisper 实战
🎬 本章特色:系统掌握 ffmpeg 音视频处理与 Whisper 语音识别两大开源利器,结合 OpenClaw 的 zhz-video-compress、zhz-transcript-summarize、zhz-video-logo、zhz-subtitle 四大技能,从视频压缩、内容转录总结、批量加水印到双语字幕生成,用命令行一站式解决视频后期处理需求。
本章目录:
| 节 | 内容 | 你将学到 |
|---|---|---|
| 1 | ffmpeg:音视频处理瑞士军刀 | ffmpeg 是什么、音视频编码基础、三平台安装、常用命令速查 |
| 2 | Whisper:开源语音识别引擎 | Whisper 是什么、模型原理与选型、faster-whisper 安装、语音转文字基础 |
| 3 | 视频压缩:zhz-video-compress 技能 | 视频压缩原理,使用zhz-video-compress 技能批量压缩实战 |
| 4 | 视频转录与总结:zhz-transcript-summarize 技能 | ffmpeg 提取音频 + Whisper 转录 + AI 摘要,30 分钟播客变文字要点 |
| 5 | 视频批量加水印:zhz-video-logo 技能 | zhz-video-logo 技能、技术原理、批量加水印实战 |
| 6 | 视频双语字幕:zhz-subtitle 技能 | 技能安装、8 步自动化工作流、中文演讲视频配英文字幕实战 |
| 7 | 总结与进阶 | 核心回顾、工作流组合、课后练习 |
1. ffmpeg:音视频处理瑞士军刀
1.1 ffmpeg 是什么
ffmpeg 是一个开源的多媒体处理工具,几乎可以处理所有已知的音频和视频格式。它诞生于 2000 年,由法国程序员 Fabrice Bellard 发起,经过二十多年的社区共同维护,已经成为音视频领域的基石级软件。
你可能没有直接使用过 ffmpeg,但你每天都在享受它的成果。VLC 播放器能播放几乎所有格式的视频,YouTube 能把上传的视频自动转成多种清晰度,这些软件的底层都依赖 ffmpeg 的编解码库。可以说,ffmpeg 是音视频世界的"基础设施",就像 Linux 内核之于操作系统一样。
ffmpeg 的核心特点有三个。第一是全能:它支持数百种音视频编解码器和容器格式,从古老的 AVI 到最新的 AV1,从 WAV 到 MP3,几乎没有它不能处理的格式。第二是跨平台:Windows、macOS、Linux 三大平台都有官方支持,安装后即可使用。第三是命令行驱动:所有操作都通过命令行完成,这意味着你可以轻松编写脚本实现批量处理,也可以让 AI 智能体直接调用它来完成音视频任务。
在 OpenClaw 的工作流中,ffmpeg 扮演着"底层工具"的角色。当你让 OpenClaw 压缩视频、提取音频、加字幕、截取片段时,它在幕后调用的就是 ffmpeg。理解了 ffmpeg 的基本原理和命令,你就能更好地理解 OpenClaw 的音视频处理能力,也能在需要时手动执行更复杂的操作。
1.2 音视频编码基础
在使用 ffmpeg 之前,你需要理解几个核心概念。这些概念技术性强,掌握了它们之后,你就能做出更好的压缩和转换决策。
音频的数字化
我们日常听到的声音是一种连续的模拟信号,计算机无法直接存储和处理这种连续波形,必须经过采样和量化两个步骤,把它转换为二进制数字数据。
采样是在时间轴上对连续声波进行离散化取值。你可以想象成每毫秒对声波"拍快照",拍的次数越多(采样频率越高),还原出的波形就越接近原声。CD 音质的采样频率是 44.1kHz,也就是每秒采样 44100 次。电话语音的采样频率通常只有 8kHz,采样频率较低,所以听起来发闷。
量化是把每个采样点的振幅值映射为有限个离散等级。例如 256 个量化级别对应 2 的 8 次方,即用 8 位二进制数表示一个采样点。量化位数越高,声音的动态范围越大,细节越丰富。CD 音质使用 16 位量化,专业录音棚使用 24 位甚至 32 位。
声道数是指音频信号中独立音轨的数量,也就是录制或播放时有多少路声音同时存在。它决定了声音的"空间感",是平面的单点声源,还是有方位感的立体声场。有单声道,双声道和多声道。双声道的数据量正好是单声道的两倍。

图15-1 音频的采样示意图

图15-2 音频的量化示意图
有了采样频率、量化位数和声道数,就可以计算一段未压缩音频的存储容量:
音频存储容量 (字节) = 采样频率 × 量化位数 × 声道数 × 时长(秒) ÷ 8
举个例子:一段 100 秒的双声道音乐,采样频率 44.1kHz,量化位数 16 位,它的未压缩大小为 44100 × 16 × 2 × 100 ÷ 8 = 17,640,000 字节,约 17 MB。如果是一首 4 分钟的歌曲,未压缩大小约 42 MB。这就是为什么早期 MP3 播放器宣传"把 1000 首歌装进口袋"时需要压缩格式的原因。
图像的数字化
和视频密切相关的另一个基础概念是图像数字化。数字图像由许多彩色或灰度点按横纵排列组成,这些点称为像素(Pixel)。图像尺寸通常表示为"水平像素数 × 垂直像素数",例如 1920×1080 表示水平方向有 1920 个像素,垂直方向有 1080 个像素。
每个像素的颜色用一定位数的二进制数表示,称为颜色深度。颜色深度为 n 位时,可以表示 2 的 n 次方种颜色。常见的颜色深度有 1 位(黑白两色)、8 位(256 级灰度或 256 色)、24 位(约 1677 万色,也叫"真彩色")。颜色深度越大,色彩越丰富,但占用的存储空间也越大。
未压缩图像的一帧存储容量计算公式:
图像存储容量 (字节) = 水平像素数 × 垂直像素数 × 颜色深度 ÷ 8
两个计算示例:一张 90×72 像素的黑白图(颜色深度 1 位),大小为 90 × 72 × 1 ÷ 8 = 810 字节。同样尺寸的 24 位彩色图,大小为 90 × 72 × 24 ÷ 8 = 19,440 字节,约 19 KB。可以看出,同样的分辨率,24 位彩色图的数据量是黑白图的 24 倍。
理解了单帧图像的数据量之后,你就能明白视频数据为什么如此庞大了。一段 1080p(1920×1080)、24 位色深、30fps 的未压缩视频,每秒钟的原始数据量为 1920 × 1080 × 24 × 30 ÷ 8 ≈ 186 MB,一分钟就是 11 GB。这就是为什么视频编码压缩如此重要。
编码(Codec)与容器(Container)的区别
这是初学者最容易混淆的两个概念。用一个比喻来理解:容器是一个"包装盒",编码是"包装里面的东西的压缩方式"。
容器(Container)是文件的"外壳",它决定了文件里能装哪些类型的数据。常见的容器格式有 MP4、MKV、AVI、MOV 等。一个 MP4 文件里可以同时包含视频流、音频流、字幕流和元数据(标题、作者、章节等)。容器就像一个快递箱,里面可以装很多东西。
编码(Codec)则是视频或音频数据的"压缩算法"。正如前面计算的,一段 1 分钟的 1080p 未压缩视频原始数据量超过 11 GB,显然不适合存储和传输。编码器的作用就是把这些原始数据压缩到可接受的大小,同时尽量保持画面质量。常见的视频编码有 H.264(目前最广泛使用)、H.265(也叫 HEVC,压缩效率更高)、VP9(Google 开发,YouTube 主力编码)、AV1(新一代开源编码,压缩效率最高但编码速度慢)。常见的音频编码有 AAC(MP4 容器的标配)、MP3(老牌格式,兼容性最好)、FLAC(无损压缩)、Opus(低延迟,适合实时通信)。
一个 MP4 容器里通常装着 H.264 编码的视频和 AAC 编码的音频。但 MP4 也可以装 H.265 视频,MKV 容器则可以装几乎任何编码的数据。容器和编码是独立的两个维度。

常见容器格式对比
| 容器 | 特点 | 适用场景 |
|---|---|---|
| MP4 | 兼容性最强,几乎所有设备和平台都支持 | 手机拍摄、网页播放、社交平台 |
| MKV | 开源格式,封装能力最强;支持多音轨、多字幕、章节信息 | 高清电影收藏、蓝光提取 |
| MOV | 苹果开发,支持专业编码和多轨道编辑信息 | 影视后期剪辑、苹果生态 |
| AVI | 微软 1992 年推出的老格式;结构老旧,不支持多字幕/多音轨,文件体积大 | 老旧设备兼容、历史资料 |
常见视频编码对比
| 编码 | 特点 | 适用场景 |
|---|---|---|
| H.264(AVC) | 兼容性极高,几乎所有设备都能硬解;算法成熟、延迟低 | 直播、视频会议、日常分享 |
| H.265(HEVC) | 同等画质下码率比 H.264 降低约 50%,文件体积减半;但编码复杂度高,老旧设备可能不支持 | 4K/8K 超高清、监控存储 |
简单记忆:H.265 是 H.264 的升级版,画质相同但体积减半,对设备要求更高。
常见音频格式对比
| 格式 | 压缩方式 | 特点 | 典型用途 |
|---|---|---|---|
| WAV | 未压缩 | 音质高,与原声基本一致,文件大 | 专业音频存储 |
| MP3 | 有损压缩 | 去除人耳不敏感的高频,失真小,文件较小 | 音乐播放 |
| AAC | 有损压缩 | 同码率下音质优于 MP3,支持多声道 | 视频默认音频编码 |
| FLAC | 无损压缩 | 还原后与原始数据一致,压缩比例小 | 高保真音乐 |
| Opus | 有损压缩 | 极低延迟,适合实时通信 | 语音通话、视频会议 |
AAC(Advanced Audio Coding) 是 MP3 的继任者,已成为 MP4 等视频容器的默认音频编码。在同码率下,AAC 的音质优于 MP3,128kbps 的 AAC 大约等效于 160kbps 的 MP3。
YUV420P:视频编码的"原材料"
在深入码率概念之前,有必要了解一种重要的色彩采样格式:YUV420P。它是 H.264、H.265 等主流视频编码默认采用的输入格式,理解它有助于你明白为什么视频压缩能做得这么小。
YUV420P 把每个像素的颜色拆分成三个分量:Y 表示亮度(Luma),U 和 V 表示色度(Chroma)。关键设计在于:Y 分量保留全分辨率,而 U 和 V 分量在水平和垂直方向各降采样一半。也就是说,每 2×2 共 4 个像素共享一组 U 和 V 值。
这个设计利用了一个人眼特性:人眼对亮度的敏感度远高于对色度的敏感度。你可以做一个实验,把一张彩色照片转成灰度图(只保留亮度),你会发现照片中的绝大部分信息仍然清晰可辨。YUV420P 正是利用这一点,把色度数据砍掉一半,总数据量降为 RGB 格式的约 50%,而人眼几乎察觉不到差异。
一帧 YUV420P 数据的大小计算很简单:宽 × 高 × 1.5(字节)。比如一帧 1080p 画面的 YUV420P 数据为 1920 × 1080 × 1.5 = 3,110,400 字节,约 3 MB。30fps 的视频每秒就是 90 MB 的原始数据。编码器的任务就是把这些数据进一步压缩到几 MB 甚至更小。
码率(Bitrate)
码率是指每秒钟的数据量,通常用 kbps(千比特每秒)衡量。在相同编码和相同内容下,码率越高,画质越好,但文件也越大。码率是控制文件大小的最直接参数:同样时长的视频,码率减半,文件大小也大致减半。
不同分辨率下,H.264 和 H.265 的推荐码率参考值如下:
| 分辨率 | H.264 推荐码率 | H.265 推荐码率 | 说明 |
|---|---|---|---|
| 720p (1280×720) | 2500 ~ 4000 kbps | 1500 ~ 2500 kbps | 网络视频、手机观看 |
| 1080p (1920×1080) | 4000 ~ 8000 kbps | 2500 ~ 5000 kbps | 日常录制、教学视频 |
| 4K (3840×2160) | 15000 ~ 25000 kbps | 8000 ~ 15000 kbps | 高质量创作、大屏播放 |
可以看到,H.265 在同等画质下所需码率大约是 H.264 的一半,这也是它被称为"体积减半"的原因。如果你的视频主要在电脑和手机上观看,1080p 配 4000 kbps(H.264)或 2500 kbps(H.265)已经能得到很好的画质。
分辨率(Resolution)
分辨率是指画面的像素数量,用“宽 × 高”表示。常见的分辨率有 720p(1280×720)、1080p(1920×1080)、4K(3840×2160)。分辨率越高,画面细节越丰富,但数据量也越大。在压缩视频时,降低分辨率是最有效的“瘦身”手段之一,但也最影响画质。分辨率对数据量的影响大致是平方关系,比如 1080p 降到 720p,像素数只剩约 44%,文件大小也下降到一半左右。
帧率(Frame Rate)
帧率是指每秒钟显示的画面数量,用 fps(frames per second)表示。常见的帧率有 24 fps(传统电影标准)、30 fps(网络视频常用)、60 fps(游戏和高帧率视频)。帧率越高,画面越流畅,需要处理的帧也越多,数据量通常会增加。对于大多数非游戏类视频,30 fps 已经足够。
从原始数据到最终文件的完整流程
把上面所有概念串起来,一个音视频文件从原始数据到最终文件经历以下过程:

理解了这些概念之后,你就能明白 ffmpeg 的命令在做什么了。比如"把视频从 1080p 压缩到 720p,码率设为 2000 kbps,使用 H.265 编码",这句话里的每一个参数你都知道是什么意思了。
1.3 安装 ffmpeg
ffmpeg 在两大平台上的安装都很简单。
Windows 安装
推荐使用 winget 一键安装:
winget install ffmpeg
winget 是微软官方推出的 Windows 包管理器(Windows Package Manager),命令行工具名就是 winget。你可以把它理解成 Windows 上的命令行应用商店。用来搜索、安装、更新、卸载软件。
安装完成后,打开一个新的 PowerShell 窗口,验证安装:
ffmpeg -version
如果看到版本号输出(例如 ffmpeg version 6.1.1),说明安装成功。
如果你更喜欢手动安装,可以到 ffmpeg 官网 https://ffmpeg.org/download.html 下载 Windows 构建包,解压后将 bin 目录添加到系统环境变量 PATH 中。
Linux 安装
Ubuntu 或 Debian 系统:
sudo apt update
sudo apt install ffmpeg
1.4 常用命令
安装好 ffmpeg 之后,下面是日常最常用的命令。建议你逐一尝试,熟悉 ffmpeg 的工作方式。
查看文件信息
# 查看视频的详细编码信息
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
ffprobe 是 ffmpeg 套件中的"探测器",用来查看媒体文件的编码信息。上面的命令会以 JSON 格式输出视频的所有信息,包括分辨率、帧率、码率、编码格式、时长等。
分辨率:
"coded_width": 1920,
"coded_height": 1024,
帧率:
"avg_frame_rate": "30000/1001"
编码格式:
"codec_long_name": "H.265 / HEVC (High Efficiency Video Coding)",
时长:
"duration": "1248.347100",
如果你只需要简洁的概览:
ffmpeg -i input.mp4
ffmpeg 会在最后几行输出视频和音频流的基本信息。例如时长和码率:
Duration: 00:20:48.35, start: 0.000000, bitrate: 201 kb/s
-i 表示指定输入文件。
格式转换
# 把 AVI 转成 MP4
ffmpeg -i input.avi output.mp4
# 把 MP4 转成 MKV(仅更换容器,不重新编码,速度极快)
ffmpeg -i input.mp4 -c copy output.mkv
第二条命令中的 -c copy 是一个非常重要的参数,它告诉 ffmpeg"直接复制音视频数据,不要重新编码"。当源格式和目标格式兼容时(比如 MP4 转 MKV),这样做可以在几秒钟内完成转换,而且画质完全不变。
提取音频
# 从视频中提取音频,保存为 MP3
ffmpeg -i video.mp4 -vn -acodec libmp3lame -q:a 2 audio.mp3
-vn 表示不要视频,-acodec libmp3lame 指定使用 MP3 编码,-q:a 2 设置音频的编码质量级别(范围 0-9,数值越小质量越高)。0-3 通常产生"透明"效果(人耳难以察觉差异),4 是默认值,6 以上质量明显下降。)。
截取视频片段
# 从第 10 秒开始,截取 30 秒
ffmpeg -i input.mp4 -ss 00:00:10 -t 30 -c copy clip.mp4
-ss 指定起始时间,-t 指定时长。加上 -c copy 可以不重新编码,截取速度非常快。
调整分辨率
# 把 1080p 视频缩放到 720p
ffmpeg -i input.mp4 -vf "scale=1280:720" -c:a copy output_720p.mp4
-vf 是视频滤镜参数,scale=1280:720 表示缩放到 1280×720 像素。-c:a copy 表示音频直接复制,不重新编码。
生成缩略图
# 在视频第 5 秒处截取一帧画面保存
ffmpeg -i input.mp4 -ss 00:00:05 -vframes 1 thumbnail.jpg
-ss 表示指定起始时间。-vframes 1 表示只输出 1 帧画面。
掌握了以上这些基础命令,你已经可以用 ffmpeg 处理大部分日常需求了。后面的章节会在此基础上介绍更高级的用法。
2. Whisper:开源语音识别引擎
2.1 Whisper 是什么
Whisper 是 OpenAI 在 2022 年 9 月开源发布的一款自动语音识别(ASR)模型。它的目标是把人类说话的声音自动转换成文字,而且能做到多语言、多口音、高准确率。
在 Whisper 出现之前,高质量的语音识别基本上是商业公司的专利。Google 的语音识别、百度的语音转文字、科大讯飞的语音输入,这些都是闭源的商业产品,要么需要联网调用 API,要么需要购买授权。Whisper 的出现改变了这个局面:它是一个完全开源的模型,任何人都可以免费下载并在本地运行,不需要联网和付费。
Whisper 的训练数据量非常大。OpenAI 从互联网上收集了大约 68 万小时的多语言音频和对应的文字标注,用这些数据训练出了一个 encoder-decoder 架构的 Transformer 模型。作为对比,早期的语音识别模型通常只有几千到几万小时的训练数据。海量的训练数据让 Whisper 拥有了极强的泛化能力:它不仅能识别标准播音腔的普通话,也能应对各种口音、方言腔调、背景噪音、多人对话等复杂场景。
Whisper 的核心能力包括四个方面。第一是多语言识别:支持 99 种语言的语音转文字,中文、英文、日文、法文等主流语言表现尤为出色。第二是语音翻译:可以直接把非英语的语音翻译成英文文字输出,比如输入中文语音,直接输出英文文本。第三是时间戳标注:能精确标注每句话的起止时间,这对生成字幕至关重要。第四是语言检测:即使你不告诉它音频是什么语言,Whisper 也能自动检测出来。
在 OpenClaw 的工作流中,Whisper 承担着"语音转文字"的核心角色。当你让 OpenClaw 转录一段视频、生成字幕、总结播客内容时,第一步就是用 Whisper 把音频转换成文字。后面介绍的zhz-video-compress 技能、zhz-transcript-summarize 技能和 zhz-subtitle 技能就是基于 Whisper 构建的。
2.2 模型选型:从 tiny 到 large-v3
Whisper 提供了 5 种不同大小的模型,从最小的 tiny 到最大的 large-v3,分别适用于不同的场景。选择合适的模型是效率和质量的关键平衡点。
| 模型 | 参数量 | 显存需求 | 相对速度 | 中文准确率 | 英文准确率 | 适用场景 |
|---|---|---|---|---|---|---|
| tiny | 39M | ~1 GB | 最快 | 一般 | 较好 | 快速预览、测试 |
| base | 74M | ~1 GB | 很快 | 较好 | 好 | 日常使用、短视频 |
| small | 244M | ~2 GB | 中等 | 好 | 很好 | 长音频、中文内容 |
| medium | 769M | ~5 GB | 较慢 | 很好 | 很好 | 高精度需求 |
| large-v3 | 1550M | ~10 GB | 最慢 | 最好 | 最好 | 专业转录、多语言 |
选择建议如下。如果你只是转录英文内容或做快速预览,base 模型已经足够好用,速度也很快。如果你需要转录中文内容,建议至少使用 small 模型,因为中文的识别难度比英文高不少,小模型容易出现错字和漏字。如果你追求最高准确率,而且电脑有独立显卡(显存 5 GB 以上),可以选择 medium 或 large-v3。对于大多数 OpenClaw 用户来说,base 或 small 是最实用的选择。
2.3 faster-whisper:快 4 倍的替代实现
原版 Whisper 使用 PyTorch 框架实现,虽然功能完整,但运行速度不是最优的。社区开发者在此基础上开发了 faster-whisper,它使用 CTranslate2 推理引擎,在保持同样准确率的前提下,速度提升了约 4 倍,内存占用也显著降低。
安装 faster-whisper 非常简单:
pip install faster-whisper
安装完成后,你可以用 Python 脚本来转录音频:
from faster_whisper import WhisperModel
# 加载模型(首次运行会自动下载)
model = WhisperModel("base", device="cpu", compute_type="int8")
# 转录音频文件
segments, info = model.transcribe("audio.mp3", language="zh")
# 输出转录结果
print(f"检测到的语言: {info.language} (概率: {info.language_probability:.2f})")
print(f"音频时长: {info.duration:.1f} 秒")
print()
for segment in segments:
print(f"[{segment.start:.1f}s ~ {segment.end:.1f}s] {segment.text}")
这段代码做了四件事:加载 base 模型,指定 CPU 推理和 int8 量化(减少内存占用),转录指定的音频文件,最后逐段输出转录结果和对应的时间戳。
首次运行时,faster-whisper 会自动从 Hugging Face 下载对应的模型文件。如果你在国内,可能需要设置镜像源来加速下载:
# 设置 Hugging Face 镜像(国内用户)
set HF_ENDPOINT=https://hf-mirror.com
pip install faster-whisper
或者在 Python 脚本的最开头加上环境变量设置:
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
2.4 基础用法:一段音频转文字
让我们用一个完整的例子来体验 Whisper 的工作流程。假设你有一段名为 meeting.mp3 的会议录音,想要把它转成文字。
from faster_whisper import WhisperModel
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" # 国内镜像
# 加载 small 模型(中文效果更好)
model = WhisperModel("small", device="cpu", compute_type="int8")
# 转录音频,自动检测语言
segments, info = model.transcribe("token.m4a")
# 保存转录结果
with open("token.txt", "w", encoding="utf-8") as f:
for segment in segments:
f.write(segment.text + "\n")
print(segment.text)
print(f"转录完成!共 {info.duration:.0f} 秒,语言: {info.language}")
#什么是token, Token是大语言模型处理文本时的最小计量单位, 翻译为中文,名称是词元。
运行后,你会在同目录下得到一个 token.txt 文件,里面是完整的转录文字。整个过程完全在本地完成,不需要联网(首次下载模型除外),也不需要任何 API 密钥。
这就是 Whisper 的核心价值:免费、开源、本地运行、支持多语言。有了它和 ffmpeg 的配合,你就能处理几乎所有的音视频转录需求了。
3. 视频压缩:zhz-video-compress 技能
3.1 需求背景
手机和相机录制的视频文件往往大得惊人。一段 30 分钟的 1080p 手机录像,文件大小轻松达到 3 到 5 GB。如果你经常录制屏幕教学视频、视频会议录像、Vlog 素材,磁盘空间会被迅速吃光。
压缩视频的需求来自几个现实场景。第一是节省存储空间。硬盘再大也有装满的一天,尤其是视频这种动辄几十 GB 的素材,日积月累很快就会爆盘。第二是便于传输和分享。原片体积太大,上传到网盘、发微信、发邮件都慢甚至超限,压缩后的版本传输成本大幅下降。第三是归档整理。长期拍摄积累的素材如果按拍摄时间归档,查找和管理会方便很多。
这些需求共同指向一个动作:批量压缩。一次旅行拍了上百段素材,一次课程录了 30 集,手动逐条压缩不现实。你需要一个能递归扫描目录、自动判断哪些该压、哪些已经压过、安全可靠的批量工具。
3.2 技术原理
视频压缩的本质,是去掉原始数据里的"冗余信息",在可接受的画质损失下大幅减小体积。要理解压缩,需要先理解几个核心概念。
CRF(Constant Rate Factor,恒定质量因子)
CRF(Constant Rate Factor,恒定质量因子)是 H.264/H.265 编码器的质量控制参数,与固定码率相反,它让编码器按画面复杂度动态分配码率,使全片主观画质保持一致。
CRF 是控制压缩质量的核心参数。它的取值范围是 0 到 51,数值越小画质越好,文件也越大。对于 H.264 编码,CRF 23 是默认值,画质良好;CRF 28 画质可接受、文件更小。对于 H.265(HEVC)编码,同样的画质对应的 CRF 值大约比 H.264 低 4 到 6,也就是说 H.264 的 CRF 23 大约等于 H.265 的 CRF 28。
preset(编码预设)
preset 控制编码的速度和效率。取值从快到慢依次是 ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow。越慢的预设,编码器花更多时间寻找最优压缩方案,最终文件更小但耗时更长。
H.265 为什么比 H.264 更能压
H.265 也叫 HEVC,是 H.264 的下一代标准。在同等画质下,H.265 的码率大约只需 H.264 的一半,文件体积减半。代价是编码复杂度更高、编码速度只有 H.264 的 1/2 到 1/3,且老旧设备可能不支持硬解。所以"体积优先"用 H.265,"兼容性优先"用 H.264。
为什么有的视频压不动
压缩不是万能的。如果文件本来就小(比如不到 10 MB),或者码率已经很低,压缩的意义也不大。这些"压不动"的情况,脚本会分两类处理:文件太小、码率过低在压缩前就自动跳过;压缩后若收益不足 5% 会自动保留原片,不做无意义替换。
批量压缩的两个工程难点
一是幂等性,也就是避免对已经压过的视频重复压缩,否则每跑一次就再转码一次,浪费时间还可能累积画质损失。二是安全性,转码中途失败不能损坏原片。批量工具必须先把结果写到临时文件,校验通过后才落盘,而且默认保留原片、不会替换原视频,压缩收益不足 5% 时宁可保留原片也不做无意义替换。
3.3 zhz-video-compress 技能
zhz-video-compress 是一个 OpenClaw 技能,它把上面的编码原理封装成一个纯 Python 标准库脚本 video_compress.py。脚本不依赖 OpenClaw,只依赖系统里的 ffmpeg 和 ffprobe,可以直接独立运行。
安装技能
在 OpenClaw 中通过 clawhub 安装该技能:
clawhub install zhz-video-compress
安装成功后输出类似:
✔ Installed zhz-video-compress v1.0.0 -> C:\Users\zhang\.openclaw\workspace\skills\zhz-video-compress
安装后技能位于 C:\Users\<用户名>\.openclaw\workspace\skills\zhz-video-compress 目录,其中 scripts/video_compress.py 即为主脚本,SKILL.md 为操作手册。
技能能力
技能支持递归扫描目录或处理单个视频,用 ffmpeg 转 H.265(默认)或 H.264 大幅压缩体积。它的核心价值在于"智能"和"安全"两点:
| 能力 | 说明 |
|---|---|
| 语义化画质档位 | --quality 封装 H265/H264 + CRF,无需了解底层编码参数 |
| 速度档位 | --speed 封装 preset,在速度与体积间取舍 |
| 智能跳过 | 已压缩、文件太小、码率过低,命中任一即跳过 |
| 安全优先 | 先写临时文件校验通过才落盘,失败或无收益保留原片,默认不替换原视频 |
| 分辨率缩放 | --max-height 把 4K 等比降到 1080p 等 |
| 归档整理 | --organize 按拍摄年月归档到 YYYY-MM 子目录 |
| 自定义输出 | --out-dir 输出到指定目录(默认保留原片,输出到同目录 _compressed 文件) |
| 强制重压 | --force 忽略 comment 标志与台账,强制重新压缩 |
| 扩展名 | 支持 15 种常见视频扩展名,可用 --extensions 追加(如 .dav) |
画质与速度档位
压缩必须重新编码视频,技能把底层编码参数封装成语义化档位,无需了解 ffmpeg 选项:
| 档位 | 编码 | CRF | 说明 |
|---|---|---|---|
--quality small |
H265 | 28 | 体积优先,默认最常用 |
--quality balanced |
H265 | 24 | 画质体积平衡 |
--quality smallest |
H265 | 32 | 最小体积 |
--quality best |
H264 | 18 | 最佳画质,兼容性也最好 |
速度档位有 --speed fast(更快,体积略增)、--speed balanced(默认)、--speed slow(更省体积,耗时更长)。高级用户仍可用 --codec / --crf / --preset 直接覆盖档位,但一般无需使用。
智能跳过机制
脚本用三重判定来决定是否跳过某个文件,命中任一即不处理:
- comment 标志:压缩时向文件 metadata 的 comment 字段追加标志(如
zhz-video-compress|v1|h265|crf28|medium|时间戳),原有 comment 内容用;拼接保留,跨目录跨机器都能识别,是最可靠的判定; - 台账记录:在扫描目录维护
.video_compress_ledger.json,记录每个文件的 size + duration 指纹; - 体积与码率过滤:文件小于 10 MB(
--min-size)或码率低于 300 kbps(--skip-below-kbps)跳过。
压缩后若收益不足 5% 自动保留原片(见"安全设计"一节)。
安全设计
压缩必须先转码,脚本先写到临时文件 .vcompress_tmp_*,完成后校验三件事:能否解析、是否含视频流、时长是否一致。校验通过才落盘,失败保留原片。如果压缩收益不足 5%(新文件体积 ≥ 原片的 95%),也保留原片,不做无意义替换。默认保留原片,不会替换原视频,只有显式加 --replace 才会原地覆盖。中途 Ctrl+C 不会损坏原件。
音频方面,音轨为 AAC 或 MP3 时直接复制不转码,其余格式转成 AAC。字幕方面,MP4 中转成 mov_text,MKV 中直接复制。另外要注意,--replace 原地替换时如果源容器与目标不一致(如 .avi 换成 .mp4),原文件会被替换成新扩展名的文件;只有默认(不加 --replace)时原片才始终保留。
3.4 使用命令验证
下面用一个完整场景演示 zhz-video-compress 的使用。假设你有一批手机拍摄的旅行素材放在 D:\Travel 目录下,全是 1080p 或 4K 的原始视频,总共有几十 GB,现在要压缩整理。
第零步:前置检查
先确认 ffmpeg 和 ffprobe 可用:
ffmpeg -version
ffprobe -version
两个命令都能输出版本号才算就绪。如果系统没装 ffmpeg,先安装(Windows 可用 winget install ffmpeg),或用环境变量 FFMPEG_PATH / FFPROBE_PATH 指定可执行文件路径。同时确认目标目录存在、磁盘空间足够(默认保留原片输出时需要约等于源文件大小的临时空间)。
第一步:dry-run 预览
正式压缩前先预览,确认待处理清单和跳过情况:
python video_compress.py "D:\Travel" --dry-run
这一步不会真正转码,只打印出每个文件的分辨率、编码、体积、码率,以及哪些会被压缩、哪些会被跳过、为什么跳过。首行会显示生效的画质档位和速度档位。
第二步:正式压缩
确认无误后正式执行:
python video_compress.py "D:\Travel"
默认使用 H.265 体积优先档位(CRF 28)。脚本递归扫描目录下所有视频,逐个转码。默认保留原片,输出到同目录 *_compressed 文件,不会替换原视频;也可以用 --out-dir 指定输出目录(注意 --out-dir 不能位于扫描目录内部,否则会重复扫描输出文件):
# 输出到指定目录(原片保留不动)
python video_compress.py "D:\Travel" --out-dir "E:\Compressed"
完成后汇总行显示"压缩完成 N | 跳过 M | 无收益 K | 失败 0",并打印总共节省的空间和百分比。
因为 H.265 转码速度约为 H.264 的一半到三分之一,几十 GB 的素材可能需要数小时,建议后台运行并跟踪进度。
第三步:需要更高画质或降分辨率
如果这批素材里有些是重要场景想保留更高画质,可以改用平衡档位;如果 4K 素材太多,可以顺手降到 1080p:
# 画质与体积平衡
python video_compress.py "D:\Travel" --quality balanced
# 4K 降到 1080p,同时按拍摄年月归档
python video_compress.py "D:\Travel" --max-height 1080 --organize
--organize 会把压缩结果按拍摄年月归档到 YYYY-MM/ 子目录,方便后续查找。
第四步:需要原地替换时才用 --replace
默认情况下原片始终保留,不会替换。只有当你确实想用压缩后的文件覆盖原片时,才显式加 --replace:
python video_compress.py "D:\Travel" --replace
注意,--replace 原地替换时如果源容器与目标不一致(如 .avi 转成 .mp4),原文件会被替换成新扩展名的文件,请谨慎使用。
第五步:幂等性验证
再次用相同命令运行一遍,脚本应全部显示"跳过",证明已压缩的文件不会被重复处理:
python video_compress.py "D:\Travel"
这个特性让技能可以安全地反复运行,中途中断后重新执行也不会出错。如果你确实想对已压缩过的文件重新压缩(比如换了更高画质档位),可以加 --force 忽略 comment 标志与台账,强制重压;--force 只会更新 comment 标志,不会重复堆叠。
3.5 实战案例:用一句提示词压缩整理目录
前几节拆解了编码原理和技能能力,这一节回到在OpenClaw真实使用。你根本不用记那些 ffmpeg 参数和脚本命令,只要在 OpenClaw 的 WebChat 里说一句话:
压缩整理以下目录视频 D:\Travel
下面结合这次真实调用,一步步拆开 agent 在背后是怎么按技能执行的,以及每一步背后的原理。
第零步:匹配技能,读取 SKILL.md
agent 收到这句话后,先用「压缩」「整理目录视频」这类触发词匹配到 zhz-video-compress,然后读取它的 SKILL.md。SKILL.md 写明了这个技能的核心纪律:始终先 dry-run 预览,确认无误再实际执行。这背后是批量转码的一个重要工程判断——转码不可逆且耗时数小时,一旦参数搞错(比如误用了 --replace 覆盖原片、或画质档位选错),代价很大。所以"先预览、再执行"被写进了操作手册,agent 会严格照做,而不是直接开跑。
第一步:dry-run 预览,只算不转
agent 按 SKILL.md 先跑预览:
python {baseDir}/scripts/video_compress.py "D:\Travel" --dry-run
这一步对应第 3.3 节的"智能跳过"机制,但它只打印、不转码。脚本递归扫描 D:\Travel,对每个视频用 ffprobe 读元数据(分辨率、编码、体积、码率),然后按三重判定逐条判断:该压、还是跳过、为什么跳过。首行会显示生效的画质档位和速度档位。
这一步的原理价值在于:它把"哪些要压、哪些不用压"在真正动手前就全部摊开。第 3.2 节提到的"压不动"情况(源已经是 H.265、文件太小、码率过低)在这里被提前识别,避免了几十 GB 素材里混着的那些"压了也白压"的文件白白浪费转码时间。
第二步:正式压缩,安全优先
预览确认无误后,agent 执行正式压缩:
python {baseDir}/scripts/video_compress.py "D:\Travel"
默认使用 H.265 体积优先档位(CRF 28)。脚本递归扫描、逐个转码,完成后汇总行显示"压缩完成 N | 跳过 M | 无收益 K | 失败 0",并打印总共节省的空间和百分比。
这一步落地了第 3.2 节讲的"两个工程难点":
- 幂等性:压缩时向文件 metadata 的 comment 字段追加
zhz-video-compress|v1|h265|crf28|medium|时间戳标志,同时在扫描根目录写台账。已经压过的文件,下次直接命中这两个标记被跳过,不会重复转码。 - 安全性:先写到临时文件
.vcompress_tmp_*,转码完成后校验三件事(能否解析、是否含视频流、时长是否一致),通过才落盘;失败或收益不足 5% 一律保留原片。默认不替换原视频,只是另存一个新的*_compressed文件。
所以哪怕中途断了、哪怕有一条转码失败,原片都完好无损,重新执行即可,这就是"安全可反复运行"的含义。
第三步:默认保留原片,需要时才加参数
如果 agent 需要按更具体的需求调整,只需在压缩命令上追加对应参数,原理都封装在语义化档位里、无需碰 ffmpeg:
# 画质与体积平衡
python {baseDir}/scripts/video_compress.py "D:\Travel" --quality balanced
# 4K 降到 1080p,同时按拍摄年月归档到 YYYY-MM/
python {baseDir}/scripts/video_compress.py "D:\Travel" --max-height 1080 --organize
# 输出到指定目录(默认保留原片)
python {baseDir}/scripts/video_compress.py "D:\Travel" --out-dir "E:\Compressed"
# 只有显式要求原地替换时才加 --replace(会覆盖原片)
python {baseDir}/scripts/video_compress.py "D:\Travel" --replace
几点对应关系:--quality balanced 对应 H.265 CRF 24,是画质与体积的折中;--max-height 1080 对应第 3.3 节的分辨率缩放,把 4K 等比降到 1080p;--organize 按拍摄年月归档;--out-dir 指定输出目录、原片始终保留;--replace 是唯一会覆盖原片的开关,默认永远不动原片。如果确实要重压已压缩过的文件,再加 --force。
为什么一句话能反复用:最后是幂等性验证。如果 agent 用相同命令再跑一遍,应该全部显示"跳过",证明已压缩的文件没有被重复处理。这一步正是第 3.2 节那句"批量压缩的两个工程难点"之一的兑现——这个技能可以安全地反复运行,中途中断、换台机器、甚至台账文件丢失(还有 comment 标志兜底),都不会把已经压过的视频再压一遍。
4. 视频转录与总结:zhz-transcript-summarize 技能
4.1 场景描述
你手头有一堆的技术视频。同事发来的架构评审录屏、课程平台的几十集分享、收藏夹里上百个稍后再看。每一段都可能藏着你需要的核心知识。你想要:
- 快速了解每个视频讲了什么,不用逐帧看完
- 抓住其中的核心结论、关键经验和可用方案
- 面对大量同类视频,先扫要点,再决定哪些值得细看
这在日常学习和工作中是非常常见的需求。看完一段 30 分钟的视频需要整整 30 分钟,但读同样内容的要点总结只需要几分钟。面对几十上百个视频,如果都从头看到尾,时间成本根本付不起。
传统做法是自己提取音频、跑语音识别、再手动整理要点。每换一个视频就要重复一遍,视频一多就完全不可行。
zhz-transcript-summarize 技能正是为了解决这些问题而生的。
4.2 技能概述
zhz-transcript-summarize 是一个 OpenClaw 技能,它把"本地转写 + 要点摘要"拆成两个互相独立的阶段:
| 阶段 | 脚本 | 作用 |
|---|---|---|
| 阶段一:转录 | transcribe.py |
音视频转文字,结果按内容哈希缓存 |
| 阶段二:摘要 | summarize.py + render_html.py |
准备摘要输入、渲染 HTML(要点由 AI 生成) |
这两个阶段的解耦是技能最核心的设计。转录稿按文件内容哈希缓存,同一文件只转一次。之后你想换角度重新总结,比如第一次总结"讲了什么",第二次只想"提取行动项",第三次想做会议纪要,都只需要重跑阶段二,完全跳过转录,几秒钟就能出结果。
环境依赖
| 依赖 | 用途 | 版本 |
|---|---|---|
| Python | 运行脚本 | 3.12+ |
| ffmpeg | 提取音频 | 6.1.1 |
| faster-whisper | 语音识别(本地) | 1.2.1(脚本自动安装) |
脚本独立于大模型运行,转录阶段音频永不离开本机,也无需任何 API key。
安装技能
在 OpenClaw 中通过 clawhub 安装该技能:
clawhub install zhz-transcript-summarize
安装成功后输出类似:
✔ Installed zhz-transcript-summarize v1.0.0 -> C:\Users\zhang\skills\zhz-transcript-summarize
4.3 阶段一:转录(缓存命中则跳过)
转录阶段就是把音视频文件转成文字,输出一份带时间戳的转录稿 JSON,并缓存起来。
python {baseDir}/scripts/transcribe.py "D:\podcast\podcast-ep12.mp3" --model small
这条命令内部依次做四件事:提取音频 → 加载模型转录 → 写缓存 → 打印报告。缓存命中时前三步全部跳过,直接跳到第四步。
第一步:提取音频
用 ffmpeg 把音视频统一转成 16kHz 单声道 WAV,输出到临时目录、用完自动清理:
ffmpeg -y -i <源文件> -vn -ac 1 -ar 16000 -c:a pcm_s16le <临时>.wav
-vn 丢掉视频流,-ac 1 单声道,-ar 16000 采样率 16kHz(Whisper 标准输入),-c:a pcm_s16le 无损 PCM。语音识别只关心声音,统一格式保证不同来源文件的输入一致。
第二步:加载模型转录
faster-whisper 加载指定模型,逐段转录,得到带时间戳的 segments 和全文。
--device auto:探测到 CUDA 设备就用 GPU,否则 CPU;CUDA 下优先float16,失败回退int8,CPU 固定int8。vad_filter=True跳过静音段,减少幻听;beam_size=5平衡准确率与速度。- 容错:CUDA 转录失败(如缺少 cublas dll)自动静默回退 CPU,只有 CPU 也失败才报错。用户和 agent 都不用关心这台机器有没有显卡。
第三步:写缓存
按 文件内容 SHA-256 + 模型名 生成缓存键,向 ~/.cache/zhz-transcript/ 写两份文件:
| 文件 | 内容 |
|---|---|
<hash>-<model>.json |
元数据、全文、带时间戳的 segments |
<hash>-<model>.txt |
纯文本全文 |
缓存命中:未加 --force 且 JSON 已存在时,直接读取缓存、打印报告并返回,完全不调用 ffmpeg 和 Whisper。缓存损坏会提示加 --force 重转。文件名或位置变化不影响命中,只有内容真正改变才会生成新哈希——这正是「同一文件重复运行直接命中」的实现基础。
第四步:打印报告
无论缓存命中还是新转录,最后都输出一份报告:
✅ 缓存命中(无需重新转录)
来源: 1027.mp4
时长: 2:00
语言: zh (置信度 1.0)
段落: 39
缓存 JSON: C:\Users\zhang\.cache\zhz-transcript\22351d8fcfd1ce342e2db34b638218293ab14f0254fde9696e32ea3efc5dfcf6-small.json
纯文本: C:\Users\zhang\.cache\zhz-transcript\22351d8fcfd1ce342e2db34b638218293ab14f0254fde9696e32ea3efc5dfcf6-small.txt
时长超过 1 小时显示 h:mm:ss,否则 m:ss。加 --print 可把全文额外打印到 stdout。
日志约定:INFO 走 stdout,错误以 [错误] 前缀走 stderr,失败时退出码为 1。这几行报告也是 agent 判断「这一步成功了吗」的直接依据——段落数、语言、时长是否符合预期,后续 summarize.py 该传哪个 --model 才能命中缓存,全在这里。
缓存键是文件内容的 SHA-256 加上模型名,所以同一文件重复运行会直接命中缓存,除非显式加 --force 强制重新转录。
缓存默认存放在 ~/.cache/zhz-transcript/ 目录(Windows 即 C:\Users\<user>\.cache\zhz-transcript\)。文件改名或移动位置不影响命中,只有内容真正变了(重新编辑或裁剪)才会生成新哈希重新转录。缓存永久保留,可以自己手动清理。
几个常用选项:
| 选项 | 值 | 说明 |
|---|---|---|
--model |
tiny / base(默认)/ small / medium / large-v3 | Whisper 模型大小 |
--lang |
auto(默认)/ zh / en / ... | 语言,auto 为自动检测 |
--force |
无值 | 忽略缓存强制重新转录 |
--device |
auto / cpu / cuda | 计算设备,有 NVIDIA 显卡可用 cuda 加速 |
--print |
无值 | 把转录全文打印到 stdout |
--cache-dir |
路径 | 自定义缓存目录(默认 ~/.cache/zhz-transcript) |
对于 30 分钟的中文音频,small 模型在 CPU 上大约需要 5 到 15 分钟。如果你有 NVIDIA 显卡,加 --device cuda 可以大幅加速。首次运行会自动下载 Whisper 模型到 ~/.cache/huggingface/,脚本已内置 HF 镜像,国内无需额外配置。
4.4 阶段二:摘要
转录完成后,进入摘要阶段。这一步先用 summarize.py 准备摘要输入,再由 AI 生成要点,最后可选用 render_html.py 渲染成可独立打开的 HTML。
第一步:准备摘要输入
python {baseDir}/scripts/summarize.py "D:\podcast\podcast-ep12.mp3" \
--focus "云原生架构选型理由与踩坑经验" \
--audience "开发者" \
--format key_summary \
--length medium \
--lang zh
如果转录时用了非默认模型(如 --model small),这里也要传 --model small 才能精确命中对应缓存,否则会回退到同内容哈希的任一缓存(脚本会给出警告)。
这一步是确定性的准备工作,它本身不做摘要生成,而是在 summaries/<name>/ 目录下产出几个文件:
| 文件 | 说明 |
|---|---|
context.md |
转录稿全文(已按术语表更正,若提供了术语表) |
summary_prompt.md |
模板 + 本次参数(焦点 / 受众 / 长度 / 语言) |
glossary_changes.md |
术语更正记录(仅当提供术语表且有命中) |
timeline.md |
时间轴骨架(超过 20 分钟自动生成) |
subtitles.srt / .vtt |
字幕(仅当加了 --format-sub;基于原始转录稿,不含术语纠错) |
第二步:生成摘要
AI 读取 context.md 全文和 summary_prompt.md 的模板参数,按模板生成摘要,写入 summaries/<name>/summary.md。这一步由当前代理会话的模型完成。
第三步(可选):输出 HTML
python {baseDir}/scripts/render_html.py "summaries/<name>/summary.md" --title "会议记录"
把摘要渲染成同目录同名的 .html,双击即可用浏览器独立打开。它用纯 Python 标准库实现,内联 CSS、无外部依赖,离线可用。常用选项有:--title 指定页面标题(默认取第一个一级标题或文件名)、--out 指定输出路径、--meta 在标题下方加元信息、--lang 设置 HTML 的 lang 属性(默认 zh)。
4.5 实战:用一句提示词总结视频
前面几小节都是手动敲 transcribe.py 和 summarize.py,那是为了看清技能内部的实现。真实使用中你根本不用记这些命令,只要在 OpenClaw 的 WebChat 里发一句话:
请总结视频内容:C:\Users\zhang\Videos\Captures\1027.mp4
剩下的交给 agent。下面结合这次真实调用,一步步拆开 agent 在背后是怎么按技能执行的,以及每一步的原理。
第零步:匹配技能,读取 SKILL.md
agent 收到提示词后,先用「总结视频内容」「总结」这类触发词匹配到 zhz-transcript-summarize,然后读取它的 SKILL.md。SKILL.md 是技能的完整操作手册,写清了两阶段流程、三个脚本的用法、缓存规则、文件结构。agent 不靠临时发挥,而是严格照手册执行。这是 OpenClaw 技能机制的核心:把可复用流程固化成「文档 + 脚本」,agent 只做编排者,把各阶段串起来。
第一步:阶段一,转录
agent 按 SKILL.md 执行 transcribe.py,把视频路径传进去:
python {baseDir}/scripts/transcribe.py "C:\Users\zhang\Videos\Captures\1027.mp4" --model small --lang zh
这一步对应第 4.3 节,脚本内部做了四件事:
- 用 ffmpeg 把视频里的音频轨道抽出来,转成 16kHz 单声道 wav(语音识别的标准输入)。
- 加载 Whisper 模型,逐段转录,得到带时间戳的 segments 和全文。
- 计算文件内容的 SHA-256,连同模型名组成缓存键,把结果(元数据、全文、segments)写入缓存 JSON,再输出一份
.txt。 - 打印来源、时长、语言、段落数等报告信息。
本次视频约 2 分钟,识别出 39 个段落、语言为中文,很快完成。这里有个值得注意的实现细节:脚本会优先尝试 CUDA(GPU),失败时自动回退到 CPU,比如检测到缺少 cublas dll 就会静默降级。鲁棒性被下沉到了脚本里,agent 和用户都不用关心这台机器有没有显卡。
第二步:阶段二,准备摘要输入
转录完成后,agent 继续按 SKILL.md 执行 summarize.py:
python {baseDir}/scripts/summarize.py "C:\Users\zhang\Videos\Captures\1027.mp4" --model small --format key_summary --lang zh
这一步对应第 4.4 节的第一步。注意它本身不生成任何摘要,只做确定性的准备工作:从缓存按内容哈希找到转录稿,在 summaries/1027/ 目录下产出 context.md(转录全文)和 summary_prompt.md(模板 + 本次参数)。脚本仍然是纯本地确定性逻辑,没有大模型参与。
第三步:模型生成摘要
这步才是 AI 真正上场的地方。agent 读取 summaries/1027/context.md 的转录全文,以及 summary_prompt.md 里的模板和参数(焦点、受众、长度、语言),然后由当前会话的模型按 key_summary 模板生成要点摘要,写入 summaries/1027/summary.md。
这里体现了技能设计的第二条原理:确定性的部分交给脚本,理解与提炼的部分交给模型。转写、缓存、文件准备这些机械工作由脚本完成,可复现、可缓存;而「读懂这段家长会讲了什么、抓出三所试点学校和招生人数」这种需要语义理解的事,才交给大模型。
第四步(可选):渲染 HTML
如果想让结果方便转发,agent 可以再执行 render_html.py 把 summary.md 渲染成可双击打开的 HTML,对应第 4.4 节第三步。
为什么同样一句话能反复用:最实用的点在于两阶段解耦。总结完这次视频后,如果你想换个角度,比如在 WebChat 里继续说「只提取行动项,做成会议纪要」,agent 会直接命中第一步已生成的缓存,跳过转录,只重跑阶段二,几秒钟就出结果。转录只做一次,之后每次换焦点、换模板、换长度都近乎零成本。这就是第 4.2 节强调的「两阶段」设计在真实使用中的价值。
5. 视频批量加水印:zhz-video-logo 技能
5.1 场景描述
当你制作了一系列教学视频或产品介绍视频后,通常需要在视频的固定位置加上公司 logo 或水印。这既能标识内容的来源和版权,也能防止被盗用。手动给每个视频加 logo 既费时又容易出错,一旦视频数量多起来,逐条处理几乎不可能完成。
这时你面对的是一个典型的"批量重复劳动"场景。传统做法是用 ffmpeg 的 overlay 滤镜手动写命令,或者自己写 Python 脚本遍历目录调用 ffmpeg。但这样做有几个痛点:要自己处理位置坐标、透明度、尺寸缩放这些参数,要自己判断哪些视频已经加过水印以避免重复叠加,还要担心处理中途失败会不会损坏原文件。对于普通用户来说,门槛不低。
OpenClaw 的 zhz-video-logo 技能正是为解决这些问题而生的。它把 ffmpeg 的底层能力封装成一个易用的命令,你只需要说一句话,就能批量给整个目录的视频加上统一的 logo 或文字水印。
5.2 需求背景
视频加 logo 的需求来自几个真实的业务场景。
第一是版权保护。知识付费课程、企业培训视频、产品宣传片,这些内容投入了大量制作成本,一旦被下载转发,没有水印就无法追溯来源。加上公司 logo 后,即使视频被二次传播,也能标识版权归属。
第二是品牌标识。统一的 logo 让同一系列的视频有统一的视觉识别,观众一眼就能认出这是哪个机构或老师的内容。这在多平台分发时尤其重要,抖音、B 站、YouTube、视频号同时发布,logo 就是你的品牌名片。
第三是防盗用。电商平台、自媒体经常出现盗用他人视频的情况。水印虽然不能完全阻止盗用,但能显著提高盗用成本,让盗用者在裁剪水印时损失画面质量。
这些需求都有一个共同特点:处理的视频往往是"一批",而不是"一个"。一次课程录了 30 集,一次活动拍了 50 条素材,手动逐条加 logo 是不现实的。批量处理能力是这个场景的核心诉求。
5.3 技术原理
加水印的本质,是把一张图片(logo)或一段文字渲染成图片,叠加到视频的每一帧画面上。这个过程在 ffmpeg 里通过 overlay 滤镜完成。
叠加的基本思路很简单:把 logo 图片作为第二个输入,和视频画面按照指定的位置坐标进行像素混合。混合时有两个关键参数。一个是位置,用 overlay=X:Y 指定 logo 左上角在画面中的坐标。比如 overlay=W-w-10:H-h-10 表示放在右下角,其中 W、H 是视频的宽高,w、h 是 logo 的宽高,10 是距离边缘的像素数。另一个是透明度,通过调整 logo 图片的 alpha 通道实现,colorchannelmixer=aa=0.5 就是把透明度设为 50%。
尺寸适配也是常见需求。直接叠加原始尺寸的 logo,在 1080p 视频上合适,在 4K 视频上就显得太小。ffmpeg 可以用 scale2ref 让 logo 按主视频宽度的百分比缩放,这样同一个 logo 在不同分辨率的视频上视觉比例一致。
有一个必须理解的技术约束:加水印必须重新编码视频。它和压缩不同,压缩可以选择 -c copy 直接复制流,但叠加 logo 改变了每一帧的画面内容,所以整段视频都要重新转码一遍,耗时明显长于纯压缩。这也是为什么"批量"处理时需要后台运行、耐心等待。
此外,批量处理还有两个工程上的难点。一是幂等性,也就是避免对已经加过水印的视频重复叠加,否则每跑一次 logo 就叠一层。zhz-video-logo 用两种方式解决:在视频文件的 comment 元数据里写入标志,以及在目录里维护一份台账记录文件指纹。二是安全性,转码中途失败不能损坏原片。zhz-video-logo 的做法是先写临时文件,校验通过后才落盘,而且默认保留原片,不会替换原视频,只有显式加 --replace 才会原地覆盖。
5.4 zhz-video-logo 技能
zhz-video-logo 是一个 OpenClaw 技能,它把上面的 ffmpeg 底层能力封装成一个纯 Python 标准库脚本 video_logo.py。脚本本身不依赖 OpenClaw,只依赖系统里的 ffmpeg 和 ffprobe,文字水印模式额外需要 Pillow。
安装技能
使用前先通过 clawhub 安装该技能:
clawhub install zhz-video-logo
安装成功后输出类似:
✔ Installed zhz-video-logo v1.0.0 -> C:\Users\zhang\.openclaw\workspace\skills\zhz-video-logo
技能会被安装到 OpenClaw 工作区的 skills/zhz-video-logo 目录下,其中 scripts/video_logo.py 即为主脚本,SKILL.md 为操作手册。后续命令中的 {baseDir} 就指向该技能目录。
技能能力
技能支持两种水印来源:
| 水印类型 | 说明 | 示例 |
|---|---|---|
| 图片 logo | PNG/JPG 等图片文件,推荐带透明通道的 PNG | --logo "D:\assets\company.png" |
| 文字水印 | 用 Pillow 渲染成透明 PNG 再叠加,支持中文 | --text "张老师课程" |
位置支持 9 个预设方位(四角、四边、居中)和自定义像素坐标,透明度 0 到 100% 可调,水印尺寸可以固定像素宽度,也可以按视频宽度的百分比缩放,随分辨率自适应。
核心命令
一个最简单的图片 logo 加水印命令:
python video_logo.py "D:\Videos" --logo "D:\assets\company.png" --position bottomright --opacity 70
常用的位置与透明度参数:
| 场景 | 命令片段 |
|---|---|
| 右下角(默认,最常用) | --position bottomright |
| 左上角 | --position topleft |
| 居中水印(半透明覆盖) | --position center --opacity 25 |
| 精确像素坐标 | --position 100,50 |
| 半透明水印 | --opacity 50 |
| 固定宽度缩放 | --logo-width 160 |
| 随分辨率自适应 | --logo-scale 12(宽=视频宽的 12%) |
文字水印用 --text 指定内容,支持中文字体和字号颜色:
python video_logo.py "D:\Videos" --text "内部资料" --position center --opacity 25
文字水印还可以指定字体、字号、颜色,比如 --font C:/Windows/Fonts/simhei.ttf --font-size 64 --font-color yellow。
画质档位
加水印必须重新编码,技能把编码参数封装成语义化的画质档位:
| 档位 | 编码 | 说明 |
|---|---|---|
--quality best |
H264 | 最佳画质 |
--quality balanced |
H264 | 默认平衡,兼容性最好 |
--quality small |
H265 | 体积优先 |
--quality smallest |
H265 | 最小体积 |
关键设计
技能有两个非常好的设计。
第一是幂等性:已经加过水印的视频会自动跳过,不会重复叠加。它靠两种方式判定,一是在文件 metadata 的 comment 字段写入标志,二是在目录里维护 .video_logo_ledger.json 台账记录文件指纹。
第二是安全性:先写临时文件,校验通过(能解析、含视频流、时长一致)后才落盘,中途失败或 Ctrl+C 都不会损坏原件。默认保留原片,不会替换原视频;只有显式加 --replace 才会原地覆盖。
5.5 实战案例
前面几节演示的都是命令行用法,你需要记住 video_logo.py 的参数名、位置选项、透明度取值范围。对熟练用户来说没问题,但对只想"加个水印"的普通用户,这仍然是一道门槛。OpenClaw 的价值就在于,你完全不需要记住这些命令,只需要在 Web Chat 里说一句话。
下面用一个完整场景演示。假设你有一套课程视频放在 D:\Courses 目录下,想给全部视频右下角加上"词元创想"四个字的文字水印。直接在 Web Chat 里发送:
请将以下课程加logo"词元创想" D:\Courses
就这么一句话,不用提参数,不用写命令。OpenClaw 收到后会自动完成下面几件事。
第零步:匹配技能,读取 SKILL.md
agent 收到这句话后,第一步不是直接动手,而是先判断这属于哪类任务。"加 logo""水印"是批量处理视频的典型需求,agent 会匹配到 zhz-video-logo 这个技能,并读取它的 SKILL.md 说明文件,搞清楚这个技能能做什么、有哪些参数、正确的调用方式。只有读懂了技能的使用说明,后续的命令才会发对。这一步是 OpenClaw 技能机制的核心:先匹配技能、读文档,再执行,而不是凭印象瞎猜。
第一步:理解意图,dry-run 预览
agent 会先理解这句话:加 logo 用的是文字"词元创想",目标目录是 D:\Courses。它不会直接开跑,而是先执行 dry-run 预览,把待处理清单反馈给你,包括目录下有多少个视频、每个视频的分辨率、编码、体积、时长,以及将要生效的水印内容、位置和透明度。你确认无误后,它才进入正式处理。
第二步:后台执行,汇报进度
确认后,agent 把正式加水印的任务放到后台运行,边处理边回报进度。因为加水印必须重新编码,视频多的时候耗时较长,agent 不会空转傻等,而是用 exec 起后台任务,通过 process poll 跟进,处理完一批就汇报一次。全部完成后,汇总行显示"完成 N | 跳过 M | 失败 0"。
第三步:自动验证效果
退出码为 0 不代表水印真的可见。agent 会抽一个输出文件截取一帧,确认"词元创想"四个字的位置、大小和透明度符合预期,再把验证结果告诉你。如果位置或透明度不对,它会调整参数重跑。
第四步:幂等性兜底
如果因为中途中断需要重跑,你只需要把同一句话再说一遍。技能会自动跳过已经加过水印的文件,不会重复叠加,所以反复运行、中断重启都很安全。
整个过程你只做两件事:发一句话、确认一下结果。剩下的意图理解、dry-run 预览、后台转码、截帧验证、幂等判断,全部由 OpenClaw 和 zhz-video-logo 技能自动完成。这也是技能相比裸 ffmpeg 命令最大的价值:把"批量加水印"从一个需要记忆参数的工程操作,变成一句人话就能完成的事情。
如果你有明确的输出要求,也可以在这句话里直接说,比如"输出到 E 盘 Branded 目录",agent 会对应加上 --out-dir "E:\Branded"。默认情况下技能保留原片、不会替换原视频,输出文件在同目录下、文件名追加 _watermark 后缀。只有当你想覆盖原片时,才需要显式说明用 --replace;如果内容偏版权保护、想在体积上兼顾瘦身,也可以让 agent 用 --quality small 换 H265 编码。
6. 视频双语字幕:zhz-subtitle 技能
6.1 为什么需要双语字幕
在全球化的技术交流中,双语字幕的需求越来越普遍。你录制了一段中文技术演讲,想发到 YouTube 让海外开发者也能观看;你参加了一场英文线上会议,想要配上中文字幕方便团队回顾;你在做跨境教育内容,需要让不同语言的观众都能理解。这些场景都需要双语字幕。
手动制作双语字幕是一项极其耗时的工作。你需要先听写原文,再逐句翻译,然后精确对齐每一句话的时间轴。一段 30 分钟的视频,人工制作双语字幕通常需要 3 到 5 个小时。而 OpenClaw 的 zhz-subtitle 技能可以把这个过程完全自动化,你只需要告诉它视频文件在哪里,剩下的事情它全部搞定。
6.2 技能概述与安装
zhz-subtitle 是一个 OpenClaw 技能,它把前面几节介绍的 ffmpeg(音频提取)和 Whisper(语音转文字)串联起来,再加上 AI 翻译能力,实现了从视频到双语 SRT 字幕的全自动化流程。
环境依赖
| 依赖 | 用途 | 安装方式 |
|---|---|---|
| Python 3.12+ | 运行脚本 | 系统自带 |
| ffmpeg | 音频提取 | winget install ffmpeg 或 brew install ffmpeg |
| faster-whisper | 语音识别 | pip install faster-whisper(脚本自动安装) |
安装技能
使用前先通过 clawhub 安装技能本体:
clawhub install zhz-subtitle
安装成功后输出类似:
✔ Installed zhz-subtitle v1.0.0 -> C:\Users\zhang\.openclaw\workspace\skills\zhz-subtitle
技能会被安装到 OpenClaw 工作区的 skills/zhz-subtitle 目录,后续 6.3 节命令中的 {baseDir}/scripts/ 就指向该目录下的脚本。
安装完成后,在技能被调用时自动创建以下文件结构:
输入文件:{name}.{ext}
工作目录:subtitles/{name}/(中间文件)
最终输出:subtitles/{name}.srt(双语字幕)
工作目录中的中间文件包括:
| 文件 | 说明 |
|---|---|
{name}.mp3 |
从视频中提取的音频 |
{name}.transcript.json |
转录结果(含时间戳) |
{name}_translated.json |
翻译后的 JSON 段落 |
{name}.en.srt |
英文字幕文件 |
{name}.chs.srt |
中文字幕文件 |
{name}.srt |
最终双语字幕文件 |
6.3 八步自动化工作流
zhz-subtitle 的完整工作流程分为 8 个步骤,每一步都有明确的完成标准。下面详细介绍每一步做了什么。

第一步:环境检查与验证
技能首先验证输入文件是否存在,检查 ffmpeg 和 faster-whisper 是否可用,然后创建工作目录 subtitles/{name}/。这是整个流程的安全阀,确保后续步骤不会因为缺少依赖而中途失败。
第二步:提取音频
如果输入是视频文件(MP4、MKV 等),用 ffmpeg 提取音频为 MP3 格式。如果输入本身就是音频文件(MP3、WAV 等),这一步会自动跳过。
python {baseDir}/scripts/extract_audio.py "<视频路径>" "subtitles/{name}/{name}.mp3"
第三步:语音转文字
使用 faster-whisper 转录音频,生成带精确时间戳的 JSON 数据和对应语言的 SRT 文件。这一步会自动检测音频的语言(中文或英文),后续步骤会根据检测结果决定翻译方向。
python {baseDir}/scripts/transcribe.py "subtitles/{name}/{name}.mp3" [model_size] [language]
可用的模型参数包括 tiny、base(默认)、small、medium、large-v3。对于中文内容,建议使用 small 或更大的模型以获得更好的识别准确率。
第四步:翻译
AI 大模型逐段翻译转录文字。翻译方向由第三步的语言检测结果决定:原文为中文则翻译成英文,原文为英文则翻译成中文。
具体执行方式是:Agent 读取转录 JSON,逐段翻译并保持相同的 JSON 结构(start、end、text 字段),将翻译结果写入 Python 脚本文件 subtitles/{name}/{name}_translate.py,再执行该脚本生成翻译 JSON。
这里有一个必须遵守的实现细节:翻译 JSON 必须通过 Python 脚本生成。因为翻译文本常含中文引号("")、书名号等标点,直接写 JSON 文件会导致解析失败,内联 Python 代码又会因 shell 转义崩溃。正确做法是把 json.dump() 调用写入 .py 文件再执行,脚本模板如下:
import json
data = {
"language": "zh", # 或 "en"
"duration": <音频时长>,
"segments": [
{"start": 0.0, "end": 5.0, "text": "翻译文本"},
# ... 更多段落
]
}
with open(r"subtitles/{name}/{name}_translated.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"翻译完成:{len(data['segments'])} 段")
翻译过程遵循以下原则:保持原文语义和语气、字幕翻译应简洁避免过长、保留专有名词(人名、地名)、教育内容保持术语准确、纯数字段落不翻译。
对于长视频(段落数超过 50 条),技能会自动分批翻译(每批 30 到 50 条),最后合并为完整的翻译结果,避免单次处理过多内容导致遗漏。
第五步:生成翻译字幕
把翻译后的 JSON 数据转换为标准 SRT 格式。如果翻译成英文,生成 .en.srt;如果翻译成中文,生成 .chs.srt。
第六步:合并双语字幕
把原文 SRT 和翻译 SRT 合并为一个双语 SRT 文件。每条字幕显示两行,默认英文在前、中文在后。合并时会自动校验条目数,如果中英文条目数不一致会输出警告。
python {baseDir}/scripts/merge_srt.py "subtitles/{name}/{name}.en.srt" "subtitles/{name}/{name}.chs.srt" "subtitles/{name}.srt" [translated_first]
第七步:验证
自动检查最终字幕文件的质量:SRT 格式是否正确、时间戳是否有重叠、是否同时包含中英文、条目数是否一致。如果发现问题会尝试修复,修复后重新验证。
python {baseDir}/scripts/verify_srt.py "subtitles/{name}.srt"
第八步:完成报告
输出最终结果:
✅ 双语字幕生成完成!
文件:subtitles/{name}.srt
条目:{count} 条双语字幕
语言:中文 ↔ English
时长:{duration}
原文语言:{original_lang}
6.4 实战:一句提示词配双语字幕
前面 6.3 把 zhz-subtitle 的八步工作流拆开讲了一遍,那是为了看清内部每一步做了什么。回到真实使用,你根本不用关心这些命令和脚本,只要在 OpenClaw 的 WebChat 里发一句话:
帮我给这个视频配双语字幕:D:\Videos\tech_talk.mp4
剩下的事全部交给 agent。下面结合这句话,一步步拆开 agent 在背后是怎么按技能执行的,以及每一步背后的原理。
第零步:匹配技能,读取 SKILL.md
agent 收到提示词后,先用「字幕」「双语字幕」这类触发词匹配到 zhz-subtitle,然后读取它的 SKILL.md。SKILL.md 是这个技能的完整操作手册,写明了八步工作流、每一步的完成标准、以及几个必须遵守的实现细节。agent 不靠临时发挥,而是照着手册一步步执行。这就是 OpenClaw 技能机制的核心:把「视频 → 双语字幕」这条复杂链路固化成可复用的文档加脚本,agent 只做编排者。
第一、二步:环境检查,提取音频
agent 先验证输入文件存在、ffmpeg 和 faster-whisper 可用,然后创建工作目录 subtitles/tech_talk/。因为输入是 MP4 视频,agent 用 ffmpeg 把它抽成音频:
python {baseDir}/scripts/extract_audio.py "D:\Videos\tech_talk.mp4" "subtitles/tech_talk/tech_talk.mp3"
这一步的原理很简单:语音识别只关心声音,视频里的画面信息对 Whisper 没有用处,反而会白白增加解码负担。所以先把音频轨道单独提出来,后续转录、翻译、合并全部在这份音频上工作,视频文件本身全程不动。
第三步:语音转文字,语言检测定方向
接着 agent 用 faster-whisper 把音频转成带时间戳的转录 JSON:
python {baseDir}/scripts/transcribe.py "subtitles/tech_talk/tech_talk.mp3" small
这一步对应 6.3 的第三步,同时产出一份对应原文语言的 SRT(中文原文就生成 .chs.srt)。这里有个关键的自动化设计:Whisper 会自动检测语言,检测结果决定后续的翻译方向。原文是中文,就翻译成英文;原文是英文,就翻译成中文。用户从头到尾不需要告诉 agent「这是中文视频」,方向由检测结果自动决定。
第四步:AI 逐段翻译,一个必须遵守的实现细节
这是整个流程里 AI 真正上场的环节。agent 读取转录 JSON,逐段把中文翻译成英文,保持相同的 start / end / text 结构,让译文和原文逐条对齐。
这里藏着技能里一个很讲究的工程细节:翻译结果必须通过 Python 脚本生成,而不是直接写 JSON 文件。原因是翻译文本里常带中文引号「」「」、书名号《》等标点,直接写 JSON 会因为这些标点导致解析失败;如果用 exec 内联 Python 代码,又会因 shell 转义而崩溃。正确做法是把 json.dump() 调用写进一个 .py 文件再执行,让 Python 自己处理所有编码和转义。
另外还有两条翻译纪律:
- 分批翻译:段落超过 50 条时,拆成每批 30 到 50 条逐批翻译,最后合并。避免一次性塞进过长上下文导致遗漏或出错。
- 纯数字不翻译:遇到「1」「1-20」这类纯数字段落,译文保持原文不变,防止模型把数字翻成没意义的内容。
翻译原则还包括保持语义语气、字幕措辞简洁避免过长、保留人名地名专有名词、技术术语准确(比如「容器编排」翻成 Container Orchestration 而不是字面直译)。
第五、六步:生成译文字幕,合并双语
翻译完成后,agent 把译文 JSON 转成对应的英文 SRT(.en.srt),再把原文 SRT 和译文 SRT 合并:
python {baseDir}/scripts/merge_srt.py "subtitles/tech_talk/tech_talk.en.srt" \
"subtitles/tech_talk/tech_talk.chs.srt" "subtitles/tech_talk.srt"
合并默认英文在上、中文在下,每条字幕两行。合并时会自动校验中英文条目数,不一致就输出警告,避免出现「某一句只有英文没有中文」的错位。
第七步:验证,第八步:完成报告
最后 agent 跑一遍验证脚本,检查 SRT 格式、时间戳是否重叠、是否同时包含中英文、条目数是否一致,有问题就修复后重验。通过后输出完成报告,告诉你最终文件路径 subtitles/tech_talk.srt、条目数、语言和时长。
为什么中途改需求近乎零成本:这背后是技能的分阶段文件结构。整个过程会留下音频、转录 JSON、译文 JSON、单语 SRT 等一系列中间文件。如果你想调整显示顺序,比如在 WebChat 里继续说「重新生成字幕,中文排在前面」,agent 根本不用重新转录、重新翻译,直接从缓存好的单语 SRT 重新合并一次,几秒钟就能得到新结果。转录和翻译这类重活只做一次,之后的调整都只是在成品文件上做轻量操作。
总结:zhz-subtitle 把「配双语字幕」这条原本要人工花 3 到 5 小时的链路,拆成了「音频提取 → 语音转文字 → AI 翻译 → 生成字幕 → 合并 → 验证」八个有明确完成标准的步骤,由 agent 照着 SKILL.md 自动编排。
核心设计有三点:一是语言检测自动决定翻译方向,用户无需说明;二是翻译结果用 Python 脚本生成 JSON,绕开中文标点和 shell 转义的坑;三是中间文件全程留存,让重跑、改顺序这类调整只做轻量操作。用户要做的,只有那句「帮我给这个视频配双语字幕」。
7. 总结与进阶
7.1 本章核心知识回顾
| 知识点 | 关键内容 | 常用命令/参数 |
|---|---|---|
| ffmpeg 基础 | 开源音视频处理工具,命令行驱动 | ffmpeg -i、ffprobe |
| 编码与容器 | 编码是压缩算法,容器是文件外壳 | H.264、H.265、MP4、MKV |
| 视频压缩 | zhz-video-compress 技能封装 CRF 与 preset,H265 默认体积优先 | --quality、--speed、--max-height |
| 批量压缩 | 递归扫描目录,智能跳过已压缩/小文件 | comment 标志 + 台账 + 编码判断 |
| Whisper | OpenAI 开源语音识别模型,支持 99 种语言 | faster-whisper、5 种模型大小 |
| 语音转录与总结 | zhz-transcript-summarize 技能两阶段:内容哈希缓存 + 模板化摘要 | transcribe.py、summarize.py、--focus、--glossary |
| 批量加水印 | zhz-video-logo 技能封装 overlay 滤镜,图片/文字水印均可 | --logo、--text、--position |
| 水印安全与幂等 | comment 标志 + 台账防重复,临时文件校验后落盘,默认保留原片 | --dry-run、--force、--replace |
| 双语字幕 | zhz-subtitle 技能自动化 8 步流程 | Whisper 转录 + 大模型翻译 + SRT 合并 |
7.2 工作流组合
ffmpeg、Whisper 和 AI 大模型可以灵活组合,构建出更多实用的音视频处理工作流。以下是几种常见的组合方式:
工作流一:视频压缩 + 转录 + 字幕
适合处理自己录制的大量教学视频。先批量压缩节省存储空间,再转录内容建立可搜索的文字索引,最后生成字幕方便观众观看。
原始视频 → ffmpeg 压缩 → 压缩视频存储
↓
ffmpeg 提取音频 → Whisper 转录 → AI 总结
↓
zhz-subtitle → 双语字幕
工作流二:批量加 logo + 压缩 + 发布
适合视频创作者在发布前的最后加工。统一加上品牌 logo,压缩到适合网络传播的大小,然后上传到视频平台。
原始视频 → 批量加 logo → ffmpeg 压缩 → 上传发布
工作流三:会议录像 → 会议纪要
适合工作会议和培训录像。先转录成文字,再由 AI 提取会议纪要,包括决议事项、行动项和责任人。
会议录像 → ffmpeg 提取音频 → Whisper 转录 → AI 生成会议纪要
这些工作流的核心思路都是一样的:用 ffmpeg 处理音视频格式,用 Whisper 把声音变成文字,用大语言模型理解和加工文字内容。掌握了这三个工具,你就拥有了一个完整的音视频处理工具箱。
7.3 课后练习
练习 1:视频压缩实战
找一段你自己录制的视频(手机拍摄或屏幕录制均可),使用 zhz-video-compress 技能将它压缩。先用 dry-run 预览,再正式执行,记录压缩前后的文件大小、分辨率和码率,对比画面质量是否有明显损失。尝试分别使用 --quality balanced 和 --quality smallest 档位,比较两者的文件大小和画质差异。
练习 2:播客转录与总结
找一段 10 分钟以上的中文播客或演讲视频,使用 zhz-transcript-summarize 技能先转录、再总结。先用 transcribe.py 转录并缓存,再用 summarize.py 生成要点摘要。试着换一个 --focus 重新总结一次,观察是否跳过了转录阶段。如果源内容有术语或英文单词,准备一份 glossary.txt 术语表,对比更正前后的摘要差异。
练习 3:批量加 logo
准备 3 到 5 个短视频和一张 logo 图片,使用 zhz-video-logo 技能,给所有视频统一加上 logo。要求 logo 显示在右下角,宽度 100 像素,透明度 50%。先用 dry-run 预览,再正式执行,最后查看验证每个视频的输出效果是否正确。
练习 4:双语字幕生成(进阶)
使用 zhz-subtitle 技能,给一段 5 到 10 分钟的中文视频生成双语字幕。用文本编辑器打开生成的 SRT 文件,检查时间戳是否准确、翻译是否合理。把 SRT 文件和视频放在同一目录下,用播放器加载字幕验证显示效果。
本文为《OpenClaw 实战指南》系列第 15 篇。