需要:FFmpeg(放到脚本所在目录 或 添加到环境变量)
作用:使用FFmpeg裁剪视频片头片尾(不转码)
适用场景:片头片尾长度固定,但视频长度不固定。
适合人群:PC性能吃鸡者、买不起正版又不用盗版的好人、找不到相应免费软件者…
使用:拖放/发送到 视频文件到该批处理/批处理的快捷方式,
如无意外将在同一目录生成 文件名_cut.文件后缀
的剪切后视频。
批处理:
@echo off
rem ===================需手动设置===================
rem 设定片头片尾长度,格式为 HH:mm:ss.fff
set op=00:00:10.250
set ed=00:00:10.250
rem ================================================
rem 将HH:mm:ss.fff时间转换为毫秒
rem %var:~0,2%、%var:~3,2%、%var:~6,2%、%var:~9%分别对于HH、mm、ss、fff
rem (1%var:~x,y%-100)删掉数值前的0,以免被视为8进制数
set /a t_op=((((1%op:~0,2%-100) * 60 + (1%op:~3,2%-100)) * 60 + (1%op:~6,2%-100)) * 1000) + (1%op:~9%-1000)
set /a t_ed=(((1%ed:~0,2%-100) * 60 + (1%ed:~3,2%-100)) * 60 + (1%ed:~6,2%-100)) * 1000 + (1%ed:~9%-1000)
rem 获取视频长度
echo 正在读取视频长度
for /f "tokens=2 delims=, " %%a in ('ffmpeg.exe -i "%~1" 2^>^&1^|findstr /r /c:"^ *Duration:"') do set dur=%%a
if not defined dur goto error
rem 计算截取时间
set /a cut=(((1%dur:~0,2%-100) * 60 + (1%dur:~3,2%-100)) * 60 + (1%dur:~6,2%-100)) * 1000 + (1%dur:~9%0-1000) - t_op - t_ed
set cut=%cut:~0,-3%.%cut:~-3%
rem 截取视频
ffmpeg.exe -accurate_seek -ss %op% -t %cut% -i "%~1" -c copy -avoid_negative_ts 1 "%~dpn1_cut%~x1"
echo,
echo 操作完成,请按任意键退出.
timeout /t -1
exit
:error
echo 读取视频时长失败。
echo,
echo 请检查视频文件名是否含有特殊字符!
echo 请按任意键退出
timeout /t -1
exit
其他事项:
-
脚本中的op和ed分别为片头片尾时长(不是时刻),必须严格按照
HH:mm:ss.fff
格式填写,可以为0(00:00:00:000),即仅切片头/片尾。
片尾时长=片长-片尾起点。精确的片长可以通过ffmpeg -i input.mp4
获取(Duration:00:00:00.00) -
FFmpeg不转码切割基于关键帧而非精确时刻,所以切割点应该采用关键帧时间点
关键帧时间取得方法(以PotPlayer为例):
- F5/右键进入播放器设置
- 播放→时间跨度→设为最小值1秒 并 勾选下方的 “如存在关键帧数据…"
- 播放视频→暂停→按设为1秒的前进/后退快捷键定位到片头结束/片尾开始附近
- 按G键/右键相应菜单项打开定位窗口→窗口显示时间即为当前关键帧时间
没多大意义的其他:
FFmpeg非转码切不准的原因:参见关键帧的存在意义
FFmpeg其他切割模式及参数:参见官方文档
FFmpeg精确切割的办法:转码(慢)
FFmpeg精确切割又不慢的办法:切割→局部转码(仅数帧)→拼接(有待验证,无期)
最后补充一句:
批处理就是个见鬼的落后玩意……