我正在尝试使用硬件加速水平翻转视频,但似乎做不到。我不想更改编解码器,只想保持原样(只是翻转)。我在 Windows 11 Pro 机器上使用 Intel Arc Pro A30M 显卡。
没有硬件加速我通常这样做:
.\ffmpeg -i input.mp4 -vf hflip -c:a copy output.mp4
它可以工作,但是速度很慢(2-4倍)。
和硬件加速,我试过这个但是失败了:
.\ffmpeg.exe -hwaccel qsv -i input.mp4 -c:a copy -vf hflip -c:v h264_qsv output.mp4
我收到以下错误:
Impossible to convert between the formats supported by the filter
'graph 0 input from stream 0:0' and the filter 'auto_scale_0'
我在这里遗漏了什么?
完整日志为:
ffmpeg version 2024-01-07-git-90bef6390f-full_build-www.gyan.dev Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --pkg-config=pkgconf --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-dxva2 --enable-d3d11va --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil 58. 36.101 / 58. 36.101
libavcodec 60. 37.100 / 60. 37.100
libavformat 60. 20.100 / 60. 20.100
libavdevice 60. 4.100 / 60. 4.100
libavfilter 9. 17.100 / 9. 17.100
libswscale 7. 6.100 / 7. 6.100
libswresample 4. 13.100 / 4. 13.100
libpostproc 57. 4.100 / 57. 4.100
[vist#0:0/h264 @ 000001cb0a934100] WARNING: defaulting hwaccel_output_format to qsv for compatibility with old commandlines. This behaviour is DEPRECATED and will be removed in the future. Please explicitly set "-hwaccel_output_format qsv".
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 02:20:24.64, start: 0.000000, bitrate: 3808 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 3674 kb/s, 23.98 fps, 23.98 tbr, 24k tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
[AVHWDeviceContext @ 000001cb0a926d00] Using device 8086:56b0 (Intel(R) Arc(TM) Pro A30M Graphics).
Stream mapping:
Stream #0:0 -> #0:0 (h264 (h264_qsv) -> h264 (h264_qsv))
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
Impossible to convert between the formats supported by the filter 'graph 0 input from stream 0:0' and the filter 'auto_scale_0'
[vf#0:0 @ 000001cb0a0dec00] Error reinitializing filters!
[vf#0:0 @ 000001cb0a0dec00] Task finished with error code: -40 (Function not implemented)
[vf#0:0 @ 000001cb0a0dec00] Terminating thread with return code -40 (Function not implemented)
[vost#0:0/h264_qsv @ 000001cb0a08d140] Could not open encoder before EOF
[vost#0:0/h264_qsv @ 000001cb0a08d140] Task finished with error code: -22 (Invalid argument)
[vost#0:0/h264_qsv @ 000001cb0a08d140] Terminating thread with return code -22 (Invalid argument)
[out#0/mp4 @ 000001cb0ac7a040] Nothing was written into output file, because at least one of its streams received no packets.
frame= 0 fps=0.0 q=0.0 Lsize= 0kB time=N/A bitrate=N/A speed=N/A
Conversion failed!
答案1
由于hflip
过滤器是在 CPU 上执行的,而h264_qsv
解码器需要数据在 GPU 的内存中,因此我们必须添加hwdownload
和hwupload
过滤器:
ffmpeg.exe -y -init_hw_device qsv=hw,child_device_type=dxva2 -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i video_with_audio.mp4 -c:a copy -vf hwdownload,format=nv12,hflip,hwupload=extra_hw_frames=10 -c:v h264_qsv output.mp4
即使 GPU 是使用系统内存存储解码/编码帧的内部 GPU,我们仍然必须使用以下顺序:
QSV 解码 -> 下载 -> 翻转 -> 上传 -> QSV 编码。
原因是 QSV 硬件加速使用通过 GPU 设备驱动程序分配的内存缓冲区(即使不是,FFmpeg 也会将缓冲区视为“设备内存”缓冲区)。
之后hwdownload
,像素格式为qsv
,并且我们必须使用format=nv12
之前hflip
过滤器(hflip
不支持qsv
像素格式)。
hwupload=extra_hw_frames=10
将帧上传到“设备”(GPU 内存),同时分配 10 个额外的缓冲区(编码器可能需要这些额外的缓冲区)。
有一个更好的解决方案:
我们可以使用 GPU 加速水平翻转vpp_qsv
过滤器:
ffmpeg.exe -y -init_hw_device qsv=hw,child_device_type=dxva2 -hwaccel qsv -filter_hw_device hw -hwaccel_output_format qsv -extra_hw_frames 10 -c:v h264_qsv -i input.mp4 -c:a copy -vf vpp_qsv=transpose=hflip -c:v h264_qsv output.mp4
上述命令在 GPU 上执行整个解码 -> 翻转 -> 编码管道 - 它应该更快......
笔记:上述命令在我的计算机上使用 ffmpeg 版本 5.1.2-full_build-www.gyan.dev 运行。
仅当显示器连接到 Intel HD Graphics iGPU 时它才工作(当显示器连接到 NVIDIA GPU 时不工作)。
使用该过滤器存在多个已知问题vpp_qsv
,并且它可能无法正常工作。