~/blog/ffmpeg-seek-lossless-cut
剪辑2026-09-14 · 8 min

无损剪辑与 seek:为什么你的剪辑总是不准

想把第 38 秒剪到头,导出来却从 35 秒开始。-ss 放前放后、配不配 -c copy,对精度的意义完全不同,一次讲清。

"想从第 38 秒开始剪,导出来却从 35 秒开始。"用 FFmpeg 剪切的人大多数被这个问题坑过。原因往往不是命令写错,而是没搞清楚 -ss 放哪个位置、配不配 -c copy,对精度的意义完全不同。这篇把 seek 和"无损剪辑"的边界讲透。

-ss 放前放后:两种 seek 语义

-ss(seek,快进定位)可以放在输入文件前,也可以放在输出文件前,两者行为不同:

输入 seek(-ss 00:00:38 -i input.mp4:快速跳转到目标位置附近,只认关键帧、不逐帧处理。FFmpeg 2.1 之后,如果后面紧跟重编码,它默认开启 accurate_seek:跳到关键帧后会把目标点之前的多余内容解码出来再丢弃,从而做到帧精确——快,又准,是推荐写法。

输出 seek(-i input.mp4 -ss 00:00:38:把输入从头解码,直到时间戳到达目标才输出。帧精确,但前面每一帧都要解一遍,大视频会非常慢。

写法速度精度
-ss 放输入前(重编码)帧精确
-ss 放输出前帧精确
-ss 放输入前 + -c copy只到关键帧

无损剪辑的边界:-c copy 不能帧精确

-c copy 的意思是"不重编码,直接复制已编码的字节",速度快,也避免了二次量化带来的画质劣化。但它有个硬约束:只能从关键帧(I 帧)开始作为片段起点

H.264 这类长 GOP 编码里,只有少数帧能独立作为解码起点,其他帧都依赖前面的参考帧。假设你想从 10.000s 开始剪,而前一个关键帧在 9.600s——-c copy 只能从 9.600s 切出去,第一帧不是你点的那帧,起点被悄悄"前移"了。误差多少完全取决于关键帧的间隔,不是看视频时长能推出来的。

所以"无损"和"精确"在 -c copy 这里是两件事,常常打架:

  • 无所谓差几个关键帧、只求快 → -ss 放输入前 + -c copy
  • 必须精确到帧 → 重编码

常用命令:

# 快速粗剪,只切开头/结尾,不重编码(起点可能前移到关键帧)
ffmpeg -ss 00:00:38 -i input.mp4 -t 00:00:15 -c copy out.mp4

# 精确剪辑,重编码
ffmpeg -ss 00:00:38.450 -i input.mp4 -t 00:00:14.500 \
  -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k out.mp4

从中间剪:避免负起始时间戳

从中间 cut 出来时,新视频的起始时间戳可能是负数(相对剪辑起点而言),有些播放器不认,表现为黑屏或无法正确定位。MP4 里可以用 -avoid_negative_ts make_zero 把起点对齐到 0:

ffmpeg -ss 00:00:38 -i input.mp4 -t 30 -c copy -avoid_negative_ts make_zero out.mp4

-t 是时长,-to 是结束时间戳,二选一,别同时用。

拼接:concat demuxer 不是想拼就能拼

站内视频合并默认走 -f concat -c copy,快、无损。但它有个隐藏前提:所有片段必须在编码层面完全一致——编码器、profile、分辨率、帧率、像素格式(yuv420p)、sar、时间基、音频采样率和声道,哪一项对不上都可能出现 Non-monotonous DTS 报错,或拼出来音画错位、后半段无声。

来源不同(不同软件 / 设备录的)的片段,直接拼大概率出问题。正解是先归一化再拼:

# 先把每段统一成同一规格
ffmpeg -i a.mp4 -c:v libx264 -r 30 -s 1920x1080 -pix_fmt yuv420p -c:a aac -ar 48000 -ac 2 a_std.mp4
ffmpeg -i b.mp4 ... b_std.mp4

# 再按清单无损拼接
printf "file 'a_std.mp4'\nfile 'b_std.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4

如果各段实在统一不了,就得用 concat filter 重新编码,接受一次画质损失。

动手试

视频裁剪拖时间轴就能精确切片段;视频合并把几段拼成一个——都在浏览器本地完成,文件不上传。

FAQ

Q:-c copy 就是无损吗? A:对,数据不重编码,避免了二次量化损失。但"画质无损"≠"剪辑精确"——它不是从你点的帧开始的,可能多出开头几秒。这两件事要分开看。

Q:把 -ss 放前面为什么也剪不准? A:当配了 -c copy 时,-ss 的 seek 会被关键帧限制住,起点只能落在关键帧上。想准就要重编码,或先用精确 seek 定位再 copy。

Q:为什么拼接后半段没声音? A:最常见是各段音频采样率或声道数不一致,concat demuxer 直接拼处理不了这种差异。先把各段统一成同采样率、同声道再拼。

RELATED TOOLS · 把文章里的东西用起来