FFmpeg 硬解在 Linux 上:从“能跑”到“跑满 GPU”的实战笔记

目录

[一、先给结论:Linux 硬加速现状速览](#一、先给结论:Linux 硬加速现状速览)

[二、VA-API:Linux 硬解的"事实标准"](#二、VA-API:Linux 硬解的“事实标准”)

[1️⃣ 检查环境(必做)](#1️⃣ 检查环境(必做))

[2️⃣ 最简单的硬解播放](#2️⃣ 最简单的硬解播放)

[3️⃣ 转码(硬解 + 硬编码)](#3️⃣ 转码(硬解 + 硬编码))

[三、NVDEC:NVIDIA 的"暴力美学"](#三、NVDEC:NVIDIA 的“暴力美学”)

[1️⃣ 确认驱动](#1️⃣ 确认驱动)

[2️⃣ 硬解播放](#2️⃣ 硬解播放)

[3️⃣ 硬解 + CUDA 滤镜(高级)](#3️⃣ 硬解 + CUDA 滤镜(高级))

四、VDPAU:老系统的"遗产"

[五、DRM Prime + EGL:Wayland / 无 X11 的终极方案](#五、DRM Prime + EGL:Wayland / 无 X11 的终极方案)

核心概念

[示例(渲染不走 X11)](#示例(渲染不走 X11))

六、零拷贝(Zero-Copy):性能分水岭

[❌ 错误示范(CPU 中转)](#❌ 错误示范(CPU 中转))

[✅ 正确示范(全程 GPU)](#✅ 正确示范(全程 GPU))

[七、Docker / 服务器部署必踩的坑](#七、Docker / 服务器部署必踩的坑)

[✅ 权限](#✅ 权限)

[✅ 驱动必须进容器](#✅ 驱动必须进容器)

[八、如何判断"到底有没有用到 GPU"?](#八、如何判断“到底有没有用到 GPU”?)

[Intel / AMD](#Intel / AMD)

NVIDIA

九、一个现实结论(很重要)

十、总结一句话


如果你在 Linux 上用过 FFmpeg 做视频处理,大概率有过这种体验:

CPU 100%,风扇起飞,GPU 却在旁边"围观"。

Linux 上的硬加速一直是碎片化重灾区 :Intel / AMD / NVIDIA 各玩各的,API 一堆(VA-APIVDPAUNVDECAMF),而且**"支持"不等于"能用",更不等于"快"**。

这篇文章不堆参数,只讲实战结论,帮你把 FFmpeg 在 Linux 上的硬加速真正用起来。


一、先给结论:Linux 硬加速现状速览

GPU 推荐 API FFmpeg 名称 稳定性 备注
Intel ✅ VA-API h264_vaapi/ hevc_vaapi ⭐⭐⭐⭐⭐ 首选
AMD ✅ VA-API h264_vaapi/ hevc_vaapi ⭐⭐⭐⭐ 新驱动
AMD(老) ⚠️ VDPAU h264_vdpau ⭐⭐⭐ 仅 legacy
NVIDIA ✅ NVDEC h264_nvdec/ hevc_nvdec ⭐⭐⭐⭐⭐ 闭源驱动
NVIDIA(开源 nouveau) 不可用 --- 放弃
嵌入式 / RK / Qcom ✅ DRM h264_v4l2m2m ⭐⭐⭐ SoC 专用

👉 一句话选型:

  • Intel / 新 AMD → VA-API

  • NVIDIA → NVDEC

  • 嵌入式 → v4l2m2m / DRM


二、VA-API:Linux 硬解的"事实标准"

1️⃣ 检查环境(必做)

复制代码
vainfo

看到类似输出才算"真可用":

复制代码
VA-API version: 1.20
Driver name: iHD / radeonsi
Supported profile: VAProfileH264Main
Supported profile: VAProfileHEVCMain

❌ 如果只有 VAProfileNone→ 驱动没装好


2️⃣ 最简单的硬解播放

复制代码
ffplay -hwaccel vaapi \
       -hwaccel_device /dev/dri/renderD128 \
       input.mp4

/dev/dri/renderD128无特权渲染节点,服务器 / Docker 必用。


3️⃣ 转码(硬解 + 硬编码)

复制代码
ffmpeg -hwaccel vaapi \
       -hwaccel_device /dev/dri/renderD128 \
       -i input.mp4 \
       -vf 'format=nv12,hwupload' \
       -c:v h264_vaapi \
       output.mp4

⚠️ 注意:

  • -vf format=nv12,hwupload不能少

  • VA-API 默认工作在 GPU 显存


三、NVDEC:NVIDIA 的"暴力美学"

1️⃣ 确认驱动

复制代码
nvidia-smi

FFmpeg 编译时必须包含 --enable-nonfree --enable-cuda-nvcc


2️⃣ 硬解播放

复制代码
ffplay -hwaccel nvdec input.mp4

👉 NVDEC 自动选 GPU,不需要手动指定 device。


3️⃣ 硬解 + CUDA 滤镜(高级)

复制代码
ffmpeg -hwaccel nvdec \
       -hwaccel_output_format cuda \
       -i input.mp4 \
       -vf 'scale_npp=1280:720' \
       -c:v h264_nvenc \
       output.mp4

零拷贝

✅ 滤镜直接在 GPU 跑


四、VDPAU:老系统的"遗产"

AMD 老显卡 / 老驱动还能用:

复制代码
ffmpeg -hwaccel vdpau -i input.mp4 ...

❌ 不支持 HEVC

❌ 新系统不建议再用

除非你在维护 legacy 系统,否则直接忽略。


五、DRM Prime + EGL:Wayland / 无 X11 的终极方案

这是 **现代 Linux 桌面(GNOME / KDE Wayland)**​ 的正确姿势。

核心概念

  • hwaccel vaapi

  • hwmap=derive_device=dr

  • 直接把解码 surface 映射到 DRM 帧缓冲

示例(渲染不走 X11)

复制代码
ffmpeg -hwaccel vaapi \
       -vaapi_device /dev/dri/renderD128 \
       -f rawvideo -pix_fmt drm_prime \
       -i decoded_frames ...

👉 常用于:

  • Wayland 播放器

  • DRM/KMS 直出

  • 嵌入式 GUI(Qt / SDL + EGL)


六、零拷贝(Zero-Copy):性能分水岭

❌ 错误示范(CPU 中转)

复制代码
ffmpeg -hwaccel vaapi -i input.mp4 -pix_fmt yuv420p output.nv12

👉 解码 → GPU → CPU → 再处理 →


✅ 正确示范(全程 GPU)

复制代码
ffmpeg -hwaccel vaapi \
       -hwaccel_output_format vaapi \
       -i input.mp4 \
       -vf 'hwmap,scale_vaapi=w=1280:h=720' \
       -c:v hevc_vaapi \
       output.mp4

✅ 解码 → GPU → 滤镜 → 编码

CPU 占用 < 5%


七、Docker / 服务器部署必踩的坑

✅ 权限

复制代码
docker run --rm \
  --device=/dev/dri/renderD128 \
  -v /dev/dri:/dev/dri \
  ffmpeg ...

✅ 驱动必须进容器

复制代码
apt install i965-va-driver vainfo

⚠️ 宿主机 + 容器驱动版本必须一致


八、如何判断"到底有没有用到 GPU"?

Intel / AMD

复制代码
intel_gpu_top

NVIDIA

复制代码
nvidia-smi dmon

如果你看到:

  • GPU 使用率 ≈ 0%

  • CPU 使用率 ≈ 400%

👉 你根本没在用硬解


九、一个现实结论(很重要)

FFmpeg 在 Linux 上"支持硬解" ≠ "默认启用硬解" ≠ "零拷贝"

90% 的性能问题,都是:

  • 忘了 -hwaccel

  • 忘了 hwupload

  • 忘了 hwaccel_output_format

  • 在 Wayland 下强行用 X11 路径


十、总结一句话

Linux 上 FFmpeg 硬加速的正确打开方式是:

  • Intel / AMD → VA-API + DRM Prime

  • NVIDIA → NVDEC + CUDA

  • 全程避免 CPU 中转

  • vainfo / nvidia-smi验证,而不是看命令行参数

相关推荐
星恒随风1 小时前
Linux 权限详解:从 rwx、chmod 到 umask、目录权限与粘滞位
linux·运维·服务器·笔记·学习
拳里剑气1 小时前
Linux:进程间通信
linux·运维·数据库·进程
lsh曙光1 小时前
防火墙-iptables
linux
阳光九叶草LXGZXJ1 小时前
达梦数据库-报错-12-[-7184]:对象定义[XXX]被修改,版本检查失败
linux·运维·服务器·数据库·sql·学习
小此方2 小时前
Re:Linux系统篇(四十九)线程篇 · 二:为什么现代操作系统选择分页式存储?分页如何解决物理内存碎片?分页结构如何演化到页表、页目录、MMU?
linux·运维·驱动开发
Huangjin007_2 小时前
【Linux 系统篇(十一)】基础开发工具(六) —— 版本控制器 Git
linux·运维·git
j7~3 小时前
【Linux】二十六.线程篇三《Linux多线程编程:线程控制、线程ID以及进程地址空间分布、线程局部存储__thread以及clone系统调用》---详解
linux·运维·服务器·开发语言·c++·多线程编辑·线程的控制
一米阳光866110 小时前
软考(中级)软件设计师核心笔记(3)数据库系统——概念、数据库设计
数据库·笔记·职场发展·软考·软件设计师
乌萨奇也要立志学C++11 小时前
【Linux】网络基础 从零理解网络通信:局域网、跨网传输与 Socket 预备知识
linux·服务器·网络