视频剪切与取帧(ffmpeg)
对视频执行多种操作,由你(AI 智能体)调用按系统自选的两个脚本之一完成,逻辑写在脚本里保证确定性:截帧、剪切、格式转换、音视频分离、压缩/调分辨率六类能力。
- 按时间点截图 —— 截取视频中指定时刻那一帧的图片(精确到帧)。
- 按时间范围剪片段 —— 剪切起止区间,支持两种模式(由用户选择):
-copy(默认):-c copy流复制,速度极快、参数与质量 100% 原样;起点吸附关键帧、边界略有偏移(通常 0.5~2 秒,取决于关键帧间隔)。
-encode:重编码,起点精确到帧、时长精准;较慢。适合用户明确要求"必须在某时刻整开始、分毫不差"。 - 格式转换
convert—— 转换到目标容器mp4/mkv/mov/avi/webm/flv/m4v/ts;优先无损流复制(换封装),失败自动重编码(H.264+AAC)。 - 音视频分离
extract—— 单独导出音频(_audio.m4a)或画面(_video.mp4,无音轨)。 - 压缩 / 调整分辨率
compress—— 减小体积或缩放(--scale W:H如1280:-2/720:-2,--crf 0-51默认 28)。
> 两个脚本接口完全一致,仅实现语言的系统差异不同:macOS/Linux 用 bash,Windows 用 PowerShell。这样既保证逻辑确定,又不给用户的系统加任何额外运行时(不装 python、不装 Git Bash)。
第 0 步:先检测操作系统,选定脚本(非常重要)
在执行任何处理前,先判断当前运行的平台,再用对应脚本:
# macOS / Linux
uname -s # 输出 Darwin 或 Linux
# Windows(PowerShell)
$env:OS # 输出 Windows_NT
| 检测到 | 使用的脚本 |
|---|---|
macOS / Linux(Darwin/Linux) |
video-cut-frame/scripts/video-cut-frame.sh |
Windows(Windows_NT) |
video-cut-frame/scripts/video-cut-frame.ps1 |
- bash 脚本通过
bash video-cut-frame.sh ...调用;PowerShell 脚本通过powershell -NoProfile -ExecutionPolicy Bypass -File video-cut-frame.ps1 ...调用。 - 脚本路径用
{skill目录}/scripts/...的绝对路径,避免受当前目录影响。
环境依赖(唯一无常)
两个脚本都依赖 ffmpeg 与 ffprobe(装 ffmpeg 时自带 ffprobe),不自动下载。脚本内部会检测:缺任一,脚本以码 3 退出并打印对应平台安装引导——mac brew install ffmpeg、Windows winget install ffmpeg、Debian/Ubuntu sudo apt install ffmpeg。你把这些转告用户即可。
时间输入(很宽松,脚本可解析)
| 用户说的 | 传给脚本的值 | 含义 |
|---|---|---|
| "第 2 分钟" / "2m" | 02:00 或 120 |
2 分 |
| "1:30" / "一分半" | 01:30 或 90 |
1 分 30 秒 |
| "第 90 秒" | 90 |
秒 |
| "00:01:05" | 00:01:05 |
精确时分秒 |
- 脚本接受
HH:MM:SS/MM:SS/ 纯秒,自动换算。 - 遇到
HH:MM:SS必须原样传(脚本认这个形式最准确);中文"X 分钟 X 秒"你换算成其中一种即可。 - 传入前先核对时间不超过视频时长、且起点<终点;脚本内部也会二次校验(超时/起点≥终点会报错并退出码 2)。
如何解析用户意图
- 截帧:"截第 X 秒/这一帧/某个时刻的图片" → 用
frame。输出名默认{原名}_frame_{时间}.jpg;图片格式参数(bash--format/ PowerShell-Format)默认jpg,用户要"高清/UI 清晰画面"用png。 - 剪片段:"剪 A 到 B 这段" → 用
cut。默认输出名{原名}_cut_{起点}_{终点}.{与原片一致的后缀};默认流复制保持原格式,可要求encode精确。 - 转格式:"转成 mp4/其它格式" → 用
convert --to/<TARGET>,目标mp4/mkv/mov/avi/webm/flv/m4v/ts。 - 音视频分离:"导出音频 / 只要画面没声音" → 用
extract --stream/-Stream audio|video。 - 压缩/调分辨率:"把视频压小 / 压到 720p / 缩窄" → 用
compress(可带--scale/-Scale、--crf/-Crf)。
操作
功能一:截帧
# macOS / Linux
bash {skill}/scripts/video-cut-frame.sh frame "<输入.mp4>" --time "00:01:30" --out "<输出.jpg>"
# Windows —— 注意:PowerShell 用「单横杠」参数(-Time/-OutputFile/...),不能写 --time
powershell -NoProfile -ExecutionPolicy Bypass -File "{skill}\scripts\video-cut-frame.ps1" frame "C:\v\视频.mp4" -Time "00:01:30" -OutputFile "C:\v\frame.jpg"
功能二:剪片段
# macOS / Linux
bash {skill}/scripts/video-cut-frame.sh cut "<输入.mp4>" --start "00:01:30" --end "00:02:45" --out "<输出.mp4>" [--mode copy|encode]
# Windows —— 同样用单横杠参数;--mode 对应 -Mode copy|encode
powershell -NoProfile -ExecutionPolicy Bypass -File "{skill}\scripts\video-cut-frame.ps1" cut "C:\v\视频.mp4" -Start "00:01:30" -End "00:02:45" -OutputFile "C:\v\cut.mp4" [-Mode copy|encode]
-Mode / --mode 说明(bash 用 --mode,PowerShell 用 -Mode):
- copy(默认)= 流复制,快、参数原样,起点吸附关键帧、边界略偏。
- encode = 重编码(-c:v libx264 -crf 18 -c:a aac),起点精确到帧、时长精准,但较慢。
- 如何选择:用户未提精确要求 → 用 copy;用户明确"必须在某时刻整开始/分毫不差/卡准帧" → 用 encode,并先说明会慢一些。
cut 的实现已封装在脚本里:copy 模式用 -ss/-to -c copy 流复制;encode 模式用 -ss -i -t -c:v libx264 -crf 18 -c:a aac 精确重编码。无需你手工拼命令。
功能三:格式转换(convert)
把视频转换到目标容器/扩展名。默认先尝试无损流复制(-c copy 换封装),失败则自动重编码(H.264+AAC)。
# macOS / Linux
bash {skill}/scripts/video-cut-frame.sh convert "<输入.mkv>" --to mp4 [--out "<输出.mp4>"]
# Windows(单横杠)
powershell -NoProfile -ExecutionPolicy Bypass -File "{skill}\scripts\video-cut-frame.ps1" convert "C:\v\a.mkv" -To mp4 [-OutputFile "C:\v\a.mp4"]
支持目标格式:mp4 mkv mov avi webm flv m4v ts。默认输出名 {原名}.{目标格式}(放在输入同目录)。
功能四:音视频分离(extract)
单独导出音频或视频流。
bash {skill}/scripts/video-cut-frame.sh extract "<输入.mp4>" --stream audio [--out "<输出.m4a>"]
bash {skill}/scripts/video-cut-frame.sh extract "<输入.mp4>" --stream video [--out "<输出.mp4>"]
powershell -NoProfile -ExecutionPolicy Bypass -File "{skill}\scripts\video-cut-frame.ps1" extract "C:\v\a.mp4" -Stream audio
默认输出名 {原名}_audio.m4a 或 {原名}_video.mp4(视频流去除声音)。
功能五:压缩 / 调整分辨率(compress)
减小体积或缩放分辨率。
bash {skill}/scripts/video-cut-frame.sh compress "<输入.mp4>" [--scale 1280:-2] [--crf 28] [--out "<输出.mp4>"]
powershell -NoProfile -ExecutionPolicy Bypass -File "{skill}\scripts\video-cut-frame.ps1" compress "C:\v\a.mp4" -Scale "1280:-2" -Crf 28
--scale:W:H,如1280:-2(等比缩宽 1280) 或720:-2;省略则保持原分辨率。--crf:0-51,越大文件越小画质越低,默认 28。- 默认输出名
{原名}_compressed.mp4。
如何解析用户意图(新增功能)
| 用户说 | 用命令 |
|---|---|
| "把 mkv 转成 mp4" / "转成 mp4" | convert --to mp4 |
| "把音频单独导出来" / "导出音频" | extract --stream audio |
| "只要画面不要声音" / "分离出视频" | extract --stream video |
| "把视频压小一点" / "压缩体积" | compress(可选 --crf 28) |
| "压到 720p / 缩到 1280 宽" | compress --scale 720:-2 / 1280:-2 |
边界与约束
- 不做自动下载 ffmpeg,缺失时按平台引导安装。
- 格式转换支持目标容器
mp4/mkv/mov/avi/webm/flv/m4v/ts;优先无损流复制,失败回退重编码。 - 输出默认带语义命名并允许覆盖旧输出(脚本已带
-y)。 - 脚本返回非零时,读取其 stderr 的错误信息转告用户,并给出可操作建议(文件不存在/时间越界/参数不合法等)。
错误处理
- bash(macOS/Linux):码
2=文件不存在/参数缺失/终点≤起点/时间越界;码3=缺 ffmpeg/ffprobe;其它非零=ffmpeg 自身报错。 - Windows PowerShell -File:某些 PS 5.1 宿主会把
exit N折叠成1。因此不要依赖具体退出码,一律以「非零即算失败 + 读取 stderr 文本」为准: - stderr 有
ffmpeg not found→ 引导安装; - stderr 有
input file not found/end must be greater than start/requires -→ 属于参数/输入问题,核对后重试; - stderr 有
cut failed/frame extraction failed→ ffmpeg 自身报错,转告原文。 - 用户时间口语难以换算时,主动向用户确认,不要猜测。
示例
- 用户:"截取 video.mp4 第 90 秒那一帧"
→bash .../video-cut-frame.sh frame "video.mp4" --time 90
→ 输出video_frame_00-01-30.jpg - 用户:"剪视频里 1:30 到 2:45 这段,保持原格式"
→bash .../video-cut-frame.sh cut "video.mp4" --start 01:30 --end 02:45
→ 输出video_cut_00-01-30_00-02-45.mp4(参数对齐原片) - 用户:"我要第 5 分钟的清晰截图"
→bash .../video-cut-frame.sh frame "video.mp4" --time 05:00 --format png