🎬 第四章 精通FFmpeg框架流程:击鼓传花之责任链设计模式
📄 一句话概括

转封装只换信封,转码重写信纸;同一个文件,时间差近十倍。 判断标准就一句:要动像素就转码,只动容器就转封装。

📝 本节和前面几节的关系

4.5.1 讲了转码链,这一节把两条路都真跑一次对比。 下一篇 4.5.3 把最后一环从写文件换成写网络。

一、两条路的本质区别

转封装搬的是包,转码搬的是像素。 转封装 转码


处理单位 包 帧 要不要解码 不要 要 要不要编码 不要 要 画质 一点不掉 掉一点 能不能改画面 不能 能

「画质一点不掉」是转封装最大的价值。 它压根不碰像素,只是把同一批压缩包换了个方式装起来。 所以能转封装就别转码,这是本课最实用的一条建议。

二、实测:时间与体积摆在一起

同一个文件,两条路各跑一次。 项 转封装 转码


耗时 十几毫秒 一百毫秒上下 处理单位 138 个包 50 帧 产物大小 与原文件接近 看分辨率与 crf

耗时差近十倍,而两条路都没有报错、都产出了可播的文件。 不测的话根本不知道差这么多。 这个差距在长视频上会被放大成分钟级,批量转封装与批量转码是两种量级的活儿。

三、体积小不等于转码更省

这个误区必须点破:转码出来的文件更小,不是因为转码高效。 小的原因是分辨率砍了、码率降了。 如果把分辨率与码率都保持原样,转码产物通常比原文件更大——多了一轮有损压缩, 编码器还多了优化空间去堆码率。 改了什么 体积会怎样


只换容器 基本不变 降分辨率 明显变小 降 crf 数值(提质量) 变大

看体积要先问「改了什么参数」,不能光看数字。 「转码之后小了 80%」这句话没有信息量,得知道砍了什么。

四、转封装有个前提

编码格式得被目标容器支持。 h264 装进 mkv 没问题,装进 mp4 也没问题。 但想把 h264 塞进只认 mpeg2 的老容器,转封装会失败——这时候只能转码。 容器是信封,编码是信纸。 信纸得塞得进新信封才行。 常见的不兼容会报错说 codec not supported in container。 这个报错很好认:它不是格式不认识,是「认识但装不下」。看见它就知道该改走转码这条路。

五、动手 Demo:两条路——转封装与转码,差多少

同一个文件,两条路各跑一次,时间与体积摆在一起。

import av

# 第一条:转封装,完全不解码
with av.open("_media32/tiny.mp4") as ic:
    with av.open("_media32/copy_out.mkv", "w") as oc:
        vs = oc.add_stream_from_template(ic.streams.video[0])
        for pkt in ic.demux(ic.streams.video[0]):
            if pkt.dts is None:
                continue
            pkt.stream = vs
            oc.mux(pkt)

实跑输出:

--------------------------------------------------------------------
两条路——转封装与转码,差多少
--------------------------------------------------------------------

**① 同一个文件,两条路各跑一次**

  项           转封装         转码
  ------------------------------------------
  耗时         5.3 毫秒       141.8 毫秒
  处理单位     138 个包       50 帧
  产物大小     45155 字节     6940 字节
  分辨率       160×120        80×60
  编码器       没动过         重新编了

**同样的源,转码比转封装慢 26.9 倍。** 慢的地方全在「解码 + 编码」这两环。

**② 体积反而小了,这不能归功于「转码更省」**

产物小是因为**分辨率砍了一半、还换了 CRF 30**。
如果把分辨率与码率都保持原样,转码出来的文件通常比原文件**更大**——因为多了一轮有损压缩。

**这一条很重要:转码不会让画质变好。** 每一次有损重编都掉一点,掉多少取决于码率给得够不够。
二代转码的片子看着发糊,就是这个原因。

**③ 什么时候用哪条路**

  需求                  该走哪条     理由
  -----------------------------------------------------
  换容器(mp4→mkv)     转封装       根本不用动码流
  改分辨率              转码         像素得重排
  改码率                转码         得重新量化
  改帧率                转码         得丢帧或补帧
  只切片/拼段          转封装       按时间切包就行

**判断标准就一句:要动像素就转码,只动容器就转封装。** 能转封装就别转码,省时间还保画质。

**④ 转封装有个前提:编码格式得被目标容器支持**

h264 装进 mkv 没问题。要是想把 h264 塞进只认 mpeg2 的老容器,转封装会失败——这时候只能转码。
**容器是信封,编码是信纸,信纸得塞得进新信封才行。**

add_stream_from_template 就是「照原样」,一字不改地搬。 两条路的耗时差在毫秒级就能看出来,长视频上是分钟级。

30 秒实验

  1. 把转封装的目标容器换成 mp4,看体积变化。
  2. 试着把 h264 转封装进 mpeg2 容器,看报什么错。
  3. 给转封装加一个 -c copy 的等价物:确认没有解码被调用。

常见误区

  1. 以为转码更省体积。 体积小是因为换了参数,不是因为转码高效。
  2. 什么都走转码。 只换容器时白花十倍时间,还掉画质。
  3. 以为转封装什么容器都能进。 编码格式得被目标容器支持。
自测三问(点开对答案) 1. 只换容器该走哪条路,为什么? —— 转封装。它不碰像素,画质一点不掉,速度快近十倍。 2. 为什么转码出来的文件可能比原文件更大? —— 多了一轮有损压缩,编码器会重新分配码率。体积取决于新参数,不取决于「转码」本身。 3. 转封装失败最常见的原因是什么? —— 编码格式不被目标容器支持,比如把 h264 塞进只认 mpeg2 的容器。

相关笔记