使用 FFmpeg 通过 VP9 进行实时编码
编码参数
VP9 会提供一系列参数来优化实时编码。比特率模式中讨论了这些方面的一些广泛原则。
FFmpeg VP9 编码示例
下表介绍了针对 VP9 编码的示例 ffmpeg
调用的参数。
参数 | 说明 |
---|---|
-quality realtime |
realtime 对于直播和速度超过 5 而言至关重要。 |
-speed 6 |
直播/实时编码应使用速度从 5 到 8 之间的数字。数字越小(5 或 6 ),说明质量越高,但占用的 CPU 越多。数字越大(7 或 8 ),画质会降低,但对于延迟较低的使用场景以及 CPU 较低的设备(例如移动设备)也更容易管理。 |
-tile-columns 4 |
平铺操作会将视频拆分为矩形区域,以支持多线程编码和解码。平铺图片数量始终是 2 的幂。0 = 1 个图块,1 = 2,2 = 4,3 = 8,4 = 16,5 = 32。 |
-frame-parallel 1 |
启用并行可解码功能。 |
-threads 8 |
要使用的线程数上限。 |
-static-thresh 0 |
移动侦测阈值。 |
-max-intra-rate 300 |
最大 iframe 比特率 (pct) |
-deadline realtime |
-quality realtime 的备用(旧版)版本 |
-lag-in-frames 0 |
延迟的帧数上限 |
-qmin 4 -qmax 48 |
量化器的最小值和最大值。此处的值只是建议值,调整此值有助于以压缩效率为代价来提升/降低视频质量。 |
-row-mt 1 |
启用行多线程处理。允许将最多 2 倍的线程用作图块列。0 = 关闭,1 = 开启。 |
-error-resilient 1 |
启用错误恢复功能。 |
选择编码参数
以下信息使用恒定比特率 (CBR) 编码进行实时自适应比特率流式传输 (ABR),其中每个目标速率在打包器清单中明确设置。这样可以在客户端之间更清晰地“切换”费率。如果比特率更灵活或对编码进行分块,也可使用可变比特率 (VBR) 编码和 CQ 模式。Q 模式不支持实时视频所需的实时编码。如需了解详情,请参阅比特率模式。
还建议您参阅有关 VOD 设置的随附文章,但要详细了解如何操控 VP9,但应重点关注 CBR。
提示和技巧
请记住,进行直播时,所有内容都被限制在 1 倍的最低实时编码速度(FFmpeg 会报告编码进度)。如果您的编码速度低于 1 倍,那么编码过程将不能跟上直播视频的输入,并且用户将需要缓冲,并且传输中断会导致直播在直播期间无法使用(尽管归档通常可以使用)。
编码参数的实际应用示例
下面显示了在搭载 Linux 的四核 i5 3.6Ghz 桌面设备上,各种帧尺寸的 CPU 利用率(25 fps):
目标解决时间 | FFmpeg VP9 参数 | CPU / 速度(示例) |
---|---|---|
3840x2160 (2160p) | -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-Parallel 1 -qmin 4 -qmax 48 -b:v 7800k - | ~88% 0.39 倍 |
2560x1440 (1440p) | -r 30 -g 90 -s 2560x1440 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-Parallel 1 -qmin 4 -qmax 48 -b:v 6000k - | ~86% 0.68 倍 |
1920x1080 (1080p) | -r 30 -g 90 -s 1920x1080 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-Parallel 1 -qmin 4 -qmax 48 -b:v 4500k - | 约 82% 1.04 倍 |
1280x720 (720p) | -r 30 -g 90 -s 1280x720 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-Parallel 1 -qmin 4 -qmax 48 -b:v 3000k - | 约 78% 1.77 倍 |
854x480 (480p) | -r 30 -g 90 -s 854x480 -quality realtime -speed 6 -threads 4 -row-mt 1 -tile-columns 1 -frame-Parallel 1 -qmin 4 -qmax 48 -b:v 1800k - | 约 64% 3.51x |
640x360 (360p) | -r 30 -g 90 -s 640x360 -quality realtime -speed 7 -threads 4 -row-mt 1 -tile-columns 1 -frame-Parallel 0 -qmin 4 -qmax 48 -b:v 730k - | 大约 62% 5.27 倍 |
426x240 (240p) | -r 30 -g 90 -s 426x240 -quality realtime -speed 8 -threads 2 -row-mt 1 -tile-columns 0 -frame-并行跟踪 0 -qmin 4 -qmax 48 -b:v 365k | 约 66% 8.27x |
FFmpeg 示例可能如下所示:
ffmpeg -stream_loop 100 -i /home/id3as/Videos/120s_tears_of_steel_1080p.webm \
-r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 \
-tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k -c:v vp9 \
-b:a 128k -c:a libopus -f webm pipe1
提示和技巧
请注意,我们将输出到 FIFO 管道 ("que1.pipe1"),该管道应在执行 FFmpeg 命令之前执行。为此,请在工作目录中提供命令
mkfifo pipe1
。使用 Shaka Packager 时,它将监听该管道作为给定流的输入源。其他打包模型可能需要不同的方法。要确保系统能够识别
-row-mt
命令,请使用 https://www.ffmpeg.org/download.html 中最新的 FFmpeg(目前为 3.3.3)版本
自适应比特率集示例
根据运行 FFmpeg 编码的机器的力量,它可以同时提供以下所有编码,也可能不会同时提供以下编码,因此应该从列表中选择适合自己的可用资源和目标对象群组的子集。
FFmpeg 完整 ABR 设置
在理想情况下,我们会合并上一部分中列出的编码示例,以创建可同时生成所有这些示例的单个命令:
ffmpeg -stream_loop 100 -i lakes1080p.mp4 \
-y -r 25 -g 75 -s 3840x2160 -quality realtime -speed 5 -threads 8 \
-tile-columns 2 -frame-parallel 1 \
-b:v 7800k -c:v vp9 -b:a 196k -c:a libopus -f webm pipe1 \
-y -r 25 -g 75 -s 2560x1440 -quality realtime -speed 5 -threads 8 \
-tile-columns 2 -frame-parallel 1 \
-b:v 6000k -c:v vp9 -b:a 196k -c:a libopus -f webm pipe2 \
-y -r 25 -g 75 -s 1920x1080 -quality realtime -speed 5 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 4500k -c:v vp9 -b:a 196k -c:a libopus -f webm pipe3 \
-y -r 25 -g 75 -s 1280x720 -quality realtime -speed 5 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 3000k -c:v vp9 -b:a 196k -c:a libopus -f webm pipe4 \
-y -r 25 -g 75 -s 854x480 -quality realtime -speed 6 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 2000k -c:v vp9 -b:a 196k -c:a libopus -f webm pipe5 \
-y -r 25 -g 75 -s 640x360 -quality realtime -speed 7 -threads 2 \
-tile-columns 1 -frame-parallel 0 \
-b:v 730k -c:v vp9 -b:a 128k -c:a libopus -f webm pipe6 \
-y -r 25 -g 75 -s 426x240 -quality realtime -speed 8 -threads 2 \
-tile-columns 1 -frame-parallel 0 \
-b:v 365k -c:v vp9 -b:a 64k -c:a libopus -f webm pipe7
不过,上述完整集需要一个非常强大的 CPU,或者可能需要从硬件 GPU 分流(如一些芯片组越来越多提供)支持。Intel Kabylake(及更高版本)拥有完整的硬件编码管道。(请注意,Kabylake GPU 可以执行 8 位 VP9 编码,但不能执行 10 位编码)。
使用 Shaka Packager 的实用桌面示例
如需常见桌面设备的实用示例,您可以使用 Shaka Packager。设置 Shaka 的一种简单方法是使用 Google 的 DockerHub 映像将其安装在 Docker 容器中。相关说明位于以下位置:
https://github.com/google/shaka-packager#using-docker-for-testing--development
在此示例中,我们使用的机器采用以下配置:
系统 | 主机:obs 内核:4.4.0-91-lowlatency x86_64(64 位) |
桌面设备 | Xfce 4.12.3 发行版:OS:https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/ |
CPU | 四核 Intel Core i5-6500 (-MCP-) 缓存:6144 KB 时钟速度:最大:3600 MHz 1:800 MHz 2:800 MHz 3:800 MHz 4:800 MHz |
显卡 | Intel Skylake 集成显卡 |
内存 | 8GB RAM |
实际上,该机器能够以最佳方式生成以下可用的 ABR 编码范围,FFmpeg 会始终报告 1 倍的编码速度:
ffmpeg -stream_loop 100 -i 120s_tears_of_steel_1080p.webm \
-y -r 30 -g 90 -s 1920x1080 -quality realtime -speed 7 -threads 8 \
-row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 4500k -c:v vp9 -b:a 128k -c:a libopus -f webm pipe1 \
-y -r 30 -g 90 -s 1280x720 -quality realtime -speed 8 -threads 6 \
-row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 3000k -c:v vp9 -b:a 128k -c:a libopus -f webm pipe2 \
-y -r 30 -g 90 -s 640x360 -quality realtime -speed 8 -threads 2 \
-row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 730k -c:v vp9 -b:a 128k -c:a libopus -f webm pipe3
请注意,-speed
设置的值非常高。这些设置是实验性的,会因机器而异。
Shaka 软件包开销开销
封装不是占用大量 CPU 资源的 Activity。可以将 Shaka Packager 设置为监听所有输出,即使 FFmpeg 只分发了一部分也是如此。以下是在上文所述的机器上测试的打包器设置:
packager \
in=pipe1,stream=audio,init_segment=livehd-audio-1080.webm,segment_template=livehd-audio-1080-\$Number\$.webm \
in=pipe1,stream=video,init_segment=livehd-video-1080.webm,template=livehd-video-1080-\$Number\$.webm \
in=pipe2,stream=audio,init_segment=livehd-audio-720.webm,segment_template=livehd-audio-720-\$Number\$.webm \
in=pipe2,stream=video,init_segment=livehd-video-720.webm,template=livehd-video-720-\$Number\$.webm \
in=pipe3,stream=audio,init_segment=livehd-audio-360.webm,segment_template=livehd-audio-360-\$Number\$.webm \
in=pipe3,stream=video,init_segment=livehd-video-360.webm,template=livehd-video-360-\$Number\$.webm \
--mpd_output livehd.mpd --dump_stream_info --min_buffer_time=10 --time_shift_buffer_depth=300 \
--segment_duration=3 --io_block_size 65536