8、流复制与重编码:codec copy与重新编码的区别、何时用copy、何时必须重编码
说实话,我刚入行那会儿,也被这两个概念搞晕过。明明都是转码,为什么有时候几秒钟就完事,有时候却要等半天?
后来我才明白——流复制(codec copy)和重编码,本质上干的是完全不同的活。一个是在搬砖,另一个是在重新造砖。
流复制:说白了就是“搬运工”
你想想看,一个MP4文件里,视频流是H.264编码的,音频流是AAC编码的。如果你只想换个封装格式,比如从MP4换成MKV,或者只想截取一段,那根本不需要重新压缩。
这时候就用 -c copy。它的意思是:“保持原样,直接搬过去”。
核心特点:
- 不解码、不编码,只做容器层面的操作
- 速度极快,基本是磁盘I/O的极限
- 画质、音质完全无损
- 文件大小几乎不变
# 把MP4封装成MKV,视频和音频都保持原样
ffmpeg -i input.mp4 -c copy output.mkv
# 只截取前30秒,不重编码
ffmpeg -i input.mp4 -ss 0 -t 30 -c copy output.mp4
我在项目中遇到过这样一个场景:客户给了个TS格式的直播录制文件,播放器不支持。我直接用 -c copy 转成MP4,前后不到5秒,文件就搞定了。客户还以为我在糊弄他,哈哈。
重编码:这才是真正的“转码”
重编码就不一样了。它会把视频流完全解码成原始像素数据,然后再用新的编码器重新压缩。
说白了,就是先拆了房子,再用旧砖头盖新房。这个过程非常吃CPU或GPU,速度也慢得多。
# 把H.264视频重编码为H.265(HEVC)
ffmpeg -i input.mp4 -c:v libx265 -c:a copy output.mp4
# 改变分辨率,必须重编码
ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 output.mp4
注意:重编码是有损的。每次重编码都会引入画质损失。我见过有人把同一个视频反复转码了七八次,最后画面全是马赛克。嗯,千万别这么干。
什么时候用copy?什么时候必须重编码?
这个问题,我总结了一个简单的判断逻辑:
| 操作场景 | 能否用copy? | 原因 |
|---|---|---|
| 更换封装格式(MP4→MKV) | ✅ 可以 | 编码格式不变,只改容器 |
| 截取视频片段 | ✅ 可以(注意关键帧对齐) | 不改变编码数据 |
| 合并多个视频 | ✅ 可以(参数需一致) | 编码格式相同即可 |
| 改变分辨率/帧率 | ❌ 必须重编码 | 需要重新采样像素 |
| 改变编码格式(H.264→H.265) | ❌ 必须重编码 | 编码算法完全不同 |
| 添加水印/滤镜 | ❌ 必须重编码 | 需要修改像素数据 |
| 调整码率/压缩比 | ❌ 必须重编码 | 需要重新量化 |
| 修复损坏的视频 | ⚠️ 视情况 | 部分损坏可用copy跳过 |
我的个人习惯:只要不涉及像素级别的修改,优先用copy。速度快、质量无损,何乐而不为?只有当你确实需要改变视频内容本身时,才考虑重编码。
一个容易踩的坑:关键帧对齐
用 -c copy 做截取时,有个细节很多人不知道——FFmpeg只能从关键帧开始截取。
举个例子:你想从第10秒开始截,但第10秒刚好不是关键帧。那FFmpeg会自动往前找,找到最近的关键帧作为起点。结果你得到的片段,可能从第9.5秒就开始了。
我曾经因为这个被客户投诉过,说截出来的视频开头多了半秒黑屏。后来我学乖了,要么用 -ss 放在 -i 前面(先seek再解码),要么干脆重编码来保证精确截取。
# 精确截取(但会重编码)
ffmpeg -i input.mp4 -ss 10 -t 5 -c:v libx264 output.mp4
# 快速截取(可能不精确,但用copy)
ffmpeg -ss 10 -i input.mp4 -t 5 -c copy output.mp4
流复制 vs 重编码:一张图看懂
下面这张图,是我自己画的工作流程对比。你看完就明白了:
实际项目中的选择策略
我一般会这样决策:
- 先问自己:我需要改变视频内容吗? 如果不需要,直接copy。
- 如果需要改变,再问:能不能用硬件编码加速? 比如用
h264_nvenc或h264_amf,速度能快很多。 - 如果对画质有极致要求,比如做母版归档,那就用
-crf 18甚至无损模式重编码。 - 如果是批量处理,我习惯先跑一轮copy做预处理,把封装统一,再针对需要改内容的文件做重编码。
一个小技巧:用 ffprobe 先看看源文件的编码信息,确认是否支持copy。我经常遇到有人拿着MPEG-2的文件想copy到MP4里,结果播放器不认——这时候就得重编码了。
# 查看编码信息
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name input.mp4
嗯,总结一下:能用copy就别重编码,这是铁律。但该重编码的时候也别犹豫,毕竟有些活,copy真的干不了。
公众号:蓝海资料掘金营,微信deep3321