(FFmpeg) VP9 Vaapi 从给定的官方 ffmpeg 示例编码到 .mp4 或 .webm 容器
(FFmpeg) VP9 Vaapi encoding to a .mp4 or .webm container from given official ffmpeg example
我正在尝试实现vp9 硬件加速编码过程。我按照 ffmpeg 官方 github 的示例 (Here -> vaapi_encode.c).
但给出的示例仅将 .yuv 文件保存到 .h264 文件,我想将帧保存到 .mp4 或 .webm 容器。以及具备品质把控能力等等
我不是从文件中读取帧,而是从实时源中收集帧。当从实时源中获得完整的 5 秒帧时,使用 vp9_vaapi 将这些帧编码为 5 秒 .mp4 文件。
我能够将我的实时供稿中的所有 5 秒帧保存到 .mp4 或 .webm 文件,但它们无法正确播放(更准确地说:继续加载,然后我打开)。
官网示例结果:
cpu 编码的 vp9 .mp4 文件结果:
编辑:
结果
您将需要直接使用 FFmpeg,如果您在 vp9_vaapi
编码器中启用 B 帧,您可以选择在同一命令行中添加 vp9_superframe and the vp9_raw_reorder bitstream filters。
示例:
ffmpeg -threads 4 -vaapi_device /dev/dri/renderD128 \
-hwaccel vaapi -hwaccel_output_format vaapi \
-i http://server:port \
-c:v vp9_vaapi -global_quality 50 -bf 1 \
-bsf:v vp9_raw_reorder,vp9_superframe \
-f segment -segment_time 5 -segment_format_options movflags=+faststart output%03d.mp4
根据需要调整输入和输出paths/urls。
此命令的作用:
它将通过 segment muxer 创建 5 秒长的 mp4 片段。
查看 movflags=+faststart
的用法,以及如何通过上面的 -segment_format_options
标志将其作为格式选项传递给底层 mp4 多路复用器。
片段长度可能不正好是 5 秒长,因为每个片段开始(被剪切)(带有)一个关键帧。
但是,我不建议在该编码器中启用 B 帧,因为这些比特流过滤器会产生其他不良影响,例如 mucking around with the encoder's rate control and triggering bugs like this one。这在生产环境中是不可取的。这就是为什么下面的脚本没有启用该选项,而是直接在编码器选项中定义设置速率控制模式。
如果您需要利用 1:N VAAPI 编码,请使用这些片段:
- 如果需要去隔行扫描,调用
deinterlace_vaapi
滤镜:
ffmpeg -loglevel debug -threads 4 \
-init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi \
-hwaccel_device va -filter_hw_device va \
-hwaccel_output_format vaapi \
-i 'http://server:port' \
-filter_complex "[0:v]deinterlace_vaapi,split=3[n0][n1][n2]; \
[n0]scale_vaapi=1152:648[v0]; \
[n1]scale_vaapi=848:480[v1];
[n2]scale_vaapi=640:360[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 没有去隔行:
ffmpeg -loglevel debug -threads 4 \
-init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi \
-hwaccel_device va -filter_hw_device va -hwaccel_output_format vaapi \
-i 'http://server:port' \
-filter_complex "[0:v]split=3[n0][n1][n2]; \
[n0]scale_vaapi=1152:648[v0]; \
[n1]scale_vaapi=848:480[v1];
[n2]scale_vaapi=640:360[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 1750k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 1000k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 使用英特尔的 QuickSync(在支持的平台上):
在 Intel Icelake 及更高版本上,您可以使用具有以下已知限制的 vp9_qsv
编码器包装器(目前):
(一)。您必须启用 low_power mode
,因为 iHD
驱动程序目前仅公开 VDENC 解码路径。
(b)。 MSDK 不支持编码选项 1 和 extra_data。
(c)。 MSDK默认会插入IVF头,但FFmpeg不需要,默认禁用。
请参阅以下示例:
- 如果需要去隔行扫描,调用
vpp_qsv
滤镜:
ffmpeg -nostdin -y -fflags +genpts \
-init_hw_device vaapi=va:/dev/dri/renderD128,driver=iHD \
-filter_hw_device va -hwaccel vaapi -hwaccel_output_format vaapi
-threads 4 -vsync 1 -async 1 \
-i 'http://server:port' \
-filter_complex "[0:v]hwmap=derive_device=qsv,format=qsv,vpp_qsv=deinterlace=2:async_depth=4,split[n0][n1][n2]; \
[n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
[n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
[n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 没有去隔行:
ffmpeg -nostdin -y -fflags +genpts \
-init_hw_device vaapi=va:/dev/dri/renderD128,driver=iHD \
-filter_hw_device va -hwaccel vaapi -hwaccel_output_format vaapi
-threads 4 -vsync 1 -async 1 \
-i 'http://server:port' \
-filter_complex "[0:v]hwmap=derive_device=qsv,format=qsv,split=3[n0][n1][n2]; \
[n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
[n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
[n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 1750k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 1000k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
请注意,我们使用 vpp_qsv filter
并将 async_depth
选项设置为 4。与使用 scale_qsv
和 deinterlace_qsv
相比,这极大地提高了转码性能。参见 FFmpeg 的 this commit git.
注意:如果您使用QuickSync路径,请注意,如果您系统上的Media SDK库支持,MFE(多帧编码模式)将默认启用。
用于推导上述代码片段的公式:
最佳bufsize:v = 目标比特率(-b:v 值)
将 GOP 大小设置为:2 * fps(GOP 间隔设置为 2 秒)。
我们通过 -threads:v
限制视频编码器的线程数,以防止 VBV 溢出。
使用的分辨率阶梯:16:9 中的 640p、480p 和 360p,参见 this link。
根据需要进行调整。
根据需要替换上面的变量($output_path{0-2}
、输入等)。
测试并反馈。
当前观察:
在我的系统上,我能够使用 VP9 使用 Apple's recommended resolutions and bit-rates for HEVC encoding for HLS 作为基准实时编码多达 5 个流。系统负载等见下图
平台详情:
我在 Coffee-lake 系统上,为此工作流程使用 i965
驱动程序:
libva info: VA-API version 1.5.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_5
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.5 (libva 2.4.0.pre1)
vainfo: Driver version: Intel i965 driver for Intel(R) Coffee Lake - 2.4.0.pre1 (2.3.0-11-g881e67a)
vainfo: Supported profile and entrypoints
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Simple : VAEntrypointEncSlice
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileH264MultiviewHigh : VAEntrypointVLD
VAProfileH264MultiviewHigh : VAEntrypointEncSlice
VAProfileH264StereoHigh : VAEntrypointVLD
VAProfileH264StereoHigh : VAEntrypointEncSlice
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileVP8Version0_3 : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile0 : VAEntrypointEncSlice
VAProfileVP9Profile2 : VAEntrypointVLD
我的 ffmpeg 构建信息:
ffmpeg -buildconf
ffmpeg version N-93308-g1144d5c96d Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
configuration: --pkg-config-flags=--static --prefix=/home/brainiarc7/bin --bindir=/home/brainiarc7/bin --extra-cflags=-I/home/brainiarc7/bin/include --extra-ldflags=-L/home/brainiarc7/bin/lib --enable-cuda-nvcc --enable-cuvid --enable-libnpp --extra-cflags=-I/usr/local/cuda/include/ --extra-ldflags=-L/usr/local/cuda/lib64/ --enable-nvenc --extra-cflags=-I/opt/intel/mediasdk/include --extra-ldflags=-L/opt/intel/mediasdk/lib --extra-ldflags=-L/opt/intel/mediasdk/plugins --enable-libmfx --enable-libass --enable-vaapi --disable-debug --enable-libvorbis --enable-libvpx --enable-libdrm --enable-opencl --enable-gpl --cpu=native --enable-opengl --enable-libfdk-aac --enable-libx265 --enable-openssl --extra-libs='-lpthread -lm' --enable-nonfree
libavutil 56. 26.100 / 56. 26.100
libavcodec 58. 47.103 / 58. 47.103
libavformat 58. 26.101 / 58. 26.101
libavdevice 58. 6.101 / 58. 6.101
libavfilter 7. 48.100 / 7. 48.100
libswscale 5. 4.100 / 5. 4.100
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
configuration:
--pkg-config-flags=--static
--prefix=/home/brainiarc7/bin
--bindir=/home/brainiarc7/bin
--extra-cflags=-I/home/brainiarc7/bin/include
--extra-ldflags=-L/home/brainiarc7/bin/lib
--enable-cuda-nvcc
--enable-cuvid
--enable-libnpp
--extra-cflags=-I/usr/local/cuda/include/
--extra-ldflags=-L/usr/local/cuda/lib64/
--enable-nvenc
--extra-cflags=-I/opt/intel/mediasdk/include
--extra-ldflags=-L/opt/intel/mediasdk/lib
--extra-ldflags=-L/opt/intel/mediasdk/plugins
--enable-libmfx
--enable-libass
--enable-vaapi
--disable-debug
--enable-libvorbis
--enable-libvpx
--enable-libdrm
--enable-opencl
--enable-gpl
--cpu=native
--enable-opengl
--enable-libfdk-aac
--enable-libx265
--enable-openssl
--extra-libs='-lpthread -lm'
--enable-nonfree
并从 inxi 输出:
inxi -F
System: Host: cavaliere Kernel: 5.0.0 x86_64 bits: 64 Desktop: Gnome 3.28.3 Distro: Ubuntu 18.04.2 LTS
Machine: Device: laptop System: ASUSTeK product: Zephyrus M GM501GS v: 1.0 serial: N/A
Mobo: ASUSTeK model: GM501GS v: 1.0 serial: N/A
UEFI: American Megatrends v: GM501GS.308 date: 10/01/2018
Battery BAT0: charge: 49.3 Wh 100.0% condition: 49.3/55.0 Wh (90%)
CPU: 6 core Intel Core i7-8750H (-MT-MCP-) cache: 9216 KB
clock speeds: max: 4100 MHz 1: 2594 MHz 2: 3197 MHz 3: 3633 MHz 4: 3514 MHz 5: 3582 MHz 6: 3338 MHz
7: 3655 MHz 8: 3684 MHz 9: 1793 MHz 10: 3651 MHz 11: 3710 MHz 12: 3662 MHz
Graphics: Card-1: Intel Device 3e9b
Card-2: NVIDIA GP104M [GeForce GTX 1070 Mobile]
Display Server: x11 (X.Org 1.19.6 ) drivers: modesetting,nvidia (unloaded: fbdev,vesa,nouveau)
Resolution: 1920x1080@144.03hz
OpenGL: renderer: GeForce GTX 1070/PCIe/SSE2 version: 4.6.0 NVIDIA 418.43
Audio: Card-1 Intel Cannon Lake PCH cAVS driver: snd_hda_intel Sound: ALSA v: k5.0.0
Card-2 NVIDIA GP104 High Definition Audio Controller driver: snd_hda_intel
Card-3 Kingston driver: USB Audio
Network: Card: Intel Wireless-AC 9560 [Jefferson Peak] driver: iwlwifi
IF: wlo1 state: up mac: (redacted)
Drives: HDD Total Size: 3050.6GB (94.5% used)
ID-1: /dev/nvme0n1 model: Samsung_SSD_960_EVO_1TB size: 1000.2GB
ID-2: /dev/sda model: Crucial_CT2050MX size: 2050.4GB
Partition: ID-1: / size: 246G used: 217G (94%) fs: ext4 dev: /dev/nvme0n1p5
ID-2: swap-1 size: 8.59GB used: 0.00GB (0%) fs: swap dev: /dev/nvme0n1p6
RAID: No RAID devices: /proc/mdstat, md_mod kernel module present
Sensors: System Temperatures: cpu: 64.0C mobo: N/A gpu: 61C
Fan Speeds (in rpm): cpu: N/A
Info: Processes: 412 Uptime: 3:32 Memory: 4411.3/32015.5MB Client: Shell (bash) inxi: 2.3.56
为什么包含最后一位:
我是 运行 最新的 Linux 内核,版本 5.0。
Ubuntu 18.04LTS 上的图形驱动程序堆栈也是如此。
FFmpeg 的构建如图 here 所示,因为这台笔记本电脑通过 Optimus 启用了 NVIDIA+ Intel GPU。这样,我就可以根据需要使用 VAAPI、QuickSync 和 NVENC hwaccels。 即使我们的硬件相同,您的情况也可能会有所不同。
参考文献:
- 查看编码器选项,包括支持的速率控制方法:
ffmpeg -h encoder=vp9_vaapi
- 查看 deinterlace_vaapi 过滤器使用选项:
ffmpeg -h filter=deinterlace_vaapi
- 关于
vpp_qsv
过滤器的用法,见:
ffmpeg -h filter=vpp_qsv
例如,如果您想要场速率输出而不是去隔行器的帧速率输出,您可以将 rate=field
选项传递给它:
-vf=vaapi_deinterlace=rate=field
例如,此功能与支持 MBAFF. Others, such as the NVENC-based ones in FFmpeg, do not have this implemented(截至撰写本文时)的编码器有关。
使用 FFmpeg 的技巧:
尽可能参考内置文档,如上例所示。
他们可以发现潜在的陷阱,您可以通过了解过滤器链接和编码器初始化的工作原理、不受支持的功能等以及对性能的影响来避免这些陷阱。
例如,您会在上面的代码片段中看到,我们只调用去隔行器一次,然后通过 split
过滤器将其输出拆分为单独的缩放器。这样做是为了降低如果我们多次调用去隔行器会产生的开销,那会很浪费。
警告:
请注意,SDK 至少需要 2 个线程才能防止死锁,请参阅 this 代码块。这就是我们在ffmpeg中设置-threads 4
的原因。
我正在尝试实现vp9 硬件加速编码过程。我按照 ffmpeg 官方 github 的示例 (Here -> vaapi_encode.c).
但给出的示例仅将 .yuv 文件保存到 .h264 文件,我想将帧保存到 .mp4 或 .webm 容器。以及具备品质把控能力等等
我不是从文件中读取帧,而是从实时源中收集帧。当从实时源中获得完整的 5 秒帧时,使用 vp9_vaapi 将这些帧编码为 5 秒 .mp4 文件。
我能够将我的实时供稿中的所有 5 秒帧保存到 .mp4 或 .webm 文件,但它们无法正确播放(更准确地说:继续加载,然后我打开)。
官网示例结果:
cpu 编码的 vp9 .mp4 文件结果:
编辑:
结果
您将需要直接使用 FFmpeg,如果您在 vp9_vaapi
编码器中启用 B 帧,您可以选择在同一命令行中添加 vp9_superframe and the vp9_raw_reorder bitstream filters。
示例:
ffmpeg -threads 4 -vaapi_device /dev/dri/renderD128 \
-hwaccel vaapi -hwaccel_output_format vaapi \
-i http://server:port \
-c:v vp9_vaapi -global_quality 50 -bf 1 \
-bsf:v vp9_raw_reorder,vp9_superframe \
-f segment -segment_time 5 -segment_format_options movflags=+faststart output%03d.mp4
根据需要调整输入和输出paths/urls。
此命令的作用:
它将通过 segment muxer 创建 5 秒长的 mp4 片段。
查看 movflags=+faststart
的用法,以及如何通过上面的 -segment_format_options
标志将其作为格式选项传递给底层 mp4 多路复用器。
片段长度可能不正好是 5 秒长,因为每个片段开始(被剪切)(带有)一个关键帧。
但是,我不建议在该编码器中启用 B 帧,因为这些比特流过滤器会产生其他不良影响,例如 mucking around with the encoder's rate control and triggering bugs like this one。这在生产环境中是不可取的。这就是为什么下面的脚本没有启用该选项,而是直接在编码器选项中定义设置速率控制模式。
如果您需要利用 1:N VAAPI 编码,请使用这些片段:
- 如果需要去隔行扫描,调用
deinterlace_vaapi
滤镜:
ffmpeg -loglevel debug -threads 4 \
-init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi \
-hwaccel_device va -filter_hw_device va \
-hwaccel_output_format vaapi \
-i 'http://server:port' \
-filter_complex "[0:v]deinterlace_vaapi,split=3[n0][n1][n2]; \
[n0]scale_vaapi=1152:648[v0]; \
[n1]scale_vaapi=848:480[v1];
[n2]scale_vaapi=640:360[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 没有去隔行:
ffmpeg -loglevel debug -threads 4 \
-init_hw_device vaapi=va:/dev/dri/renderD128 -hwaccel vaapi \
-hwaccel_device va -filter_hw_device va -hwaccel_output_format vaapi \
-i 'http://server:port' \
-filter_complex "[0:v]split=3[n0][n1][n2]; \
[n0]scale_vaapi=1152:648[v0]; \
[n1]scale_vaapi=848:480[v1];
[n2]scale_vaapi=640:360[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -c:v:0 vp9_vaapi -g:v:0 50 -r:v:0 25 -rc_mode:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 1750k -c:v:1 vp9_vaapi -g:v:1 50 -r:v:1 25 -rc_mode:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 1000k -c:v:2 vp9_vaapi -g:v:2 50 -r:v:2 25 -rc_mode:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 使用英特尔的 QuickSync(在支持的平台上):
在 Intel Icelake 及更高版本上,您可以使用具有以下已知限制的 vp9_qsv
编码器包装器(目前):
(一)。您必须启用 low_power mode
,因为 iHD
驱动程序目前仅公开 VDENC 解码路径。
(b)。 MSDK 不支持编码选项 1 和 extra_data。
(c)。 MSDK默认会插入IVF头,但FFmpeg不需要,默认禁用。
请参阅以下示例:
- 如果需要去隔行扫描,调用
vpp_qsv
滤镜:
ffmpeg -nostdin -y -fflags +genpts \
-init_hw_device vaapi=va:/dev/dri/renderD128,driver=iHD \
-filter_hw_device va -hwaccel vaapi -hwaccel_output_format vaapi
-threads 4 -vsync 1 -async 1 \
-i 'http://server:port' \
-filter_complex "[0:v]hwmap=derive_device=qsv,format=qsv,vpp_qsv=deinterlace=2:async_depth=4,split[n0][n1][n2]; \
[n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
[n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
[n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 360k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 280k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 160k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
- 没有去隔行:
ffmpeg -nostdin -y -fflags +genpts \
-init_hw_device vaapi=va:/dev/dri/renderD128,driver=iHD \
-filter_hw_device va -hwaccel vaapi -hwaccel_output_format vaapi
-threads 4 -vsync 1 -async 1 \
-i 'http://server:port' \
-filter_complex "[0:v]hwmap=derive_device=qsv,format=qsv,split=3[n0][n1][n2]; \
[n0]vpp_qsv=w=1152:h=648:async_depth=4[v0]; \
[n1]vpp_qsv=w=848:h=480:async_depth=4[v1];
[n2]vpp_qsv=w=640:h=360:async_depth=4[v2]" \
-b:v:0 2250k -maxrate:v:0 2250k -bufsize:v:0 2250k -c:v:0 vp9_qsv -g:v:0 50 -r:v:0 25 -low_power:v:0 2 \
-b:v:1 1750k -maxrate:v:1 1750k -bufsize:v:1 1750k -c:v:1 vp9_qsv -g:v:1 50 -r:v:1 25 -low_power:v:1 2 \
-b:v:2 1000k -maxrate:v:2 1000k -bufsize:v:2 1000k -c:v:2 vp9_qsv -g:v:2 50 -r:v:2 25 -low_power:v:2 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-flags -global_header -f tee -use_fifo 1 \
-map "[v0]" -map "[v1]" -map "[v2]" -map 0:a \
"[select=\'v:0,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path0/output%03d.mp4| \
[select=\'v:1,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path1/output%03d.mp4| \
[select=\'v:2,a\':f=segment:segment_time=5:segment_format_options=movflags=+faststart]$output_path2/output%03d.mp4"
请注意,我们使用 vpp_qsv filter
并将 async_depth
选项设置为 4。与使用 scale_qsv
和 deinterlace_qsv
相比,这极大地提高了转码性能。参见 FFmpeg 的 this commit git.
注意:如果您使用QuickSync路径,请注意,如果您系统上的Media SDK库支持,MFE(多帧编码模式)将默认启用。
用于推导上述代码片段的公式:
最佳bufsize:v = 目标比特率(-b:v 值)
将 GOP 大小设置为:2 * fps(GOP 间隔设置为 2 秒)。
我们通过 -threads:v
限制视频编码器的线程数,以防止 VBV 溢出。
使用的分辨率阶梯:16:9 中的 640p、480p 和 360p,参见 this link。 根据需要进行调整。
根据需要替换上面的变量($output_path{0-2}
、输入等)。
测试并反馈。
当前观察:
在我的系统上,我能够使用 VP9 使用 Apple's recommended resolutions and bit-rates for HEVC encoding for HLS 作为基准实时编码多达 5 个流。系统负载等见下图
平台详情:
我在 Coffee-lake 系统上,为此工作流程使用 i965
驱动程序:
libva info: VA-API version 1.5.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_1_5
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.5 (libva 2.4.0.pre1)
vainfo: Driver version: Intel i965 driver for Intel(R) Coffee Lake - 2.4.0.pre1 (2.3.0-11-g881e67a)
vainfo: Supported profile and entrypoints
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Simple : VAEntrypointEncSlice
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileH264MultiviewHigh : VAEntrypointVLD
VAProfileH264MultiviewHigh : VAEntrypointEncSlice
VAProfileH264StereoHigh : VAEntrypointVLD
VAProfileH264StereoHigh : VAEntrypointEncSlice
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileVP8Version0_3 : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile0 : VAEntrypointEncSlice
VAProfileVP9Profile2 : VAEntrypointVLD
我的 ffmpeg 构建信息:
ffmpeg -buildconf
ffmpeg version N-93308-g1144d5c96d Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
configuration: --pkg-config-flags=--static --prefix=/home/brainiarc7/bin --bindir=/home/brainiarc7/bin --extra-cflags=-I/home/brainiarc7/bin/include --extra-ldflags=-L/home/brainiarc7/bin/lib --enable-cuda-nvcc --enable-cuvid --enable-libnpp --extra-cflags=-I/usr/local/cuda/include/ --extra-ldflags=-L/usr/local/cuda/lib64/ --enable-nvenc --extra-cflags=-I/opt/intel/mediasdk/include --extra-ldflags=-L/opt/intel/mediasdk/lib --extra-ldflags=-L/opt/intel/mediasdk/plugins --enable-libmfx --enable-libass --enable-vaapi --disable-debug --enable-libvorbis --enable-libvpx --enable-libdrm --enable-opencl --enable-gpl --cpu=native --enable-opengl --enable-libfdk-aac --enable-libx265 --enable-openssl --extra-libs='-lpthread -lm' --enable-nonfree
libavutil 56. 26.100 / 56. 26.100
libavcodec 58. 47.103 / 58. 47.103
libavformat 58. 26.101 / 58. 26.101
libavdevice 58. 6.101 / 58. 6.101
libavfilter 7. 48.100 / 7. 48.100
libswscale 5. 4.100 / 5. 4.100
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
configuration:
--pkg-config-flags=--static
--prefix=/home/brainiarc7/bin
--bindir=/home/brainiarc7/bin
--extra-cflags=-I/home/brainiarc7/bin/include
--extra-ldflags=-L/home/brainiarc7/bin/lib
--enable-cuda-nvcc
--enable-cuvid
--enable-libnpp
--extra-cflags=-I/usr/local/cuda/include/
--extra-ldflags=-L/usr/local/cuda/lib64/
--enable-nvenc
--extra-cflags=-I/opt/intel/mediasdk/include
--extra-ldflags=-L/opt/intel/mediasdk/lib
--extra-ldflags=-L/opt/intel/mediasdk/plugins
--enable-libmfx
--enable-libass
--enable-vaapi
--disable-debug
--enable-libvorbis
--enable-libvpx
--enable-libdrm
--enable-opencl
--enable-gpl
--cpu=native
--enable-opengl
--enable-libfdk-aac
--enable-libx265
--enable-openssl
--extra-libs='-lpthread -lm'
--enable-nonfree
并从 inxi 输出:
inxi -F
System: Host: cavaliere Kernel: 5.0.0 x86_64 bits: 64 Desktop: Gnome 3.28.3 Distro: Ubuntu 18.04.2 LTS
Machine: Device: laptop System: ASUSTeK product: Zephyrus M GM501GS v: 1.0 serial: N/A
Mobo: ASUSTeK model: GM501GS v: 1.0 serial: N/A
UEFI: American Megatrends v: GM501GS.308 date: 10/01/2018
Battery BAT0: charge: 49.3 Wh 100.0% condition: 49.3/55.0 Wh (90%)
CPU: 6 core Intel Core i7-8750H (-MT-MCP-) cache: 9216 KB
clock speeds: max: 4100 MHz 1: 2594 MHz 2: 3197 MHz 3: 3633 MHz 4: 3514 MHz 5: 3582 MHz 6: 3338 MHz
7: 3655 MHz 8: 3684 MHz 9: 1793 MHz 10: 3651 MHz 11: 3710 MHz 12: 3662 MHz
Graphics: Card-1: Intel Device 3e9b
Card-2: NVIDIA GP104M [GeForce GTX 1070 Mobile]
Display Server: x11 (X.Org 1.19.6 ) drivers: modesetting,nvidia (unloaded: fbdev,vesa,nouveau)
Resolution: 1920x1080@144.03hz
OpenGL: renderer: GeForce GTX 1070/PCIe/SSE2 version: 4.6.0 NVIDIA 418.43
Audio: Card-1 Intel Cannon Lake PCH cAVS driver: snd_hda_intel Sound: ALSA v: k5.0.0
Card-2 NVIDIA GP104 High Definition Audio Controller driver: snd_hda_intel
Card-3 Kingston driver: USB Audio
Network: Card: Intel Wireless-AC 9560 [Jefferson Peak] driver: iwlwifi
IF: wlo1 state: up mac: (redacted)
Drives: HDD Total Size: 3050.6GB (94.5% used)
ID-1: /dev/nvme0n1 model: Samsung_SSD_960_EVO_1TB size: 1000.2GB
ID-2: /dev/sda model: Crucial_CT2050MX size: 2050.4GB
Partition: ID-1: / size: 246G used: 217G (94%) fs: ext4 dev: /dev/nvme0n1p5
ID-2: swap-1 size: 8.59GB used: 0.00GB (0%) fs: swap dev: /dev/nvme0n1p6
RAID: No RAID devices: /proc/mdstat, md_mod kernel module present
Sensors: System Temperatures: cpu: 64.0C mobo: N/A gpu: 61C
Fan Speeds (in rpm): cpu: N/A
Info: Processes: 412 Uptime: 3:32 Memory: 4411.3/32015.5MB Client: Shell (bash) inxi: 2.3.56
为什么包含最后一位:
我是 运行 最新的 Linux 内核,版本 5.0。 Ubuntu 18.04LTS 上的图形驱动程序堆栈也是如此。 FFmpeg 的构建如图 here 所示,因为这台笔记本电脑通过 Optimus 启用了 NVIDIA+ Intel GPU。这样,我就可以根据需要使用 VAAPI、QuickSync 和 NVENC hwaccels。 即使我们的硬件相同,您的情况也可能会有所不同。
参考文献:
- 查看编码器选项,包括支持的速率控制方法:
ffmpeg -h encoder=vp9_vaapi
- 查看 deinterlace_vaapi 过滤器使用选项:
ffmpeg -h filter=deinterlace_vaapi
- 关于
vpp_qsv
过滤器的用法,见:
ffmpeg -h filter=vpp_qsv
例如,如果您想要场速率输出而不是去隔行器的帧速率输出,您可以将 rate=field
选项传递给它:
-vf=vaapi_deinterlace=rate=field
例如,此功能与支持 MBAFF. Others, such as the NVENC-based ones in FFmpeg, do not have this implemented(截至撰写本文时)的编码器有关。
使用 FFmpeg 的技巧:
尽可能参考内置文档,如上例所示。 他们可以发现潜在的陷阱,您可以通过了解过滤器链接和编码器初始化的工作原理、不受支持的功能等以及对性能的影响来避免这些陷阱。
例如,您会在上面的代码片段中看到,我们只调用去隔行器一次,然后通过 split
过滤器将其输出拆分为单独的缩放器。这样做是为了降低如果我们多次调用去隔行器会产生的开销,那会很浪费。
警告:
请注意,SDK 至少需要 2 个线程才能防止死锁,请参阅 this 代码块。这就是我们在ffmpeg中设置-threads 4
的原因。