欢迎阅读!本教程仅算盲人摸象的业余分析,仅具备业余参考价值。若有什么不会的可以加群691892901。
推荐设置:彩色模式、不打印背景、0.04 英寸边距、打印页眉页脚
点击图片即可轮询三种图片大小。窗口宽度大于窗口高度则切换到宽屏/桌面端/平板电脑排版,否则切换到窄屏/移动端排版。
安卓 12 或更高版本中,如 Edge,Brave,Kiwi,Arc,Dragon,Opera 的 Chromium 内核网页浏览器有着中文字体过细的显示问题(谷歌早已知晓却从未修复)建议使用 Firefox 以确保舒适的观看体验。
描述数据的数据,例如食品包装上的标题、成分表、图片、营养信息、教你如何正确打开包装的附注就是一种元数据。视音频封装文件中的元数据并不是视音频本身,但播放器需要其中的一些信息才能以正确的帧率、音视频对齐、色彩标准,使用正确的视频解码器,音频解码器,以正确的打开“包装”。
图:比特,字节与体积时间比的转换
操作系统(处理器、内存)的“字节”是以二进制换算的,而储存容量(闪存、硬盘)的“字节”是十进制换算的。一开始储存容量不大,而 1000 进和 1024 进差 2.4%,不如多卖电脑重要,就有了现在不统一的容量称呼
文件体积每秒,单位 bps,Bps,Kbps,KBps,Mbps,MBps,Gbps,GBps 等。“ps”即 per second,也可写作“Kb/s,Mb/s”等。
人眼感光细胞捕获特定强度的电磁波(可见光),然后通过大脑处理,产生了我们所看到的幻觉。实际上,色彩只有一个标量属性,即频率。
图:色彩的波形频率变化,见维基百科。
YUV / YCbCr 色彩空间图像的亮度平面 Y,或者 RGB 图像分离出的亮度/灰度平面,有时也被称为伽马平面或 Y 平面。
代表将色彩信息去除,只保留黑、灰、白色的单通道图像。
数字电路中软硬件亮度从黑到白之间过渡的细分密度。由显示器的驱动板/主控板接收 GPU 输出的数字信号,并转义为像素点的电压得到。因此使用了 CRT 显像管的电视可能是模拟电视,也可能是数字电视,取决于有没有如 HDMI,DP 等数字信号接口。模拟电视使用 \( 0 \text{mV ~ } 700 \text{mV} \) 的输入电压表示色深。在当时考虑到电视台调制偏差,以及干扰可能会映射出 \( >700 \text{mV} \) 的烧屏强光,而通过限制了色深密度的范围来解决问题,得到了有限范围。
计算机擅长使用二进制,因此数字色深的分阶用位/bit 表示。如 4bit 16 深 \( 2^4 \)、8bit 256 深 \( 2^8 \)、10bit 1024 深 \( 2^{10} \) 的形式呈现:
数字电视的 Bt.601 色彩标准考虑了数字与模拟电视颜色的一致性,而定义了兼容有限 Limited-compatible 的色深密度,导致现在使用 Bt.709,Bt.2020 色彩标准的媒体(支持完整色深)中,有限范围仍是绝对主流。
输出设置为有限,未经 Y/C 转换,连接到设置为输入完整范围的显示器,显示器缺失最暗和最亮的范围,呈现灰蒙蒙的画面,例如:
输出设置为完整,未经 Y/C 转换,连接到设置为输入有限区间的显示器,显示器忽略 8bit 下 0~15 和 235~255 的亮度范围,出现画面过亮过暗(饱和度过高)的画面,例如:
yuvj 色彩空间中的 j 被误解,而使用了无效或错误的转换处理导致
heic 格式的图片被错误转换到 jpeg 或错误显示导致,一般出现在手机上,以及 Windows 11 的图片浏览器中
HDR 视频在设备没有正确配置的情况下直接显示导致
图:完整色深 Fullrange 与有限/TV 色深 Limited,包括上述说明的更优版本见硬件茶谈。
ffmpeg 转换到完整:
ffmpeg.exe -i "limited.mp4" -vf "scale=in_range=limited:out_range=full" -color_range 2 -pix_fmt yuv420p -movflags +write_colr "full.mp4"
ffmpeg 转换到有限:
ffmpeg.exe -i "limited.mp4" -vf "scale=in_range=full:out_range=limited" -color_range 1 -pix_fmt yuv420p -movflags +write_colr "full.mp4"
"scale=in_range=limited:out_range=full
代表输入和输出的范围-color_range
选择编码和封装的色深密度(0~2)-movflags +write_colr
在 .mp4 封装下写入色深密度元数据两种方式:向上提亮缩放“白化” \( s = cr^\frac{1}{\gamma} \) 和向下变暗缩放“黑化” \( s = cr^\gamma \)。
图:伽马矫正的指数算式,此处c = 1代表 0~1 的亮度区间,8bit 256 深则c = 256,见desmos 互动例。
通常情况下,表示对音量、冷热、远近等两种程度的差异大小缩放。在图像/显示器中,对比度则代表最亮和最暗的显示亮度差异。图片的对比度低会显得发灰,因为当前的亮度设置位于这个灰度水平上。
人眼在黑暗中观看同样的视频时,有些场景会显得过亮,有些场景则会显得太暗。这种情况下,降低对比度即可解决该问题;而在阳光下观看同样的视频时,即使将手机电脑调到最大亮度,也无法清晰看到暗部场景。这种情况下,降低对比度并增加亮度即可解决该问题。
售卖手机的厂商可以考虑让所有用手机看视频的人都想要换手机:只需在下拉状态栏的亮度滑块条 Brightness 上增加一个“暗度 Darkness”滑块:
一般指液体在特定压力和温度下溶解了某种成分的程度,达到最高时会沉积而不再溶解。图像中则代表颜色接近 100% 纯色的程度或“彩度”,饱和度越高则图像越鲜艳,为零时得到灰阶图像;最大时得到纯色图像。对比度接近饱和度,但不是饱和度。
像素是组成图像的最小单位,决定了图像的物理大小和分辨率。一般情况下分为屏幕的硬件像素大小,和图片/视频的软件像素大小两种。当软件像素小于硬件像素时,显示 100% 大小的图片会变小,或者通过缩放滤镜将图片放大以适应屏幕。反之,如果硬件像素大小小于软件像素,则会使用缩放滤镜将图片缩小至合适的尺寸,或者图片会溢出屏幕。图像中的每个像素都有位置和颜色两份信息。
指屏幕或印刷设备上的物理像素密度,这取决于设计时预期的观看距离。屏幕的 PPI 高则适合近距离观看,因为物理像素更密集。在印刷设备的 PPI 越高,打印出的图像就越细腻。软件的 PPI 主要用于计算新建图像的像素大小和分辨率,以确保图像有着适当的大小和清晰度。
位图使用像素和元数据(例如 n 个像素后换行)来表示图像。每个像素都包含特定的颜色信息,通常表示为 RGB 或 YCbCr 值。用于描述照片和复杂图像,但当放大时会失真,因为像素的信息已经固定,而放大只是用滤镜在其中插值填空的结果。
矢量图使用图形函数代码(例如 JavaFX,SVG)来描述图像。它们以函数定义图像的形状、线条和颜色。矢量图可以被放大而不失真,并且可以在不同的尺寸和分辨率下保持清晰度,因为它们是基于数学公式的。
用于表示和处理图像颜色的数据格式,具有适用于各种不同应用场景的多种类型。最常用的是分为硬件和操作系统的 RGB 色彩空间,以及内容的 YUV/YCbCr 色彩空间。见 Captain Disillusion 的科普。
RGB 色彩空间由红色 Red、绿色 Green、蓝色 Blue 三个通道组成,每个通道的数值表示相应颜色的强度,对应着显示器红色 LED,绿色 LED 和蓝色 LED。常用于显示器、摄像头和图形处理等硬件和软件系统中。
YUV/YCbCr 色彩空间是另一种常见的色彩表示方式,用于存储和传输视频数据。Y 代表亮度 Luminance,而 U、V 代表色度 Chrominance。YCbCr 特指数字信号,YUV 特指模拟信号,再无区别。由于后者字数更少且不需要频繁切换大小写,打字更容易,所以 YUV 拼写后来逐渐被当做讨论用的“平替”。
🎆色彩格式 | 构成色 | 特点 | 存在原因 | 支持范围 |
---|---|---|---|---|
RGB | 红绿蓝 | 通用 | 使显示器/照相机通用 | 几乎所有可视媒体 |
ARGB | α 红绿蓝 | 透明通道 | 便于图层化编辑 | 图片,部分视频 |
CMYK | 湛 zhàn 洋黄黑 | 减法色彩 | 卖墨盒 | 打印纸 |
YCbCr/YUV,YPbPr | 白蓝 - 黄红 - 绿 | 压缩 | 压缩视频图片 | 所有有损压缩 |
YUV/YCbCr 色彩空间下,利用人眼对色度细节不敏感的特性(见下图全分辨率和半分辨率的色度面),降低色度平面的分辨率,从而压缩图像。色度采样格式通常用三个数字表示,例如 4:4:4、4:2:2 等。
A:B:C 代表微观分辨率下,每个长 A 像素,高 2 像素的空间,第一行缩到 B 个色度像素,第二行缩到 C 个色度像素。如 4:2:2 代表色度平面的每个 4x2 微观区间中,第一行的色度分量保留 2 个像素,第二行的色度分量也保留 2 个像素。色度采样详见下表:
👾采样 | 1920x1080 下宏观 | 色度 4x2 微观 | 特点 | |||
---|---|---|---|---|---|---|
4:4:4 | 亮度,色度皆 1920x1080 | 色素 | 色素 | 色素 | 色素 | 逐行,读写亮色度而不用从 RGB 转——剪视频快 |
色素 | 色素 | 色素 | 色素 | |||
4:2:2 | 亮度不变,色度 960x1080 | 色素 ← | 色素 ← | 逐行扫描,颜色像素靠插值还原。直接读写亮度所以剪视频比 RGB 快 | ||
色素 ← | 色素 ← | |||||
4:2:0 | 亮度不变,色度半宽半高 960x540 | 色素 ← ↑ ⬉ |
色素 ← ↑ ⬉ |
|||
4:4:0 | 亮度不变,色度全宽半高 1920x540 | 色素 ↑ |
色素 ↑ |
色素 ↑ |
色素 ↑ |
|
4:1:1 | 亮度不变,色度 1/4 宽全高 480x1080 | 色素 ← ← ← ← | 交错扫描 Interlaced,横着扫就不会把另一场的帧参考而浪费算力了 | |||
色素 ← ← ← ← | ||||||
4:1:1-par4:3 | 亮度 3/4 宽全高,1440x1080 色度 3/16 宽全高,360x1080 | 色度像素 5.333×← | ||||
色度像素 5.333×← | ||||||
4:2:0-par4:3 | 亮度 3/4 宽全高,1440x1080 色度 3/8 宽半高,720x540 | 2.667 ← ↑ 2.848 ⬉ |
2.667 ← ↑ 2.848 ⬉ |
逐行扫描,非方形亮度像素,par 通常是 4:3 |
图:RGB 与 YCbCr 的转换,色度采样的使用及编解码与录制,传输,显示的关系
根据硬件的算力和带宽两种限制选择有损压缩,无损压缩和未压缩。一种(图/视/音频)编码可集成全部三种策略。
压缩强度 | 带宽负载 | 解码负载 | 硬盘损耗 | |
---|---|---|---|---|
未压缩 | 无 | 最高 | 最低 | 最高 |
无损压缩 | 低 | 高 | 低 | 高 |
无损压缩 | 高 | 中~高 | 中~低 | 中 |
有损压缩 | 低 | 高 | 低 | 低 |
有损压缩 | 高 | 低 | 高 | 最低 |
只要录制,剪辑,调色,混音,导出中一个环节用错了录制设备,采样率/色深,色彩空间,分辨率,像素宽高比,颜色混合,伽马映射等设定,损失就已成定局,此时选择有损或无损编码就不再有意义。
视频压制是视频编码器用户追求画质、压缩率和速度的逻辑。很多人一看到硬件编码器速度快,就忽视了软件编码器的高压缩率。
确定编码器好坏,压缩和采购策略的方法。专用编码器常用于单一目的,但难以控制另外两端的损失。高算力适合通用策略,而低算力则适合专用策略。
图:三种出发点构成。其“完美中心点”不一定符合当下需求,但决定了是否能满足所有情况
最简单的结构为——脉冲编码调制Pulse-code modulation PCM信号
🎶压缩 | 格式 | 音质 |
---|---|---|
有损 | mp3,aac,ogg(vorbis/opus) | 取决于耳机/音响,混音,声场。分为 HiFi 音频和监听音频两种质量参考 |
无损 | flac,alac,ape,it | |
未压缩 | wav(PCM) |
最简单的结构为 PCM 信号 + 每 n 个像素换行的元数据
📷压缩 | 格式 | 最大 RGB 色深 | 最大 YCbCr 色深 | 最大 CMYK 色深 | 动图 | HDR | 透明 |
---|---|---|---|---|---|---|---|
有损 | jpg | 8 8 8 | 8 8 8 | 24 24 24 24 | |||
有~无损 | gif(编码无损,颜色少了) | 24×3 中取 8×3 | √ | 仅 1bit | |||
webp | 8 8 8 | 8 8 8 | √ | √ | |||
jpg-XR(兼容 jpg) | 32 32 32 | 8 8 8 | 16 16 16 16 | √ | √ | √ | |
avif,heif/heic,filf | 32 32 32 | 16 16 16 | √ | √ | √ | ||
无损 | pdf,jpg-LS,png | 16 16 16 | 32 32 32 32 | 仅 mng | √ | ||
有损~无损~未压 | tif | 16 16 16 | 8 8 8 | 128 128 128 128 | √ | √ | |
未压缩 | raw,bmp | 24 24 24 | 仅 raw | √ | √ | ||
dpx | 64 64 64 | 16 16 16 | √ | √ |
最简单的结构为一组图片。
🎥压缩 | 格式 | RGB/YCbCr 色深 | HDR | 透明 |
---|---|---|---|---|
有~无损 | qt,hevc,avc,vvc,vp8/9,DNxHR/HD,prores | 12 12 12 | 除 avc,vp8 | 仅 prores |
无损 | rawvideo | 32 32 32 | √ | |
cineform | 16 16 16 | √ | ||
有损~无损~未压 | Flash 动画 | 内嵌图片决定 |
图片与视频之间还有图像序列,动图两种中间格式。图像序列直接储存视频为大量图像,一般用于录制素材;动图如 .gif,.mng 则表面上和视频一致:
设计\格式 | 动图编码 | 视频编码 | 图片序列 |
---|---|---|---|
播放用时 | 短(GOP = 1) | 长(GOP >= 1) | 无 |
帧率 | 随便 | 随便 | 随便 |
分辨率 | 随便 | 随便 | 随便 |
帧间冗余 | 一般不支持 | 一般都支持 | 无 |
需要封装 | 无 | 一般都需要 | 无 |
通常用于过滤水和净化空气。在信号中代表处理一维音频和二维视频信号的算法。滤镜工具代表能够将滤镜应用到信号上的软件或插件,比如 Adobe Premiere Pro,After Effects,ffmpeg,DaVinci Resolve,ScreenToGIF,FL Studio,Reaper,Ableton,Audition,GIMP,Photoshop,FSCapture,LightRoom,OpenCV 等编辑图像、视频和音频的工具。AviSynth(+)和 VapourSynth 严格上称为帧服务器,因为需要连接一个编码器才能导出视音频。
电影胶片(卤化银晶体)被投影灯放大得到胶片颗粒 Film Grain,在单独一帧胶片画面上是一种比较自然静态噪声。更广义且不自然的噪声来自于电视信号接收器或相机使用放大电路 amplifier 放大无信号频段,或黑暗场景产生的“雪花”画面和声音。以及根据厂家镀膜工艺水平而定的显示器屏幕磨砂表面“静态噪声”等等。
一般来说,如果噪点的边角尖锐,缺乏渐变,则属于“难看的噪声”。另一种比较极端的判断方法是——只有影视导演亲手保留,或游戏美工专门根据显示技术适配处理过的噪声才是好看的噪声、由第三方私自添加的噪声是“难看的噪声”。
实际上,人眼的“成像技术”也决定了人看到的画面本来就有很多噪点,而且是动态噪点,只是未注意的时候都是大脑的实时降噪和幻觉在抑制而已。
图:正在放映 2023 年电影《奥本海默》的 70mm IMAX 胶片放映机。源:Nicolas Vega
图:磨砂镀膜与镜面镀膜显示器的微观区别。可以看到没有漫反射的镜面更加“通透”。源:The Display Guy
源自早期操作系统只能显示有限数量的颜色,因此采用了高频闪烁两种颜色的方法来欺骗视觉(副作用是使人感到晕眩)。在图像、音频和低端显示器中,抖动滤镜代表通过分辨率或采样率来换取位深的加噪补偿手段。
具体来说,通过间隔几个像素就调亮/调暗一个像素的颜色,使得宏观整体上看起来像是淡化或加深;在音频位深分量两端的采样点间成比例的(以方形波或三角波信号)快速摆动,从而利用扬声器反应速度,起到淡化或深化偏移宏观上位深的效果。
图:音频的采样点,以及下采样音频,抖动关对比开的效果,见Micoope 科普。
图:下采样 8bit 到 1bit,开抖动的效果
抖动滤镜的效果主要是欺骗视觉,但因为效果独特,所以衍生出了 Ditherpunk 抖动朋克美术。典型如 1bit 游戏《奥博拉丁的回归》贯彻了这种风格——利用随机,蓝噪声,蓝噪声,黄金分割,Riemersma 等不同的加噪算法来定义游戏引擎的材质。
图:图像噪声算法
Windows 系统一般用双线性缩放放大 PPI 小的软件,视频视频播放器一般用 bicubic 或 lanczos 插值
使用 sinc 函数取近似,且引入了窗函数来矫正 sinc 函数,同时要计算 lanczos 核实现插值。计算量大,准确度略高于 bicubic 插值。
通过认知大量训练数据,在其中找出更高维度规律的情况下,利用这些规律推断像素值。计算量极大,准确度时高时低。
固定翼飞机,或者矩形的最小两边分量。被忽略的“长”是屏幕相对人眼的 z 轴。而换算长短边如 16:9 高 720 的方形像素视频,其宽就是 \( 720 \div 9 \times 16 = 1280 \)。
图:16:9 的矩形整数偶数放大后的图像分辨率
图片格式一般支持奇数分辨率,视频一般仅支持偶数分辨率。
假设函数 \(y=\cos\left(ux\right)\)。可以调节变量 u,如 \(y=\cos\left(2x\right)\),\(y=\cos\left(3x\right)\) 等。u 越大则余弦函数周期越短——频率越高;u 越小则余弦函数周期越长——频率越低。
变换算法可以将这个 u 作为输出数轴,原始波形中从低频到高频的分量都会被准确地排列进来。
图形界面交互 Graphic user interface GUI:通过图形元素(如按钮、滑块、菜单等)进行用户交互的界面设计。随着程序复杂度的增加,设计出好用的界面会变得更加困难。因此,只有在利润丰厚、注重美学设计、且拥有设计人才的行业才会推出外观精美的 GUI。然而,外观好看并不一定意味着好用、再而,很多时候有外观用都是一种奢求。
图:音频插件宿主软件 FL Studio,外加一堆免费和“免费”音频插件随便摆放的外观
图:网页服务器宿主软件 XAMPP 的 GUI(左下为 CLI),作为跨行业对比
命令行交互 Commandline interface CLI:在如 Terminal、Bash、CMD 和 PowerShell 的终端环境中,用户可以手动输入命令并按回车键查看结果。通常,只要输出结果有一定的文本排版,就可以轻松阅读。随着使用的增加,CLI 可能反而会变得比 GUI 更方便。然而,由于某些命令太长,而且需要储存变量,因此为了简化操作,人们会将其写作批处理、Shell 等命令脚本文件。例如PowerShell 一站式系统硬件检测的脚本。
应用编程交互 Application programming interface API:定义了软件应用程序如何相互通信的规则和工具。用于使开发人员和从程序的外部访问,以便在自己的应用程序中集成其中的功能。API 可以被看作是 CLI 的映射源,当开发者没有编写 CLI 参数或 GUI 时,可以退而求 API 来调用所需的功能。尽管 API 通常不直接面向最终用户,但它们在软件开发中非常重要
帧 Frame 通常用来描述连续图片序列中的单张图片。帧率 Frame Rate 是指每秒显示/刷新的图像帧数。帧率越高,则连续背景变化越流畅。因此,在游戏中,例如微软模拟飞行、极限着陆等模拟客机的游戏,以及电影运镜等故意限制背景变化程度的场景,其帧率一般只需要 30fps 左右(每秒更新 30 张画面)。而对于背景高速运动的游戏,比如模拟赛车等,即使是在手机平台上,最低帧率也不能低于 120fps。
在动漫中,如果背景高速移动变化时的帧率低于 60fps,观看体验会大大降低,例如《进击的巨人》中的部分场景。相反,对于一些其他动漫,如果设计师本意是为了降低成本而利用视觉暂留原理来创建顿挫画面,那么低帧率反而会破坏观赏体验。
逐行扫描通过一行行从左到右地刷新像素来构建图像,是最为常用的屏幕刷新方式。交错扫描的方法不同,它使用 YUV 4:1:1 采样,将屏幕的奇数像素行视为一个场,偶数像素行视为另一个场。这两个场在录制时错开一定时间,这样在模拟电视上观看时会产生 60fps 的视觉效果。交错扫描的原理是为了节省模拟电视信号的频段区间(与收音机接收电台信号一样)。因此,通过在时间上分隔行来节省空间,可以几乎将每个频道的频宽减半,例如(\(525 \text{行} \times 30\text{fps} = 15.75 \text{MHz}\))。
图:NTSC,PAL 和 SECAM 播放规格的地区分布,见维基百科
NTSC 模拟电视每个频道的标准带宽大约为 6MHz(但实际宽度仅为 4.5MHz)。接下来发生的事谁都没有预料到——彩色电视出现了。结果是原本的频宽完全放不下彩色电视台信号,而且由于电视机已经售出,不可能更改用户家里电视的频宽和扫描线的数量。最终解决方案是在每秒 30 帧的基础上丢掉一帧,并加速 1 秒到 1.1001 秒,以保持与帧率的对齐(同时也引入了 YUV 4:2:0 色彩空间)。经过这般折腾,码率/频宽总算被压缩了下来,但后继影响了数字视频的丢帧帧率标准——为了与模拟电视兼容Reddit: GhostOfSorabji 。
在视频编辑中,对齐帧率不同视频是极其困难的操作,而这个天大的难题只需更改录制设定(点击两三个按钮)即可解决。
图:不同帧率的对齐地狱,见Taran Van Hemert
此步骤涵盖了基本的视频打开过程,在实际情况下会因为软硬件,用户设定,以及操作系统逻辑的不同而有出入。
编码的标准 Encoding Standard 一般称为 coding 或 codec。其中 code 即代码,其末尾加 c 是一种名词化的形容词,如 politic/political,magic/magical,electric/electrical。
♙编码 | 全程 | 一般封装格式 |
---|---|---|
AV1 | AOMedia Video 1 | MP4,WebM,MKV |
AVC (H.264) | Advanced Video Coding | 3GP,MP4 |
H.263 | H.263 Video | 3GP |
HEVC (H.265) | High Efficiency Video Coding | MP4 |
MP4V-ES | MPEG-4 Video Elemental Stream | 3GP,MP4 |
MPEG-1 | MPEG-1 Part 2 Visual | MPEG,QuickTime |
MPEG-2 | MPEG-2 Part 2 Visual | MP4,MPEG,QuickTime |
Theora | Theora | Ogg |
VP8 | Video Processor 8 | 3GP,Ogg,WebM |
VP9 | Video Processor 9 | MP4,Ogg,WebM |
其中,“H.264”的 H 代表国际电信联盟 - 电信标准化部门(ITU‑T)中的 H 系列建议指南,例如 ITU-T H.810 个人健康系统(血压计、血糖仪、体重秤)的交互设计建议指南。一些符合某个 H 系列视频编码建议指南的视频编码器会将这个标号写在程序名字上,就有了所谓的 x264,x265。
由开发者定义,将函数或程序中的一些变量设为通过命令传递。命令行参数一般使用空格作为分隔符(也有用半角冒号,半角句号等其他情况),参数和参数值之间一般使用空格做分隔符(也有使用等于号的其他情况),多个参数值之间一般使用半角逗号或半角冒号分隔,而含有空格的参数值则使用半角直引号 "" 或 '' 连起来。
例如,x264 使用 CLI 参数的例子:
x264.exe --rc-lookahead 90 --bframes 12 --b-adapt 2 --me umh --subme 9 --merange 48 --no-fast-pskip --direct auto --weightb --keyint 360 --min-keyint 5 --ref 3 --crf 20 --qpmin 9 --chroma-qp-offset -2 --aq-mode 3 --aq-strength 0.7 --trellis 2 --deblock 0:0 --psy-rd 0.77:0.22 --fgo 10 --nr 4 --output ".\输出.mp4" ".\导入.mp4"
以及 ffmpeg 中使用 CLI 参数启用 libx264,通过 -x264-params
发送 API 参数的例子:
ffmpeg.exe -loglevel 16 -hwaccel auto -y -hide_banner -i ".\导入.mp4" -c:v libx264 -x264-params "rc-lookahead=90:bframes=12:b-adapt=2:me=umh:subme=9:merange=48:fast-pskip=0:direct=auto:weightb=1:keyint=360:min-keyint=5:ref=3:crf=20:qpmin=9:chroma-qp-offset=-2:aq-mode=3:aq-strength=0.7:trellis=2:deblock=0,0:psy-rd=0.77,0.22:nr=4" -fps_mode passthrough -c:a copy ".\输出.mp4"
ffmpeg 中,导入文件由 -i
参数完成,因为 ffmpeg 支持导入多个文件,而每个文件后跟随一些处理命令就需要较为严格的命令添加顺序,而 x264/5 这些编码器一般只是导入一个文件,所以在末尾加一个路径到文件的字符串就代表导入文件了。
图:使用命令行窗口启动视频压制命令后,视频编码器会给出大致这些信息
--参数
<开关 | 整数 A~B | 浮点 A~B | 其它格式,默认值,限制>说明信息,特点注解,推荐这个值,其它情况可设这个值。
在进程/软件之间通信的操作系统机制。在 CLI 中表现为两个程序的命令通过链接符 | 串联起来。常用于将上游程序/协议/函数输出的信息传递给下游程序/协议/函数实现过滤。最早的形式为 Unix Pipe。管道中程序/协议/函数的默认输入,输出与报错分别叫做 stdin,stdout,stderr,它们可以被手动指定到特定的路径,或作为管道传给更下游的程序/协议/函数。
管道中的程序同步运行,持续地传输上游输出到下游。适用于串流作业和处理流数据,包括视音频和文本流。
管道中的程序按顺序接力,一个程序/协议/函数跑完后再打开下一个。适用于处理对象化 Object-oriented 的数据,面向对象的应用程序。Windows PowerShell 使用了对象管道,所以不适合处理视音频流文件。如 Bash 下:for txt in *.txt; do md5sum $txt; done | awk '{print $2, $1}' | sort -bn
在不默认从 stdin 读取管道上游 stdout 的程序/协议/函数,以及不默认从 stdout 输出数据流的程序/协议/函数中,需要添加“-”以特别指定上游输出到 stdout,下游从 stdin 输入;还可以额外选择导出 stderr 到文本文件,就有了这样的命令:
ffmpeg -i <源> -an -f yuv4mpegpipe -strict unofficial - | x264 --y4m - --output "" 2> D:\文件夹\报错.txt
在 Advanced Video Coding AVC 中,帧的下级结构按照分辨率大小分为条带组 slice group → 条带 slice → 宏块 Macroblock → 块 block。从大小和功能上细分为:
而相对的,在帧之上的结构被称为图组 Group of pictures。每个 GOP 的创建取决于关键帧间隔设置以及转场判断,其中都包含了 IDR 帧,i 帧,P 帧,Pyramid-B 帧以及 b 帧。一个视频中最少由一个 GOP 组成,同视频长度下 GOP 的数量越多则视频体积越大,解码难度越低。
--keyint
参数和 --scenecut
参数决定--min-keyint
参数决定x264 首次引入了超过前后一帧长度的帧间参考范围。因此动态搜索也能更好的检查运动向量的时间一致性,从而减少动态噪点对动态搜索的干扰,同时提高了压缩。多参考帧不是越长越好,而是只要满足「一帧只要参考前后各 n 帧的信息就足以还原自身」的长度就是对的,而超过后会导致视频体积增加,同时画质降低。这个长度一般是前后各 3 帧,
最先启动,设立关键帧和参考帧,决定了 GOP 划分的初始编码步骤。决定了后续所有步骤的大纲:
--seek
参数指定的位置开始,顺序导入视频帧到 Lookahead 过程h->Lookahead->next->list
)会更新 Lookahead 起点。--no-open-gop
,且输入帧与之前的非 B 帧画面差距达到 --scenecut
阈值触发转场,则设立 IDR 帧以建立新的 GOP--min-keyint
范围内则设 I 帧)的前一帧会被强制改为 P 帧,以阻止 B 帧的双向参考特性--b-adapt
指定的算法和 --bframes
的最大连续 B 帧长度,区分出 P 帧和 B 帧,得到如 PBBBPBP 的序列--b-pyramid
参数允许连续 B 帧中的偶数帧作为参考帧使用,保证了长距离的连续 B 帧--ref
参数设定了参考帧的最远范围,使编码器不总选择成本最低的 B 帧--no-open-gop
,且当前 GOP 长度达 --min-keyint
大小,则设立 IDR 帧以建立新的 GOP--min-keyint
范围内则设 I 帧)的前一帧会被强制改为 P 帧,以阻止 B 帧的双向参考特性--rc-lookahead
参数指定的长度为一组,通过当前和未来两帧相减,得到差值,以大致分配压缩强度--min-keyint
<整数,默认 25,小于等于 keyint>判断新发现的转场距离上个 IDR 帧是否小于该值长短。有两种设定逻辑,而它们给出的画质都一样:
--keyint
<整数>一般设 9 倍于帧率(9 秒一个 IDR 帧),影响视频解码计算难度和拖进度条的延迟:
--ref
<整数 1~16, 推荐 3 或 \(1\%\times \text{fps} + 3.4\)>多参考帧前后帧数半径,一图流设 1。必须要在溯全尽可能多块的情况下降低参考长度,所以推荐 3:
--no-mixed-refs
<开关>关闭参考帧混合溯块(16×8,8×8 分块的参考)以提速,增加误参考。不推荐
--scenecut
<整数,不推荐用>Lookahead 中两帧差距达到该参数值则触发转场
--seek
<整数,默认 0>从第几帧开始压缩
--frames
<整数,默认全部>一共压缩多少帧
--fps
<整数或除法>设定输出视频帧率,只有源视频帧率错误才用得到。制动该参数后会自动开启 -force-cfr
--force-cfr
<开关>强制设定视频帧到整数时间码,可能用于对齐小数帧率的误差(如 23.976 或 24000/1001 变成 23.977)用
--fullrange
<开关,7mod x264 自动>启用 0~255 色彩范围,而不是默认的 16~235。视频内容永远不在使用有限色域设备/软件/视频网站下播放下可以考虑开启
Motion Estimation。用于在连续帧间进行运动估计。过程涉及逐个像素点(微观)在相邻帧之间寻找最小失真朝向/最小失真方向 Direction of minimal distortion DMD,从而在每帧之间都生成一张向量表。如果这个过程缺失或不够理想,参考帧与分块的建立就可能会出现问题,从而导致潜在的压缩率损失或画质下降。
图:宏块上帧间的动态向量
简化模型下,动态搜索得到帧间向量表,帧间向量表加上上帧的画面得到预测帧,原始帧减去预测帧得到残差帧,残差帧储存为参考帧,得到帧间结构。x264 使用了不对称多六边形搜索 Uneven multiple Hexagon,从而让一个搜索算法在多个分辨率下检查画面,制衡了动态噪点对传统动态搜索算法的干扰。搜索算法详见 x265 教程。
--me
<hex/umh/esa/tesa,推荐 umh> 搜索算法,umh 平衡,star 四角星搜索之后收益递减,sea 是优化过的 x264 esa 穷举,但收益递减仍大。umh 通过多种分辨率大小的查找范围,减轻了动态噪点对传统搜索算法的干扰
--merange
<整数,推荐 4 的倍数,需 me>完全取决于 ME 算法和分辨率,过大会因「找不到更好,找到也是错」而损失画质和压缩。
--no-fast-pskip
<开关,推荐开> 关闭跳过编码 P 帧的功能
--direct
<temporal/spatial/auto> 指定动态搜索判断方式的参数,除直播和低性能设备录屏外建议 auto
--no-chroma-me
<开关,推荐直播/录屏用> 跳过色度平面动态搜索,将亮度平面直接应用。可能对画质有略微负面影响
Sum of absolute transformed difference 为两个变换块间做差,取和,取绝对值的步骤:
注:为了简化所以写作 \(T(D(x,y))\),实际这样相当于每加一个像素值就要变换一遍
全称 Subpixel refinement。动态预测的精度最高只有 1px,在此之上还有可能被动态噪点干扰,导致了预测帧相比原画会欠缺大量的纹理细节。动态补偿 Motion Compensation MC 通过对比原画与预测块得到残差,并根据残差的分布动态向量的精度到¼子像素,使“精加工预测块”的画面残差尽可能地缩小,得到足够准确的预测帧,即大幅减少残差帧的内容。
图:根据动态搜索与补偿所得,完成宏块到块的细分
至于对抗动态噪点,大体上是允许真正移动的物件(所涵盖的分块)有运动向量,拦截噪点在静止画面上的孤立运动向量,即「允动之移,防静所变」解决,详见 x265 教程。
关于 FIR 插值滤镜,以及 x264/5 分别使用了哪些插值和搜索方法,见x265 教程网页版 - 动态补偿。
--subme
<整数 1~10,推荐 6~10>调整具体的动态补偿强度,x264 中同时决定模式决策和率失真优化的强度。根据画质和编码速度选择合适的大小:
--rd-refine
功能--rd-refine
功能--me hex
动态搜索检验对齐,需 --trellis 2 --aq-strength > 0
rd-refine
<嵌入 --subme 8
中,x265 中可手动打开> 率失真优化分析帧内预测的最佳量化和分块结果,耗时换压缩率和画质。x264 中还包括了最优动态向量的分析
--partitions
<字符串 p8x8,p4x4,b8x8,i8x8,i4x4/none/all,默认 p8x8,b8x8,i8x8,i4x4,推荐 all>允许的细分块种类。增加分块种类会增加计算负载,但 x264 放到现在来看,也只有高分辨率快速编码场景才需要保持默认。因此推荐 all
模拟信号转换为数字信号的主要步骤之一——将音量、亮度、温度、压力等信号整理为低频到高频的分量。具体来说,这个过程根据要处理的信号和用途不同,会使用傅里叶变换,小波变换,和 x264/5 使用的二维离散余弦变换 2D Discrete cosine transform。二维离散余弦变换利用预制的二维波形模具,通过穷举加减将源信号逐步分解成不同频率的平面波形,并合成变换块。图:缩放到 8x8 的波形分布,由于 cos(x) 的波形范围是 -1~1,所以图中的黑色到白色并不是 0~255 或 16~235,而是 -1~1
变换的过程中,“DCT 像素”称为系子 coefficients。这些系子的强度可以是负值,表示反相的波形;也可以是小数,表示低强度的波形(但因为计算机浮点计算慢于整数计算,所以一般仅用于演示)。变换块左上角的系数是直流 DC 分量,代表整体亮度水平,其余的系数是交流 AC 分量,表示图像中的细节和纹理信息。
每个频域分量都清点计算范围内所有像素值的“共鸣程度”,计为 DCT 频域系子的分量,得到变换块。
\[T(u,v) = \alpha(u) \alpha(v) \sum_{x=0}^{N-1} \sum_{y=0}^{N-1} f(x,y) \cos\left(\frac{(2x+1)u\pi}{2N}\right) \cos\left(\frac{(2y+1)v\pi}{2N}\right)\]
上式的 \(\sum_{x=0}^{N-1} \sum_{y=0}^{N-1}\) 部分。等同于:
for($x=0; $x<$N-1; $x++) { for($y=0; $y<$N-1; $y++) { $T.u+=...; $T.v+=... } }
因此,一个 2x2 块下,上式一共要计算 (\2^2\) 次,将每次的结果取和,在乘以归一化缩放值 \( \alpha(u) \) 和 \( \alpha(v) \) 完成变换。
RMS 是统计中常用的一种数据量化,用于表示一组数据平均值的平方根。对于一个包含 N 个值的数据集:\( \{ x_1, x_2, \ldots, x_N \} \)
\[ \text{RMS} = \sqrt{\frac{1}{N} \sum_{i=1}^{N} x_i^2} \]具体到 DCT 变换,对于 N×N 块 \( f(x,y) \) 的均方根可以表示为:
\[ \text{RMS}_{f(x,y)} = \sqrt{\frac{1}{N^2} \sum_{x=0}^{N-1} \sum_{y=0}^{N-1} f(x, y)^2} \]DCT 变换后,DCT 系子 \( T(u,v) \)的均方根为:
\[ \text{RMS}_{\text{DCT}} = \sqrt{\sum_{u=0}^{N-1} \sum_{v=0}^{N-1} C(u, v)^2} \]保证变换后,块的能量不变,所以通过 \( \alpha(u) \) 和 \( \alpha(v) \) 两个缩放值来对齐,使得 \( \text{RMS}_{\text{DCT}} = \text{RMS}_{f(x,y)} \):
\[ \alpha(u), \alpha(v) = \begin{cases} \frac{1}{\sqrt{N}} & \text{if } u,v = 0 \text{ (DC)} \\ \frac{1}{\sqrt{2N}} & \text{if } u,v \neq 0 \text{ (AC)} \end{cases} \]而在 JPEG 中:
使用上述 JPEG 的缩放值对齐
以上提供了两种变换,因为理论上只要能通过逆运算还原原来的 1-2-3-4 矩阵就算能用(当然量化矩阵也要跟着修改),且不同信号的编码可能会使用不同的变换算法。
简单地说,是根据不同的量化强度,块类型(亮度,色度,16x16,8x8,4x4)给出对应变换块的量化表/矩阵。将变换后的块点除量化矩阵,得到剩余 DCT 系子的块,从而减少高频的 DCT 系子分量,实现压缩。
Quantization Parameter 是 CRF,ABR 等码率质量控制模式算出,以及率失真优化量化、模式决策等步骤所调整的中间变量
Quantization Step-size 是 qp 于量化表中的映射值。规则是「qp 每 +1,则 qStep +0.125;qp 每 +6 则 qStep ×2,使其越往后增量越大」:
qp | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40… |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
qStep | 0.625 | 0.6875 | 0.8125 | 0.875 | 1 | 1.125 | 1.25 | 1.375 | 1.625 | 1.75 | 2 | 2.5 | 3.25 | 4 | 5 | 6.5 | 8 | 10 | 13 | 16 | 20 | 26 | 32 | 40 | 52 | 64… |
一串于特定位置换行的数字,用括号括起来得到。矩阵和矩阵之间可以根据情况选一种算法实现加减乘,和一种除法
两个矩阵之间,位置相对应的数相乘,得到新的矩阵。如果两个矩阵大小不一,则需要设定其它规则才能计算。
通过一种算法(此处为行列式)将矩阵坍缩为一个数字(标量)得到。
将乘数矩阵本身乘进被乘数矩阵中的每一个值得到:
两个大小相同矩阵下的一种常用的自定义点乘/内积算法。
x264 中,变换与量化会通过哈达玛积合并为一个矩阵表格,如 4x4 亮度块下为:
得到 qp 为 0,1,2,4,5 下的 4x4 块变换量化合并矩阵分别为:
回到量化本身,如 JPEG 8x8 亮度变换块的量化,就是普通的矩阵除法:
x264 中,量化值 qp 大致上存在于以下几处:
步骤 | 名称 | 应用 |
---|---|---|
率控制 | CRF/ABR | 逐帧 qp(或 cqp → 全局 qp) |
I-P 帧质量比 | I-P Ratio | P 帧 qp |
P-B 帧质量比 | P-B Ratio | B 帧 qp |
自适应量化 | Adaptive Quantzation AQ | 逐块 qp |
(率失真优化)模式决策 | Mode Decision MD | 逐块 qp |
率失真优化量化 | Rate-distortion optimized quantization RDOQ | 逐块 qp |
色度块 qp 偏移 | --chroma-qp-offset |
亮度与色度块 qp |
根据输入的质量设定参数,以及视频数据与人眼视觉的两种特性得到压缩强度——量化值 qp 的具体步骤。其中,视频数据已经分为了关键帧与参考帧(预测 + 残差)。根据这一性质就可以推断基础的质量差异,如:
--ipratio --pbratio
<浮点,默认 1.4、默认 1.3>P 帧相比 IDR/i 帧,以及 B/b 帧相比 P 帧的质量偏移。默认预设是给录像视频片源用的。
同时,“人眼视觉特性”代表人对明暗变化与画面细节程度的曲线感知。简单说就是人眼敏感于中低亮度的画面细节——应当非线性地根据亮度分配画面质量,以及画面细节损失的程度(量化压缩的强度)需要一个妥协平衡点——需要非线性地映射量化强度,共两个技术要求。具体的转换见 x265 教程网页版 - 率控制。
其结果就是通过 CRF/ABR 通过非线性的推演,再转换出线性的 qp 值。一般分为 1~17,18~23,和 24~69 三个阶段,分配到 qp 1~17 的画面算作低量化,分配到 qp 18~23 的画面算作中量化,分配到 qp 24~69 的画面算作高量化。
平面等本来就没有什么信息的分块就算经过高量化,也不会影响其画质;主要的损失出现在有无意地给内容复杂的纹理细节分块分配了高量化或降噪处理,导致了信息的损失。降噪处理影响画面细节的原因是噪点本身是突兀的像素值,所以只能用高频信息表示。
仅于本教程中使用以解释各种率控制模式搭配方法的概念。
全称 Constant Rate Factor。压制三角形下,距离妥协中心点最近的模式。因此也是压制最常用的模式。
--crf
<浮点范围 0~51,默认 23>据 cplxBlur,cutree,B 帧偏移给每帧分配各自 qp 的固定目标质量模式,或简称质量呼应码率模式,统称 crf。素材级画质设在 16~18,收藏~高压画质设在 19~20.5,YouTube 是 23。由于动画和录像的内容差距,动画比录像要给低点
全称 Average Bitrate。编码器自行判断量化程度,尝试压缩到用户定义的平均码率 average bitrate 上,速度最快
--bitrate
<整数 kbps>平均码率。若视频易压缩且码率给高,就会得到码率比设定的片子;反过来低了会不照顾画质强行提高量化,使码率达标。如果给太低则会得到码率不达标,同时画质差的片子。平均码率模式,除 2pass 分隔,一般推流用的"码率选项"就是这个参数,速度快但同时妥协了压缩
全称 Constant Quantizer Parameter
--qp
<整数 0~69,禁用 CRF/ABR/模式决策/率失真优化>设定全局量化强度。除非有既定目的,否则不建议使用。如果要手动指定特定范围的帧类型和量化值,则应使用 SBRC 下层模式
手动指定帧数片段,每个片段允许指定一种上层模式和一些控制参数。
--zones
<开始帧,结束帧,参数 A,参数 B…> 手动在视频中划区,采用不同上层模式来实现如提高压制速度,节省平均码率,提高特定画面码率等用途 (一般用来"处理"片尾滚动字幕). zones 内的 me, merange 强度/大小不能超 zones 外。可用参数有 b=, q=, crf=, ref=, scenecut=, deblock=, psy-rd=, deadzone-intra=, deadzone-inter=, direct=, me=, merange=, subme=, trellis=
--zones
内的场景使用当前 0~99999% 的码率,100% 相当于不变--qp
参数先用 CRF 模式分析整个视频总结可压缩信息,后根据 ABR 模式的码率限制统一分配量化值。有 pass 2 给特别高的平均码率,输出最小损失的最小体积近无损模式,以及 pass2 给码率硬限的全局整体压缩模式
--pass 1
<挡位,导出 stats 数据文件>
--pass 2
<挡位,导入 stats 数据文件>
--stats
<路径,默认在 x264/5 所在目录下>设定导出和导入 stats 数据文件的路径和文件名
说明见x265 教程网页版
--vbv-bufsize
<整数 kbps,默认关=0,小于 maxrate>编码器解出原画后,最多可占的缓存每秒。bufsize÷maxrate=播放时解码出每 gop 原画帧数的缓冲用时(秒)。值的大小相对于编完 GOP 平均大小。编码器用到是因为模式决策要解码出每个压缩步骤中的内容与原画作对比用。
--vbv-maxrate
<整数 kbps,默认关 0>峰值红线。用「出缓帧码率 - 入缓帧码率必≤maxrate"」限制编码器在 GOP 码率超 bufsize,即缓存跑满时压缩超载帧(提高 qp 值 + 强降噪至码率合规为止)。当入缓帧较小时,出缓帧就算超 maxrate 也会因缓存有空而不被压缩。所以有四种状态,需经验判断:
由于 gop 多样,4 种状态可以出现在同一视频中。buf/max 实际控制了这些状态的出现概率
--nal-hrd
<开关,默认关,需 VBV>开启假想对照解码器 Hypothetical reference decoder。与假想播放流程中得到额外的 VBV 控制信息,并写进每段序列参数集 sps 及辅助优化信息 sei 里,适合提高 VBV 控制精度
--ratetol
<浮点百分比,默认 1> maxrate 限码的容错程度,用于防止压缩过大,但与此同时码率过大所导致卡顿的次数会增加
手动通过文件制定帧类型和 qp 值。
--qpfile
<路径到文件>手动指定帧类型和 qp 值 closed-gop 下 K 帧的 frame type qp 下层模式。qpfile 文件内的格式为"帧号 帧类型 QP"
--no-open-gop
时代表 IDR 帧--open-gop
时代表 i 帧qpfile.txt 例:
可以搭配除 CQP 以外的上下层模式使用,决定了视频各处的最终量化值
--qpmin
<整数 0~51>由于画质和优质参考帧呈正比,所以仅高压环境建议设最高 14
--qpmax
<整数 0~51>在要用到颜色键,颜色替换等需要清晰物件边缘的滤镜时,可以设26防止录屏时物件的边缘被压缩的太厉害,其他情况永远不如关 --cutree/--mbtree
--chroma-qp-offset
<整数,默认 0>AVC 规定 CbCr 的码率之和应等于 Y 平面,所以 x264 会拉高色度平面的量化。
--psy-rd
后,x264 会自动设定 -2~-4。--psy-rd
时,动漫或幻灯片录屏片源的 4:2:0 视频可手动设 -2~-4--slow-firstpass
<开关>pass1 里自动关闭以下提速,或自动提高以下参数的强度,以保证 pass1 模式中 CRF 模式计算量化值的准确度:no-8x8dct me dia partitions none ref 1 subme <=2 trellis 0 fast-pskip
,可手动覆盖为强度更高的参数
一般情况下,用户要求在可接受的编码速度(fps 为单位)下,得到画质较高、文件体积较小的视频,构成了压制三角形。而不同的率控制模式,包括不同的视频编码器都会影响这一点。注意妥协点有三种:不省时,码率大,画质差,对应了三种不同的编码策略。
图:不同率控制模式权衡编码速度,画质,文件体积的能力不同,当然有的模式根本没得选
CRF/ABR 设定每帧量化值 qp 后,方差自适应量化 Variance adaptive quantizer VAQ 会将每帧的 qp 细化到块上。AQ 与 VAQ 存在混淆。方差 variance 代表差→方→和→均的计算顺序。将数据样本逐个与整体平均做差,以偏差之和窥数据之衡。乘方是方便正负数一起求和计算(算式左的σ也乘方,优化了正负号在二进制中的额外占用):
方差表示数据样本相对于整体平均值的离散程度,通过差→方→和→均的计算顺序,以偏差之和窥数据之衡。计算如下:
\[ \sigma^{2}=\frac{\sum_{i=1}^{N} (x_{i}-\overline{x})^{2}}{N} \]--aq-mode
<整数 0~3>据原画和 CRF/ABR 强度设定,码率不足时分配细分块 qp 值的策略
--aq-strength
的强度。推荐用于录像电影,或搭配 CRF 小于 17,高码率 ABR 等不会欠码的策略--aq-strength
<浮点>自适应量化强度,推荐搭配 --aq-mode
使用。如动漫和幻灯片录屏等平面多过纹理的场景下 --aq-mode 1 --aq-strength 0.8
, 2:0.9,3:0.7
由于 AVC 的环路滤波步骤中只有去块,所以叫去块滤波在此更准确。
修复“CRF/ABR 模式在某些场景的部分区域里分配量化值过高时,宏块间出现明显横纵割痕瑕疵”的平滑滤镜。编码器内去块利用了帧内帧间搜索到的信息,而理论上相比外部滤镜误判更少(当然外部滤镜也能做动态和帧内搜索)。去块大体上是检查 1 像素宽,且此块边缘没有较大像素值变化造成的横纵边缘(所以也存在误判)。块失真源自块间不统一的量化程度,有的块量化高流就会从邻近画面里凸现出来。而去块手段是平滑滤镜,因此要降低强度才适用于高码视频,动漫,素材录屏等锐利画面。边界强度 Boundary strength(去块力度判断)
图:取最小 8x8 范围(两个 4x4 分块)间的界线举例。
--deblock
<浮点偏移值,默认 1:0。推荐 0:0,-1:-1,-2:-1> 平滑强度:搜索精度。两值于原有强度上增减。
注:如果片源已有明显的边缘失真,模式决策优化反而需要减少,因为优化方向是尽可能保留原画,导致失真本身被当成细节
Rate distortion optimization,RDO。原本有损压缩视频编码器的策略就是码率越小越好——所以量化强度越大越好。但实际情况是量化压缩相当程度的破坏了 P-B 帧原本可以参考 I 帧的部分——因为量化后差异太大而只能放弃参考,换成 I 块。解决这种乱量化问题的方法是将失真,码率分别看成两种越大越差的程度;将其中一个程度乘以一个缩放值以对齐另一个(使两值权重对等)以相互牵制出平衡点。再将这个“新的程度”应用到原本的编码器策略里,就是率失真优化。
“编码器策略”就是模式决策。率失真程度由代价函数「开销=失真+λ⋅码率」(越小越好)得出:
\[J = D + \lambda \cdot R\]由于这个式子是一元一次函数( \(y = mx + b\) ),所以可画图表示为每个方案 J 作为位于 D,R 坐标系,斜度 λ 线上的点;其中失真 D 用平方差 SSE 或总差异 SAD 判断(SSE 多取一步平方,使较大的差异呈指数增长)进而分到更多补偿的码率。拉格朗日值 λ 源于 qp,即 crf,abr 指定的率失真斜度区间。qp 越大斜度越小:
图:率失真优化中λ的斜度变化与效果
图:率 - 失真表格中不断调整并得到“×”的实际效果
--fgo
<整数默认关,推荐 15 左右>将高频信号在量化前后的差距也算进率失真优化的统计中,使优化更倾向于保留细节和噪声
Psycho-visual optimization PVO 更类似于一种自适应量化,利用人类视觉系统的特性,通过掩蔽和感知量化量化,实现低码画面的码率再分配,保持高压缩的同时,提供更好的主观视觉质量。主观质量是建立在损失客观质量(与输入源的差距)上的质量。
--psy-rd
<a:b 浮点,默认 1:0>心理学优化设置。a 保留纹理,b 在 a 的基础上保留噪点细节,ab 值据画面复杂度拉高,
--no-mbtree
可将 b 设置为 0--no-psy
<开关>若视频量化很低,纹理清楚,没有优化的必要可以关。但大部分情况下不应该关,而是用较低的优化强度
图:心理视觉优化保留高频信号,同时压缩周围和其中的非高频信号
源自 libavcodec 以复杂动态场景的帧间参考少而应提高压缩,分码率给参考多而远的简单动态场景,以实现同码率下整体画质更高结果的逻辑。缺点则是动漫场景等「背景不动前景动」的场景被误压缩。说到底是处理精度低而非错误,应逐宏块应用这套逻辑,就有了 mbtree。量化值曲线缩放 quantizer curve compression 则被贬为控制 mbtree 等一系列 qp 分配算法中的一个缩放参数,见 desmos 互动例。
--qcomp
值设置初始复杂度百分比:
\[ \text{Complexity} = \left( \frac{\text{Count}_{MB}}{2} \right) ×700000^{\left( \frac{qcomp}{100} \right)} \div 100 \]
--qcomp
缩放模糊复杂度,以换算出当前帧的 qScale:
\[ \text{qScale} = \left( \text{Complexity}_{blurred} \right)^{1-qcomp} \]
--qcomp
<浮点范围 0.5~1,推荐默认 0.6>模糊复杂度 cplxBlur 以及 mbtree 迭代每帧 qp 值范围的曲线抑制参数。越小则复杂度迭代越符合实际状况,抑制 CRF,mb-cutree,bframes 影响的效果就越弱,搭配高 CRF 能使码率控制接近 VBV 的程度。越大则 CRF,mb-cutree,bframes 越没用,越接近 CQP
如果一个宏块用作帧间参考的码率比用作帧内参考低 70%,则该宏块可视为 30% 非帧间参考和 70% 帧间参考两部分。已知帧间参考占据的部分越多,则这个宏块自身就没有多少信息;而在宏块树所运行的时间,这个宏块是位于软转场 GOP 末尾——scenecut 步骤之后,keyint 步骤之前。因此,可以增强其压缩——把更多的码率分给参考传播最远的 I 帧,以提拔整个软转场 GOP 的画质。详见 x264 率控制算法 及 mbtree paper。
由于宏块树的步骤位于前瞻进程 Lookahead 中,而前瞻进程位于动态搜索和运动补偿之前,且 Lookahead 只使用半分辨率的视频帧,因此,此时的宏块树只能额外尝试简单的帧内和帧间预测。
宏块帧内和帧间的参考代价记为 \(\text{Cost}_{intra}\) 和 \(\text{Cost}_{inter}\),通过 Lookahead 中以下“搜索”步骤得到:
--rc-lookahead
开始,从远到近地累积所有宏块的 \( \text{Propagate}_{amount} \),作为统计列表中下一个宏块的 \( \text{Cost}_{propagate} \)
--rc-lookahead
开始,从远到近地根据已有的 \( \text{Cost}_{propagate} \) 和自身的信息量 \( \text{Cost}_{intra} \),通过 \( \log_{2}() \) 非线性地映射到 qp,得到宏块树中每个宏块的量化值偏移:
\[ \Delta \text{QP} = -\text{strength} \times \log_{2}\left( \frac{\text{Cost}_{intra}}{\text{Cost}_{propagate}} \right) \div \text{Cost}_{intra} \]
大部分情况下 mbtree 偏移值为零,因为宏块没有溯块信息可用
--rc-lookahead
<帧数量,范围 1~250,推荐 keyint÷2> 指定 cutree 的检索帧数,通常设在帧率的 2.5~3 倍。高则占用内存增加延迟,低则降低压缩率和平均画质。
注:mbtree/cutree 会自动选择 --rc-lookahead
和 \( \max\left( \text{keyint}, \max\left( \text{vbv-maxrate}, \text{bitrate}\right)\div\text{vbv-bufsize} \times \text{fps} \right) \) 中最小的值作为检索帧数
--no-mbtree
<开关> 关闭少见宏块量化偏移。可能只有近无损,--crf
小于 16 才用的到。
x264 教程中仅提及最简单的形式。完成的熵编码流程见 x265 教程网页版 - 熵编码。
曾经广泛应用于数据压缩的算法。步骤分为:
来源:geekforgeeks - greedy3 算法。假设第一次遍历文本得到了如下字符及其频率:
字符 | 频率 |
---|---|
A | 5 |
B | 9 |
C | 12 |
D | 13 |
E | 16 |
F | 45 |
字符 | 编码 |
---|---|
F | 0 |
C | 1-0-0 |
D | 1-0-1 |
A | 1-1-0-0 |
B | 1-1-0-1 |
E | 1-1-1 |
从上面的内容可见,熵编码是一种无损压缩(例如代码和小说都是文本,文本编码不可更改其内容)。既然是无损,那么不同的熵编码算法之间就只有编码速度和压缩率两个判断标准。x264 中使用了上下文自适应可变长度编码 Context Adaptive Variable Length Coding 和压缩率更高,速度慢一点的上下文自适应二进制算数编码 Context Adaptive Binary Arithmetic Coding CABAC。CABAC 的原理见 x265 教程网页版 - 熵编码
--no-cabac
<开关,不推荐>关闭 CABAC,使用 CAVLC
Residual DCT coefficients 代表变换后量化前,已知经过量化后会被抹除的 DCT 系子。DCT 变换的例子见本教程的 变换 - DCT 变换 部分。总之就是与“残差块”无关,只是都叫做残差而已。
Coded block flag 会被标在预测和/或与其相应的变换单元(亮度块加色度块)中表示该单元是否附有较多的残差系子:CBF=1 代表有、0 代表没有。引导四叉树 quadtree 算法进一步分枝——宏块向下分块。详见 US9749645B2。
图:四叉树的分块。见维基百科
由上可知,录像与电影片源中的动态噪点会直接干扰编码器的分块,导致熵编码总是要处理系子数量少的 8x8,4x4 分块,而 x264 设计时面向了 640x480 分辨率的视频,所以就有了专门用于避免无效分块,避免性能和熵编码压缩率被浪费的系子归零处理(现已淘汰但默认开启)。具体是:
--no-dct-decimate
<开关,默认关>关闭 DCT 变换的低强度系子归零操作,以减少细节损失,降低有损压缩。适合幻灯片录屏等画面极其干净,或经过大量滤镜过滤噪声,--crf < 17
或 ABR --bitrate > 500000
编码策略的源视频
死区,也叫 dead-band,netual-zone,或无作用区,代表输入到输出波形中可归零的部分。
图:信号死区设 0.5 时,输入到输出 y=x 波形的变化。见维基百科
死区量化器的用途同上。x264 中,--trellis
没有完全开启(2)时,死区量化器会被替代启用。默认设置下:
因此,结果是在高分辨率下,默认设置对画面细节的涂抹较强,所以一般建议 --trellis 2
,或在最少大于等于 1600x900 分辨率、--trellis < 2
的时候更改死区量化器相关参数的默认值。
--deadzone-inter
<整数 0~32,默认 21,--trellis
小于 2 时开启>一种逻辑简单的帧间再量化——细节面积小于死区就删掉,大就保留。一般用途建议 8,高画质建议 6
--deadzone-intra
<整数 0~32,默认 11,--trellis
小于 2 时开启>一种逻辑简单的帧间再量化——细节面积小于死区就删掉,大就保留。一般用途建议 8,高画质建议 4
Soft decision quantization / SDQ trellis 算法。通过限制量化后块中的 DCT 系子 coefficients 强度,甚至偏移当前系子的强度值到临近系子,以保证游程编码中走线的平稳。过程中由率失真计算确认对画面的影响符合预期质量,从而提高压缩率。--trellis
应用于量化步骤之后,并且对少数突兀的 DCT 系子强度做了平均化,所以叫“再量化”。详见 x265 教程 - 优化熵编码
--trellis
<整数,范围 0~2, 推荐 2>软判决优化 CABAC 的率失真再量化。
重复一开始说明的物理亮度:可见光电磁波的强度或振幅,以流明 lumen/lm,坎德拉/烛光量 candela/cd,或尼特 nits/cdm2 计量:
原本是高端音响的标准,代表最小音量下没有一点电流噪声,最大音量可以和真实场景媲美。与扬声器的大小和材质是否匹配场景相关,即「重硬件轻软件」。因为只要硬件达到 HDR 1000 规格,那么只要调高亮度就可以了;而随便一个中位水平的电视/显示器/手机屏幕亮度都能达到 HDR 400 标准。
注意高亮度的显示只适合电影和部分游戏场景,在工作学习用途下高亮度极其伤眼。
x264/5 皆支持的元数据设置。但因为 HDR 分为硬件标准,软件标准,以及数据标准,所以很乱。为了保证色彩正确,必须参考片源的元数据。如:
图 1: cll 1000,640. master-display 由 G(13250…) 开头,L(10000000,1) 结尾
图 2: cll 1655,117/L(40000000,50)/colorprim bt2020/colormatrix bt2020nc/transfer smpte2084
--cll
<最大内容光强,最大平均光强>压制 HDR 源一定照源视频信息设,找不到不要用,见上图例。
--colorprim
<字符>播放用三原色 (以及白点) 指标,查看视频信息可知:bt470m,bt470bg,smpte170m,smpte240m,film,bt2020,smpte428,smpte431,smpte432。如图 1 为 bt.2020。
--colormatrix
<字符>播放用矩阵格式/系数指标:fcc,bt470bg,smpte170m,smpte240m,GBR,YCgCo,bt2020c,smpte2085,chroma-derived-nc,chroma-derived-c,ICtCp。
注:不支持 bt2020nc
--transfer
<字符>传输特质:bt470m,bt470bg,smpte170m,smpte240m,linear,log100,log316,iec61966-2-4,bt1361e,iec61966-2-1,bt2020-10,bt2020-12,smpte2084,smpte428,arib-std-b67。
上图图 2 的 PQ 即 st.2084 的标准,所以参数值为 smpte2084。
--master-display
<G(x,y)B(,)R(,)WP(,)L(,)(绿,蓝,红,白点,光强)>写进 SEI 信息里,告诉解码端色彩空间/色域信息用
--preset
<ultrafast/superfast/veryfast/faster/fast/medium/slow/slower/veryslow/placebo>见下:
参数\预设 | ultrafast | superfast | veryfast | faster | fast | medium | slow | slower | veryslow | placebo |
---|---|---|---|---|---|---|---|---|---|---|
b-adapt | 0 | 默认 1 | 2 | |||||||
bframes | 0 | 默认 3 | 8 | 16 | ||||||
direct | 默认 spatio | auto | ||||||||
me | dia | 默认 hex | umh | tesa | ||||||
merange | 默认 16 | 24 | ||||||||
partitions | none | i8x8,i4x4 | 默认 p8x8,b8x8,i8x8,i4x4 | all | ||||||
rc-lookahead | 0 | 10 | 20 | 30 | 默认 40 | 50 | 60 | |||
ref | 1 | 2 | 默认 3 | 5 | 8 | 16 | ||||
subme | 0 | 1 | 2 | 4 | 6 | 默认 7 | 8 | 9 | 10 | 11 |
trellis | 0 | 默认 1 | 2 | |||||||
weightp | 0 | 1 | 默认 2 | |||||||
no-weightb | 1 | 默认 0 | ||||||||
no-8x8dct | 1 | 默认 0 | ||||||||
no-cabac | 1 | 默认 0 | ||||||||
no-deblock | 1 | 默认 0 | ||||||||
no-mbtree | 1 | 默认 0 | ||||||||
no-mixed-refs | 1 | 默认 0 | ||||||||
scenecut | 0 | 默认 40 | ||||||||
no-fast-pskip | 默认 0 | 1 | ||||||||
slow-first-pass | 默认 0 | 1 |
--tune
<zerolatency/animation/grain/film/fastdecode/psnr/ssim>更改 preset 的一些参数,见下:
--bframes 0 --force-cfr --no-mbtree --sync-lookahead 0 --sliced-threads --rc-lookahead 0
--deblock -2:-2 --psy-rd <跳过>:0.25 --aq-strength 0.5 --no-dct-decimate --deadzone-inter 6 --deadzone-intra 6 --ipratio 1.1 --pbratio 1.1 --qcomp 0.8
--ref <若当前设定大于 1 则乘以 2> --bframes <当前设定值 +=2> --deblock 1:1 --psy-rd 0.4:<跳过> --aq-strength 0.6
--no-deblock --no-cabac --no-weightb --weightp 0
--deblock -1:-1 --psy-rd <跳过>:0.15
--deblock -3:-3 --psy-rd 2.0:0.7 --aq-strength 1.2
--aq-mode 0 --no-psy
--tune psnr
缓和一些
--aq-mode 2 --no-psy
不同的算法和数据决定了不同的多线程优化性能。量化的步骤中,进程之间几乎不需要共享数据,进程占用和运算速度也不变;而冗余的步骤中则是反过来——占用可大可小,速度忽快忽慢,也需要进程间共享一定数据/内存。可以说如果想要让进程吃满更多核心,就得尽可能减少搜索冗余相关算法的强度。x264 编码器一共会占用 --threads
加 --lookahead-threads
条进程。而 --threads
达到并超过 16~24 时,可以看到一定的画质下降,以及在更多核心的电脑上出现“吃不满”的问题,这就是 x264 中冗余算法的优化极限了。
因此,设置创建比电脑处理器更多的线程只会从任务数量上冲淡如各个冗余步骤需要“等到之前步骤给出结果才能运行”的时间窗口,甚至有时等不到就跳过,导致码率增加,画质降低,得不偿失。
x264 并没有对多路/多 CPU 节点电脑优化,但 x265 使用线程池 实现了。
--threads
<整数,建议保持默认(等于 CPU 线程)>由于参考帧步骤要等其之前的步骤算完才开始,所以远超默认的值会因为处理器随机算的特性而降低参考帧的计算时间,使码率增加,画质降低,速度变慢
--non-deterministic
<开关,默认关,推荐开> 降低多线程完算性——减少多线程共享数据的可靠性,些微提高画质。使用后每个进程的冗余判断更为独断,且让新的动态搜索线程得知「旧动态搜索线程线程实际搜素过,而非参数设定」的区域。「完算性」一般仅代表通过完整计算得到结果,而不是提前跳过的计算特征。而启用多线程,VBV 都会降低完算性
--lookahead-threads
<整数,建议保持默认(应该是 --threads
的 1/4)>指定前瞻进程占用的线程数,速度太快则其后的编码进程跟不上,太慢则其后的编码进程要等结果,所以不需要改动
--frame-threads
<整数,建议保持默认(自动)>指定 --threads
中分配多少线程给编码帧,决定一次同时编码多少帧(量化,优化,帧内预测,熵编码)。剩下则是上下游的处理(连续 B 帧推演,SEI,完算性错误管理),后者占用较少
--sliced-threads
<开关,默认关>逐条带分配多线程。x264 r1607 前的多线程分配机制,后来因为问题太多而改成了逐帧分配多线程。剩下直播录屏等场景降低延迟一个用途
退一步讲,若能占满全部 CPU 核心,那么也算是实现了多线程优化。因此,关于“最大化利用 CPU 核心数量很多的电脑并提升画质”的平价方法就是多开几个编码,并限制每个编码占用的 CPU 线程数实现。例如 Windows 批处理提供的 START
命令实现异步并行(多开些编码),搭配上述的 --threads
命令限制每个编码的进程数实现。
x264/5 中,理论画质与性能最平衡的多线程数实际是 4,所以若设定 --threads 4
,则 --lookahead-threads
等于 1。得到共 5 个线程占用。
此外还有一种难办的情况:游戏录屏。这会导致编码进程与其它进程争夺 CPU 或内存资源。后者可以通过升级内存解决,但前者不同的地方在于“多线程优化越好则越糟”——因为软件开发也遵循了“应该占满全部 CPU 核心”的逻辑,因此当 CPU 的算力或核心数没有超过两个程序占用加起来的峰值,就只能保护其中优先级较高的进程了。另一边,多人游戏的反作弊机制和防盗版机制的升级也增加了游戏对 CPU 和内存的压力。
此时,“冗余”步骤的不稳定占用很可能会超出 CPU 算力极限导致卡顿(除非内存或散热不好,否则不会死机),因此要适当降低冗余强度来保证流畅(但需要一定经验并花费时间测试)。大多数人应对这种情况最简单的方案只有使用显卡或核显/SoC“附赠”的硬件视频编码器,或者购置高端些的视频采集卡两种方法实现;但如果 CPU 的算力足够同时流畅运行大型游戏和视频编码器,则可以参考附录:急用版 x264 教程配置 OBS 录屏的一些方案。
--nr
<整数 0~65536,降噪范围 100~1000,不推荐>当 ABR/VBV 指定了高于 --qpmax
或默认最大 qp 值时,会调用这个滤镜。如果有降噪需求则建议使用效果更好的外部滤镜工具,或至少使用 --vf hqdn3d
滤镜
--vf
<crop:[←],[↑],[→],[↓]/pad: [←],[↑],[→],[↓]/resize:[宽,高],[变宽比],[装盒],[色度采样],[缩放算法/select_every:步,帧,帧…]/hqdn3d:[空域 Y 降噪强度],[空域 C 降噪强度],[降噪时域 Y 强度],[时域 C 降噪强度]/yadif[模式],[顺序]>裁剪,加边,缩放/更改分辨率,删除/保留视频帧,降噪,色彩空间转换滤镜。例:
--sub
导入字幕文件,然后使用 --vf subtitles
参数渲染字幕到视频这些滤镜可以在实现简单的画面处理。使用多个滤镜的例子如:--vf crop:10,0,10,0/resize:640,480,,,,lanczos
。
--vf hqdn3d
则使用默认强度(仅开启滤镜)为 4,3,6,4.5--sub
<路径到文件,需 --vf subtitles
和 VSFilter64.dll>导入字幕文件,
恒定帧率的视频播放和剪辑都最具兼容性。可变帧率有助于解决手机录像时的发热和耗电速度快的问题,同时,将可变帧率转换为恒定帧率以正常剪辑视频时则需要重新编码。因此,录制视频时应根据设备的电量和散热能力进行选择,而录制需要剪辑的素材时则应选择恒定帧率。
可变帧率转恒定帧率(60fps)需要借助外部滤镜完成。如 ffmpeg:
ffmpeg -i <输入> -vsync cfr -y -vf fps=60 -c:a copy -f yuv4mpegpipe - | x264 <参数> - --demuxer y4m --output <输出.mp4>
由于视频元数据里也有着标错的情况,所以用 MediaInfo 等工具查看到视频帧率是 Variable 时,还要用播放器逐帧查看,或者用 ffprobe 检测。见 ffprobe 教程
并没有特别好的选择。尤其是当能够使用 CLI 参数命令 ffmpeg.exe,x264.exe 后。
Shana Encoder |
ffmpeg-CLI 搭配部分 GUI,上手较慢。使用了 ffmpeg 内嵌的 libx264,libx265,NVEnc |
|
---|---|---|
Simple x264 Launcher | 内嵌 AviSynth,支持便携版 VapourSynth,额外支持 x265 和 NVEnc 编码器,适合批量压制 | |
小丸工具箱 | 操作简单,适合入门的中文软件。网上能搜到详细教程。内嵌 MediaInfo,mp4box,Mkvtoolnix 镜像:百度云 提取码"crhu" |
ffmpeg | 强大的 CLI 开源视音频处理工具。几乎所有的视音频处理都绕不开 | |
---|---|---|
mpv | 开源,支持便携的现代视频播放器。见 安装与配置教程 | |
Voukoder | 开源 Premiere Vegas After Effects 压制导出插件,分为 Voukoder 和 V-Connector 两部分 | |
OBS | 强大的开源直播框架和软件,设置略比传统录屏软件复杂,但效果也更好 | |
MediaInfo | 开源的 GUI 媒体元数据/视音频格式读取器,用于配置正确的压制参数 |
|
ffprobe | CLI 视音频格式读取器,若检测所得信息与 MediaInfo 所异,则优先参考 ffprobe 见基本使用,以及搭配 Excel 的视频数据可视化教程 |
Patman | 支持 FFMS2 Lavf 编解码 [8~10bit] |
---|---|
LigH | 支持 FFMS2 Lavf 编解码 [8~10bit] |
jspdr (tMod) | 支持 FFMS2 Lavf 编解码,MCF 线程管理库 |
x264 7mod | 支持 FFMS2 Lavf 编解码,支持 hqdn3d 降噪,镜像链接:谷歌盘/百度云 |
Komisar KMod | 支持 FFMS2 编解码 [8][10]bit |
将编码前后的视频窗口至于同屏下,使用截图软件截图,再使用取色器测量特定区域的颜色:
colormatrix=源矩阵:目标矩阵
参数转换一段原视频做测试复现:ffmpeg.exe -i "偏色前.mp4" -vf "colormatrix=bt709:bt601" -c:v libx264 -c:a copy -c:s copy "D:\Desktop\转601.mkv"