FFmpeg 视频编辑器
使用 ffmpeg 和 fftools.py 助手脚本,在终端中编辑视频、音频和图像。
CLI 工具
所有操作都通过助手脚本进行。脚本位于仓库克隆目录的相对路径,或:
SCRIPT="~/.claude/skills/ffmpeg/scripts/fftools.py"
所有输出均为 JSON 格式。
命令参考
# INFO — 获取文件详情(时长、分辨率、编码、大小)
python3 $SCRIPT info input.mp4
# CUT — 提取片段
python3 $SCRIPT cut input.mp4 output.mp4 --start 00:01:30 --end 00:02:45
python3 $SCRIPT cut input.mp4 output.mp4 --start 00:01:30 --duration 30
# MERGE — 拼接多个视频
python3 $SCRIPT merge video1.mp4 video2.mp4 video3.mp4 -o merged.mp4
python3 $SCRIPT merge video1.mp4 video2.mp4 -o merged.mp4 --reencode # 不同编码
# EXTRACT AUDIO — 提取音频轨道
python3 $SCRIPT extract-audio input.mp4 output.mp3
python3 $SCRIPT extract-audio input.mp4 output.opus --bitrate 128k
# SUBTITLES — 将字幕烧录到视频中
python3 $SCRIPT subtitles input.mp4 output.mp4 --srt subs.srt
# RESIZE — 更改分辨率
python3 $SCRIPT resize input.mp4 output.mp4 --width 1280 --height 720
python3 $SCRIPT resize input.mp4 output.mp4 --width 1920 --height -1 # 自动高度
# GIF — 视频转动态 GIF(两遍编码,高质量)
python3 $SCRIPT gif input.mp4 output.gif --fps 15 --width 480
python3 $SCRIPT gif input.mp4 output.gif --start 00:00:05 --duration 3
# THUMBNAIL — 提取单帧
python3 $SCRIPT thumbnail input.mp4 thumb.jpg --time 00:00:30
# THUMBNAILS — 提取 N 张均匀分布的帧
python3 $SCRIPT thumbnails input.mp4 --count 10 --output-dir ./thumbs/
# COMPRESS — 减小文件大小
python3 $SCRIPT compress input.mp4 output.mp4 --crf 28 --preset medium
python3 $SCRIPT compress input.mp4 small.mp4 --crf 32 --preset fast # 激进压缩
# SPEED — 更改播放速度
python3 $SCRIPT speed input.mp4 fast.mp4 --factor 2.0 # 2 倍速
python3 $SCRIPT speed input.mp4 slow.mp4 --factor 0.5 # 半速(慢动作)
# WATERMARK — 添加图片水印
python3 $SCRIPT watermark input.mp4 output.mp4 --watermark logo.png --position bottom-right
# TEXT — 烧录文字叠加
python3 $SCRIPT text input.mp4 output.mp4 --text "第1章" --position center --size 72 --border
python3 $SCRIPT text input.mp4 output.mp4 --text "促销!" --position top-left --start 5 --end 15
# CONVERT — 转换格式
python3 $SCRIPT convert input.avi output.mp4
python3 $SCRIPT convert input.mp4 output.webm --video-codec libvpx-vp9
# FRAMES — 提取帧为图片
python3 $SCRIPT frames input.mp4 --output-dir ./frames/
python3 $SCRIPT frames input.mp4 --output-dir ./frames/ --every 30 # 每 30 帧提取一帧
# AUDIO REPLACE — 替换音频轨道
python3 $SCRIPT audio-replace input.mp4 output.mp4 --audio music.mp3
# VOLUME — 调整音频音量
python3 $SCRIPT volume input.mp4 output.mp4 --level 2.0 # 音量加倍
python3 $SCRIPT volume input.mp4 output.mp4 --level 0.5 # 音量减半
python3 $SCRIPT volume input.mp4 output.mp4 --level 10dB # 提高 10 分贝
# FADE — 添加淡入/淡出效果
python3 $SCRIPT fade input.mp4 output.mp4 --fade-in 2 --fade-out 3
# STABILIZE — 修复抖动视频(需要 vidstab 滤镜)
python3 $SCRIPT stabilize input.mp4 output.mp4 --shakiness 7 --smoothing 15
# TRANSCRIBE — 语音转文字,带说话人标签(离线;请参阅“转写与转录”部分)
python3 $SCRIPT transcribe meeting.mp4 # 生成 meeting.json/.srt/.txt
python3 $SCRIPT transcribe meeting.mp4 --speakers 3 # 指定说话人数
python3 $SCRIPT transcribe meeting.mp4 --no-diarize # 仅转录,不分离说话人
转写与转录分析——理解视频中说的内容
使用 transcribe 命令,将会议录音、采访或任何语音视频/音频转换为带说话人标签和时间戳的转录稿。这是回答“讨论了什么?”、“谁说了什么?”、“总结会议”或“查找他们谈到 X 的地方”等问题的工具。
该功能完全本地和离线运行——音频不会离开本机,无需云 API。底层技术:使用 WhisperX (large-v3) 进行转录并生成字级时间戳,使用 sherpa-onnx 进行说话人分离(无 token,开放 ONNX 模型)。
一次性设置(需要网络一次)
运行 /setup-transcribe 斜杠命令,或直接:
bash ~/.claude/skills/ffmpeg/scripts/install-transcribe.sh
默认情况下,脚本会从 GitHub 发布版本中获取预构建的捆绑包(速度快:无模型限制,无需 torch 构建),并完全离线安装;如果不可用(发布版本缺失或平台不匹配),则会自动回退到从头构建。它会创建一个隔离的 Python 3.12 虚拟环境(通过 uv)并下载所有模型;之后 transcribe 命令不需要网络。如果命令报告虚拟环境丢失,请运行此脚本完成设置。
如果需要,可以强制使用特定模式:
bash install-transcribe.sh --release # 仅使用预构建的发布捆绑包
bash install-transcribe.sh --build # 仅从头构建(需要 HF + PyPI)
HF_TOKEN=hf_xxx bash install-transcribe.sh --build # 同时启用 --diarizer pyannote
离线环境/无法访问 HuggingFace? 在一台有网络的机器上构建一个自包含的捆绑包,将其托管在任何位置,然后从该位置安装,无需 HF/PyPI 访问:
# 在已经运行过 install-transcribe.sh 的机器上:
bash ~/.claude/skills/ffmpeg/scripts/make-bundle.sh ffmpeg-transcribe-bundle.tar.gz
该捆绑包包含所有代码、模型、模型缓存和 Python wheels。如果超出 2GB,会自动分割为 <name>.part-aa、<name>.part-ab 等(每个 <2GB),以适应托管/上传限制。然后,在目标机器上(仅需 uv、ffmpeg 和 python3.12):
# 单文件捆绑包:
bash install-transcribe.sh --bundle https://your.server/ffmpeg-transcribe-bundle.tar.gz
# 分割捆绑包——按顺序传递各部分(会自动拼接):
bash install-transcribe.sh --bundle \
https://your.server/ffmpeg-transcribe-bundle.tar.gz.part-aa \
https://your.server/ffmpeg-transcribe-bundle.tar.gz.part-ab
(手动重新拼接:cat ffmpeg-transcribe-bundle.tar.gz.part-* > ffmpeg-transcribe-bundle.tar.gz)。
使用方法
# 完整转录 + 说话人标签(生成 meeting.json、meeting.srt、meeting.txt)
python3 $SCRIPT transcribe meeting.mp4
# 选项
python3 $SCRIPT transcribe interview.mp4 --speakers 2 # 已知说话人数 → 更高精度
python3 $SCRIPT transcribe call.m4a --language en # 强制语言(跳过自动检测)
python3 $SCRIPT transcribe lecture.mp4 --format txt # 仅写入 .txt
python3 $SCRIPT transcribe long.mp4 --model medium # 更快,精度稍低
python3 $SCRIPT transcribe q4.mp4 --diarizer pyannote # 更高质量的分离器(需要 HF token)
python3 $SCRIPT transcribe notes.mp4 --no-diarize # 仅转录,不分离说话人
python3 $SCRIPT transcribe raw.wav -o ./out/session # 自定义输出基础路径
输出格式
.txt— 人类可读,按说话人话轮分组。阅读此文件以理解内容:[00:03:12] SPEAKER_01: ....srt— 带说话人标签的字幕,可用subtitles命令烧录回视频.json— 完整结构化数据:每个片段和单词都带有开始/结束时间和说话人,用于程序化分析(搜索、时间线、带时间戳的引用)
会议分析工作流程
# 1. 转录并添加说话人标签
python3 $SCRIPT transcribe meeting.mp4
# 2. 阅读转录稿以分析内容
# (使用 Read 工具打开 meeting.txt,或解析 meeting.json 获取时间戳)
# 3. 接下来可以进行总结、提取行动项、查找谁说了什么,
# 或跳转到某个时刻:将 JSON 时间戳与 cut/thumbnail 命令配合使用。
python3 $SCRIPT cut meeting.mp4 clip.mp4 --start 00:12:30 --end 00:14:00
注意事项:
- 转录在 CPU 上运行(CTranslate2 在 Apple Silicon 上没有 GPU 路径),因此 large-v3 大约是 1–2 倍实时速度。一小时的会议大约需要 30–60 分钟处理——适合后台运行。使用
--model medium或distil-large-v3可提高速度。 - 传递
--speakers N(当知道说话人数时)可以显著改善说话人分离效果。
标准工作流程
步骤 1 — 分析输入
始终先获取文件信息:
python3 $SCRIPT info input.mp4
这将告诉你时长、分辨率、编码和文件大小。利用这些信息做出关于输出设置的明智决策。
步骤 2 — 执行操作
使用相应的命令。对于复杂编辑,可以链式执行多个操作——将一个操作的输出作为下一个的输入。
步骤 3 — 验证结果
任何操作后,检查输出以确认工作正常:
python3 $SCRIPT info output.mp4
步骤 4 — 展示结果
使用 Read 工具显示图像(缩略图、帧)。对于视频,告知用户输出路径和文件大小。
原始 ffmpeg — 用于高级操作
当助手脚本无法满足你的用例时,可以直接使用 ffmpeg:
# 画中画
ffmpeg -y -i main.mp4 -i overlay.mp4 \
-filter_complex "[1:v]scale=320:-1[pip];[0:v][pip]overlay=W-w-10:H-h-10" \
-c:v libx264 -c:a copy output.mp4
# 并排比较
ffmpeg -y -i left.mp4 -i right.mp4 \
-filter_complex "[0:v]pad=iw*2:ih[bg];[bg][1:v]overlay=W/2:0" \
-c:v libx264 output.mp4
# 网格/马赛克(2x2)
ffmpeg -y -i a.mp4 -i b.mp4 -i c.mp4 -i d.mp4 \
-filter_complex "[0:v]scale=640:360[v0];[1:v]scale=640:360[v1];
[2:v]scale=640:360[v2];[3:v]scale=640:360[v3];
[v0][v1]hstack[top];[v2][v3]hstack[bot];[top][bot]vstack" \
-c:v libx264 grid.mp4
# 视频倒放
ffmpeg -y -i input.mp4 -vf reverse -af areverse reversed.mp4
# 提取特定音频通道
ffmpeg -y -i input.mp4 -af "pan=mono|c0=FL" left_channel.wav
# 降噪
ffmpeg -y -i input.mp4 -af "afftdn=nf=-25" denoised.mp4
# 色彩校正(亮度、对比度、饱和度)
ffmpeg -y -i input.mp4 -vf "eq=brightness=0.1:contrast=1.2:saturation=1.3" corrected.mp4
# 色度键(绿幕去除)
ffmpeg -y -i greenscreen.mp4 -i background.mp4 \
-filter_complex "[0:v]chromakey=0x00FF00:0.3:0.1[fg];[1:v][fg]overlay" \
-c:v libx264 composited.mp4
# 从图像序列创建延时摄影
ffmpeg -y -framerate 30 -i frame_%04d.jpg -c:v libx264 -pix_fmt yuv420p timelapse.mp4
# 从单张图片+音频创建视频
ffmpeg -y -loop 1 -i cover.jpg -i audio.mp3 -c:v libx264 -tune stillimage \
-c:a aac -shortest output.mp4
# 两个视频之间的交叉淡入淡出(1 秒)
ffmpeg -y -i first.mp4 -i second.mp4 \
-filter_complex "xfade=transition=fade:duration=1:offset=FIRST_DURATION_MINUS_1" \
-c:v libx264 crossfade.mp4
CRF 质量指南
| CRF | 质量 | 用途 |
|---|---|---|
| 18 | 视觉无损 | 存档、专业编辑 |
| 23 | 高质量 | ffmpeg 默认值,适合大多数用途 |
| 28 | 良好 | 推荐用于分享,文件较小 |
| 32 | 可接受 | 社交媒体,激进压缩 |
| 38+ | 低质量 | 预览、缩略图 |
CRF 越低 = 文件越大,质量越好。每增加 6,文件大小大约减半。
格式快速参考
| 容器 | 视频编码 | 音频编码 | 用途 |
|---|---|---|---|
.mp4 | H.264 (libx264) | AAC | 通用兼容性 |
.webm | VP9 (libvpx-vp9) | Opus | 网络,较小文件 |
.mkv | H.265 (libx265) | Opus | 最大压缩 |
.mov | ProRes | PCM | 专业编辑 |
.gif | — | — | 动画,无音频 |
错误处理
- "No such file" — 检查输入路径,使用绝对路径
- "Unknown encoder" — 编码器未编译。检查
ffmpeg -encoders - "Permission denied" — 输出路径不可写
- "Avi header too large" — 输入文件损坏,尝试在输入前添加
-fflags +genpts - Timeout — 视频太长。增加超时时间或使用
--preset ultrafast - Out of memory — 先降低分辨率,然后再处理