昇腾Atlas平台实战:编译集成NPU加速的FFmpeg全流程

去年开始深度接触昇腾Atlas平台之后,我最大的感受是:AI推理这部分资料已经慢慢多起来了,但真正涉及到 多媒体处理与NPU结合 的实战资料依然少得可怜。尤其是像FFmpeg这种传统CPU侧的重型工具,怎么把它和昇腾的DVPP硬件编解码能力打通,很多刚上手的人连编译这一步都迈不过去。

这次我完整走了一遍在昇腾Atlas环境上编译集成NPU加速能力的FFmpeg全流程,包括环境检查、依赖安装、源码修改、编译参数设计,以及最后拿真实视频流做硬解码验证的完整过程。这篇文章会把每一步的关键细节和我踩过的坑全部写出来,希望能帮你少走弯路。

1. 昇腾NPU视频处理能力与FFmpeg的结合点

1.1 昇腾Atlas平台的视频处理硬件单元概览

昇腾Atlas系列硬件(310P/300V/加速卡等)上面除了AI计算核心之外,还有一套独立的媒体数据处理硬件单元,官方叫DVPP(Digital Vision Pre-Processing)。DVPP内部包含VPC(Video Pre-Processing Codec)和JPEGD/JPEGE等模块,分别负责视频编解码和JPEG图片编解码。

硬件编解码和CPU软解的差别是代差级的。我实测过一段4K H.265视频流,用CPU软解跑FFmpeg时,单个1080p视频流通常能占到4到8个核的负载,而切换到DVPP硬解之后CPU占用几乎可以忽略,GPU/NPU的专有硬件引擎直接接管了解码输出。这对视频分析、安防监控、媒体处理这类场景是质的提升。

1.2 FFmpeg在昇腾平台上为什么需要重新编译

很多人会问:官方发布页不是已经有编译好的FFmpeg吗?直接下载解压用不就行了?这里有一个非常关键的认知: 通用版FFmpeg根本不认识昇腾的DVPP硬件,也不包含任何与NPU设备交互的插件接口 。它只是一份标准的CPU侧多媒体工具链。

要让FFmpeg调用昇腾硬件能力,需要做两件事:

  • 在FFmpeg源码层加入昇腾提供的硬件设备注册模块(libavdevice/avdevice),以及对应的硬件编解码封装层。
  • 在编译配置时启用昇腾平台相关的编译宏,把CANN(Compute Architecture for Neural Networks)工具链中的头文件和库文件链接进FFmpeg。

这两件事单靠下载二进制包是做不到的,必须本地编译。另外,发行版自带的FFmpeg(比如Ubuntu的apt版本)也基本是老版本,OpenH264、libx265这些第三方库的版本也不可控。为了确保后续能稳定接NPU,我建议直接从FFmpeg官方master分支拉源码来编译。

1.3 硬件选型:310P3和300V系列到底差在哪

从性能规格上看,目前昇腾设备主要分两个方向:

一个是偏推理侧的加速卡,比如Atlas 300V系列。它本质上是纯推理卡,视频编解码能力相对有限,主打高并发AI推理任务,比如YOLO系列模型部署。很多场景下用户会搭配CPU做视频前处理,它自己不会参与大量视频解码。

另一个是偏边缘计算和多媒体处理的设备,比如Atlas 310P系列。310P3这块卡我实际用下来,它既支持FP16/INT8推理,又带了完整的DVPP硬件编解码单元,非常适合接视频流做推理前处理——硬解出来的YUV数据可以直接喂给NPU做模型推理,全程不需要经过CPU拷贝。

关于310P3的推理精度,很多刚上手的朋友会想当然地以为它默认就是FP16。实际上,310P3的AI Core支持FP16、BF16、INT8等精度,默认情况下如果你不做特殊配置,CANN工具链会按照算子注册的精度执行,多数框架默认走FP16。如果你做的是对精度极度敏感的任务(比如某些检测模型),建议专门对模型做精度比对后选择INT8量化或FP16。

如果你是纯视频处理场景,300V这种运算加速卡并不一定是最优选。它的名字虽然叫“运算加速卡”,但侧重点在矩阵运算而不是媒体编解码,媒体处理硬件的规格和310P系列有明显差距。我个人的选型经验是: 做视频分析选310P,做高并发AI推理选300V。

2. 编译前的系统环境准备

2.1 驱动、固件与CANN工具链的版本对齐

昇腾平台最折磨人的点就是版本匹配。驱动、固件、CANN三者版本必须严格匹配,否则运行时会报很奇怪的问题,比如设备初始化失败或者算子加载失败。我在编译前专门整理过一张版本对应表,建议你建一个文档记录自己的环境版本,方便后续问题回溯。

我这次用的环境组合是:

  • 操作系统:Ubuntu 20.04 x86_64
  • 昇腾驱动:23.0.3
  • 昇腾固件:23.0.3(与驱动配套)
  • CANN工具链:CANN 7.0.RC1
  • FFmpeg源码:master分支(拉取日期为2024年9月中旬)

需要说明的是,FFmpeg与CANN的版本并不是严格绑定的,只要CANN提供的头文件接口没有大的断裂性变化,一般都能编译过。但如果你用的CANN版本太老,建议直接升级到6.3以上,早期的ACL接口和现在的DVPP接口有较多差异,老接口在新驱动上会直接失效。

2.2 安装必要的编译工具与依赖库

昇腾环境下编译FFmpeg,除了常规的build-essential之外,还需要装一些多媒体相关的开发库。这里我直接给出Ubuntu 20.04上的完整依赖安装命令:

sudo apt update
sudo apt install -y build-essential pkg-config make cmake
sudo apt install -y yasm nasm
sudo apt install -y libx264-dev libx265-dev libvpx-dev libfdk-aac-dev libmp3lame-dev libopus-dev
sudo apt install -y libssl-dev libtool autoconf automake
sudo apt install -y libavformat-dev libavcodec-dev libavutil-dev

其中yasm和nasm在编译FFmpeg内嵌汇编时是必须的,不装的话config步骤会报nasm not found。x264/x265这类编码库看你自己的需求,如果只是用FFmpeg接NPU做解码,这些编码库不装也能编译通过。但建议装一下,因为你做验证的时候经常需要自己造测试视频流,有编码库方便得多。

2.3 确认CANN的环境变量配置

CANN安装完成之后,需要设置环境变量。正常情况下CANN的安装路径在 /usr/local/Ascend ,你需要确认以下几点:

# 确认CANN目录存在
ls /usr/local/Ascend/ascend-toolkit/latest

# 设置环境变量(可以直接写进 ~/.bashrc)
source /usr/local/Ascend/ascend-toolkit/set_env.sh

set_env.sh 这个脚本会自动设置 ASCEND_HOME_PATH 、 LD_LIBRARY_PATH 等关键环境变量,建议编译的时候在同一个终端里先source好,避免后续找不到头文件或库文件。

我之前踩过一个坑:在systemd服务里启动FFmpeg时没有source环境变量,导致程序起来之后动态库找不到 libascendcl.so 直接崩溃。这个问题后面在第四部分详细说,这里先记住一点—— 昇腾相关的环境变量是编译和运行时都必须具备的 。

3. FFmpeg源码获取与NPU补丁集成

3.1 从官方仓库拉取FFmpeg源码

这一步比较简单,直接用git拉取即可:

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg

如果你在国内网络环境下clone速度很慢,可以通过镜像方式拉取,但这个就不展开了。FFmpeg的master分支更新很快,拉下来之后可以先用 git log -1 确认一下当前提交点,方便后续回溯。

3.2 昇腾官方提供的NPU适配补丁

昇腾官方在CANN工具链的安装包里,以及Gitee的昇腾社区仓库中,提供了针对FFmpeg的硬件适配补丁。补丁本质上做了两件事:

  • 在FFmpeg源码中新增 libavdevice/avdevice_ascend 之类的设备插件目录,注册昇腾设备。
  • 实现 av_hwdevice_ctx_create 对应的昇腾后端,让FFmpeg的hwdevice框架能识别 ascend 设备类型。

补丁打完后的编译,生成的FFmpeg会多出 --enable-ascend 或 --enable-npu 之类的配置选项。具体宏名取决于你的CANN版本,老版本可能是 --enable-ascend ,新版本可能统一改成了 --enable-npu ,实际以 ./configure --help 里显示的为准。

我这次用的打补丁方式是:

# 假设补丁文件已下载到当前目录
git apply ascend_ffmpeg.patch

打补丁时如果提示冲突,不要强行apply。更稳妥的做法是直接对比补丁涉及的源文件,手动进行合并。尤其是当你拉的FFmpeg版本过新、补丁基于的FFmpeg版本过老时,冲突概率会比较高。

3.3 检查Patch是否生效的方法

打完补丁之后,先不要着急configure,建议先检查一下关键文件是否存在:

ls libavdevice/

如果看到 avdevice_ascend.c 或类似的昇腾相关源文件,说明补丁已经打进去了。另外可以在FFmpeg源码目录下搜一下 ascend 关键字:

grep -r "ascend" configure

如果configure里出现了对应的选项,说明补丁生效了。这一步看起来简单,但能帮你省去后面configure失败回退排查的大量时间。

4. NetEase FFmpeg配置脚本与编译参数详解

4.1 configure关键参数说明

FFmpeg的configure是整个编译流程的“总开关”。昇腾平台编译时,我的核心配置如下(以实际命令为例):

./configure \
    --prefix=/usr/local/ffmpeg-ascend \
    --enable-ascend \
    --enable-nonfree \
    --enable-gpl \
    --enable-libx264 \
    --enable-libx265 \
    --enable-libvpx \
    --enable-libfdk-aac \
    --enable-libmp3lame \
    --enable-libopus \
    --enable-shared \
    --disable-static \
    --extra-cflags="-I/usr/local/Ascend/ascend-toolkit/latest/include" \
    --extra-ldflags="-L/usr/local/Ascend/ascend-toolkit/latest/lib64"

几个关键参数的解析:

  • --enable-ascend :启用昇腾设备支持,这是核心。
  • --enable-shared :生成动态库。建议务必启用,因为很多场景下要把FFmpeg集成到自己的服务进程里,动态库方式更灵活,而且链接NPU相关的动态库时也更不容易出问题。
  • --extra-cflags 和 --extra-ldflags :指向CANN的头文件和库文件路径。如果没有加这两个参数,即使打了补丁,编译时也会因为找不到ACL相关的头文件而报错。

4.2 关于“nonfree”和“libfdk-aac”的授权问题

--enable-nonfree 这个参数,严格来说是因为libfdk-aac这个库的许可证与GPL不兼容,而我又确实需要AAC编码能力,所以只能开启nonfree模式。如果你不需要AAC编码,可以把 --enable-libfdk-aac 和 --enable-nonfree 都去掉,这样可以保持纯GPL合规。

我个人建议,如果是企业内部自用,怎么选都可以;如果是要对外分发编译产物,建议把libfdk-aac去掉,换成原生的AAC编码器,避免许可证上的麻烦。

4.3 静态编译还是动态编译

昇腾环境下,我更推荐动态编译,原因有两点。

第一,动态编译产出的FFmpeg二进制体积小,依赖的NPU库是通过 libascendcl.so 等方式动态加载的,升级CANN版本时不需要重新编译整个FFmpeg。

第二,静态编译有时会跟昇腾自带的一些开源库(比如protobuf、opencv等)产生符号冲突。这种冲突排查起来非常痛苦,问题往往表现为运行时报错,但报错信息并不直接指向符号冲突,你很难快速定位。

如果你后续想把FFmpeg的库集成到自己的C++工程中,动态编译产出的 libavcodec.so 等库也可以直接被CMake工程引用,使用方式更友好。

4.4 编译命令与安装

configure完成之后,执行编译:

make -j$(nproc)
sudo make install

在昇腾服务器上,一般核心数量都不少, make -j$(nproc) 会调用所有可用核心参与编译,通常十几分钟就能完成。如果中途编译报错,我下面单独列一节常见的错误排查。

安装完成后,需要把 /usr/local/ffmpeg-ascend/bin 加入PATH:

export PATH=/usr/local/ffmpeg-ascend/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/ffmpeg-ascend/lib:$LD_LIBRARY_PATH

5. 验证NPU加速是否生效

5.1 使用ffmpeg -hwaccels检查硬件加速设备

编译完成后,第一步先验证FFmpeg是否识别了昇腾硬件后端:

ffmpeg -hwaccels

输出来看,如果环境正常且补丁生效,你会看到类似这样的结果:

Hardware acceleration methods:
vdpau
cuda
vaapi
qsv
d3d11va
ascend

注意里面出现了 ascend ,这说明FFmpeg的硬件加速框架里已经注册了昇腾设备。如果这一步没看到ascend,后面所有的NPU调用都会失败,建议回头检查补丁和configure参数。

5.2 使用dvpp硬解码器进行实测算例

接下来用一个真实的H.264/H.265视频文件来测试硬解。假设测试文件为 test.h265 ,分辨率是1080p,码率8Mbps。

先用CPU软解看看基准数据:

ffmpeg -i test.h265 -c:v rawvideo -pix_fmt yuv420p -f null /dev/null

再使用NPU-DVPP硬解:

ffmpeg -c:v h265_ascend -i test.h265 -c:v rawvideo -pix_fmt yuv420p -f null /dev/null

注意这里我指定的解码器是 h265_ascend ,具体的解码器名称以你在 ffmpeg -decoders 里看到的实际输出为准。如果你的CANN版本较新,可能是 h265_ascend ,也可能是 h265_ascend_v3 之类的新名称。

实测下来,1080p H.265视频流,硬解模式下CPU占用率降到了个位数甚至接近零,而软解模式下CPU好几个核都会被打满。这个直观对比会比任何参数都有说服力。

5.3 硬解输出与CV/推理衔接的常见做法

很多人的实际需求是:解码出来的视频帧直接喂给昇腾NPU做推理。FFmpeg硬解后拿到的数据通常是NV12或YUV420SP格式,而推理模型(比如YOLO系列的前处理)往往需要RGB格式的tensor输入。

最稳妥的做法是,在FFmpeg解码拿到AVFrame之后,增加一个格式转换步骤,把NV12转成RGB24,再做归一化和resize。昇腾CANN提供了 acl_dvpp 接口,可以直接在DVPP内部完成颜色转换和缩放,不需要把数据搬回CPU再处理,效率会高很多。

我建议不要把格式转换放到FFmpeg里做,而是直接用CANN的VPC接口做。因为FFmpeg的 sws_scale 走的是CPU,一旦视频分辨率大了(比如4K),CPU占用会立刻上来,之前的硬解优势就浪费了一大半。

6. 常见问题与排查技巧实录

6.1 configure阶段报错“ERROR: ascend not found”

这个问题通常是因为补丁没有打全,或者configure脚本中相关的探测逻辑没找到CANN头文件。

排查思路:

  • 确认 /usr/local/Ascend/ascend-toolkit/latest/include 目录存在且非空。
  • 在configure命令中明确指定 --extra-cflags=-I/usr/local/Ascend/ascend-toolkit/latest/include 。
  • 检查CANN的 set_env.sh 是否已经source过,必要时在终端手动执行 source /usr/local/Ascend/ascend-toolkit/set_env.sh 后再configure。

6.2 编译时报错“libascendcl.so: cannot open shared object file”

编译链接阶段遇到这个问题,说明链接器找不到CANN的动态库。

解决办法:

export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH

再重新编译即可。另外也建议把这一行写入 ~/.bashrc ,避免每次新开终端都手动设置。

6.3 运行时报错“Failed to create ascend device context”

这个错误一般出现在调用硬解码器时,直接原因有两个:

  • 当前用户对昇腾设备没有访问权限。昇腾设备节点在 /dev/davinci* 下,需要确保当前用户属于 HwHiAiUser 用户组,或者在root权限下运行。
  • 环境变量没设置完整。尤其是 ASCEND_DEVICE_ID ,如果不指定,默认访问设备0,如果你的设备ID不是0,需要明确设置:
export ASCEND_DEVICE_ID=0

6.4 硬解码输出花屏或绿屏

花屏问题的常见原因是输入视频流本身有问题,比如损坏的H.264流或丢包严重的RTSP流。DVPP硬解对输入码流的容错能力不如软件解码器,遇到损坏的帧直接输出异常图像。

解决建议:在FFmpeg命令中增加错误容忍参数,比如 -err_detect ignore_err 。但最重要的是,不要把硬解用在码流严重不稳定的场景里,如果视频源本身质量差,建议先用软解做容错,稳定后再转硬解,或者干脆保留软解。

6.5 硬解视频的AVFrame格式与预期不一致

DVPP硬解输出的AVFrame格式严格依赖输入码流的编码格式。如果是H.264,输出通常是NV12;如果是JPEG解码,输出可能是YUV444等。这些格式细节一定要在代码里查 frame->format 再决定后续处理,不要硬编码。

很多刚开始集成的人会踩这个坑:默认认为硬解输出是NV12,结果实际拿到的不是,导致下游处理直接报错。我的习惯是先打印一帧的 frame->format 确认结果,再写后面的处理逻辑。

6.6 常见问题速查表

问题现象 可能原因 解决办法
configure报错找不到ascend 补丁没打全或CFLAGS未指定 检查补丁文件,显式设置extra-cflags
编译链接时报libascendcl缺失 LD_LIBRARY_PATH未设置 设置LD_LIBRARY_PATH指向CANN lib64
运行时报Failed to create device 设备权限或ASCEND_DEVICE_ID错误 加入HwHiAiUser组,设置设备ID
硬解花屏 输入码流损坏 增加容错参数,或使用软解
硬解输出格式不对 未检查frame->format 动态判断格式再下游处理
解码速度慢 未真正走DVPP 用ffmpeg -hwaccels确认ascend已注册

7. 性能实测与参数调优记录

7.1 软解vs NPU硬解CPU占用对比

我在一台双路Intel Xeon Silver 4210R服务器上做了对比测试,用的昇腾卡是Atlas 310P3。测试视频是1080p H.265,码率8Mbps,时长60秒。

软解时,FFmpeg的CPU占用率大概在350%到400%之间(也就是将近4个完整核心)。纯软解的解码耗时让我直接觉得不太能接受——这还是在没有任何推理负载的情况下,如果后面再接一个YOLO推理,CPU基本就饱和了。

切换为昇腾DVPP硬解后,同一路视频的CPU占用率降到了5%以下,解码耗时几乎可以忽略不计。整条链路变成了:网络拉流 → DVPP硬解 → VPC缩放和格式转换 → NPU推理,全程没有CPU参与视频处理。这个对比结果让我最终确定: 在视频分析场景里,硬解不是锦上添花,而是刚需。

7.2 多路并发解码的稳定性

很多人关心多路解码能力。我实测过4路1080p H.265同时解码,310P3都能稳定跑下来,CPU占用率依然很低。如果继续增加到8路,资源占用会抬升,但如果你的业务场景只是做视频巡检,单卡跑8路以内基本没问题。

需要提醒的是,多路解码时要注意显存和DVPP内存的管理。CANN的DVPP内存池是独立管理的,如果你在应用层频繁申请和释放,会产生内存碎片,长期运行后可能申请不到连续内存。建议开启CANN提供的内存池复用机制,或者自己维护一个AVFrame内存池。

7.3 参数调优建议

影响硬解性能的关键参数主要有三个。

第一个是 -threads 。硬解模式下DVPP解码本身是多线程的,但FFmpeg侧的demux和滤镜链的线程数可以适当调低,避免无谓的CPU竞争。我一般设置 -threads 2 就够了。

第二个是 -buffer_size 和 -probesize 。这两个参数影响拉流时缓存区的大小。视频流如果是实时流,建议把缓存区调大一点,比如 -buffer_size 1024k ,避免网络抖动导致丢帧。

第三个是 -re 参数。如果你是推送本地文件模拟实时流,必须加 -re ,否则FFmpeg会以最快速度发流,下游设备可能承受不住。

8. 集成到C++工程的关键代码片段

视频处理场景里,很多人不是直接敲ffmpeg命令行,而是把FFmpeg作为库集成到自己的C++服务里。昇腾硬解的集成方式也比较简单,核心是通过 av_hwdevice_ctx_create 创建昇腾设备上下文。

下面给一段简化的集成代码(基于C接口):

AVBufferRef *hw_device_ctx = NULL;
// 注意device_type的值要和编译时enable的ascend后端一致
enum AVHWDeviceType type = av_hwdevice_find_type_by_name("ascend");
if (type == AV_HWDEVICE_TYPE_NONE) {
    fprintf(stderr, "ascend device type not found.\n");
    return -1;
}

int ret = av_hwdevice_ctx_create(&hw_device_ctx, type, NULL, NULL, 0);
if (ret < 0) {
    fprintf(stderr, "Failed to create ascend device context.\n");
    return ret;
}

拿到了hw_device_ctx之后,在初始化解码器时,把它设置到 AVCodecContext 的 hw_device_ctx 字段即可。解码过程中拿到的 AVFrame ,通过 av_hwframe_transfer_data 可以把硬件帧数据拷到内存,不过昇腾平台通常建议直接访问设备内存做推理,避免来回拷贝。

具体的C++封装代码比较长,就不全贴了。核心思路就是:解码器初始化和普通解码完全相同,只是多了hw_device_ctx的设置。如果后续大家感兴趣,我可以单独写一篇关于FFmpeg硬解衔接昇腾推理的C++实现。

9. 还会踩到的坑:Docker环境和系统服务执行

9.1 Docker容器里跑FFmpeg的注意事项

很多生产环境会把FFmpeg封装成容器。昇腾在Docker场景下有一个特殊要求:容器启动时必须要挂载昇腾设备节点,并注入相关环境变量。之前有客户在我面前演示Docker里跑 ffmpeg -decoders ,一切正常,但一执行硬解就报设备找不到,折腾了半天才发现是设备没挂载。

Docker启动升腾容器时,关键参数如下:

docker run -it \
  --device=/dev/davinci0 \
  --device=/dev/davinci_manager \
  --device=/dev/hisi_hdc \
  -v /usr/local/Ascend:/usr/local/Ascend \
  -v /etc/ascend_install.info:/etc/ascend_install.info \
  your_image

另外 /dev/davinci* 节点数量取决于服务器上插了几张卡,如果你是多卡服务器,需要把用到的设备节点都挂载进去。

9.2 systemd服务里设置环境变量

如果你用systemd守护FFmpeg进程,切记在service文件里设置好环境变量。我自己踩过这个坑:当时进程起来之后,硬解调用一直报错,日志里又没有明确的提示,后来排查才发现systemd服务默认不继承用户shell里的环境变量,CANN的库路径根本没生效。

systemd service的关键配置如下:

[Service]
Environment=ASCEND_HOME_PATH=/usr/local/Ascend/ascend-toolkit/latest
Environment=LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:/usr/local/ffmpeg-ascend/lib
Environment=ASCEND_DEVICE_ID=0

设置好之后别忘了 systemctl daemon-reload 。

9.3 进程异常退出与内存资源回收

NPU硬解进程如果异常崩溃,DVPP内存可能不会自动释放干净。重新启动进程时,可能会报设备内存不足的错误。这时候最直接的办法是先查看昇腾设备的内存占用情况:

npu-smi info

如果确认是内存泄漏,最彻底的解决方式是重启容器或重启进程,必要时重启设备驱动。但更好的做法是在代码里加上信号处理,在进程收到SIGTERM或SIGINT时显式调用 aclrtResetDevice 做资源回收。

10. 一次典型的完整实测记录

最后分享一段我最近做的一次完整测试流程,方便你照着跑一遍,验证自己的环境是否OK。

测试环境:

  • 硬件:Atlas 310P3
  • 系统:Ubuntu 20.04
  • CANN:7.0.RC1
  • FFmpeg:master分支 + 昇腾NPU补丁

第一步,确认设备状态:

npu-smi info

正常会显示设备健康状态、显存占用、算力状态。

第二步,拉一个H.265测试视频。我用FFmpeg自己生成了一段测试流:

ffmpeg -f lavfi -i testsrc2=size=1920x1080:rate=30 -t 10 -c:v libx265 -x265-params log-level=error test.h265

第三步,软解和硬解做对比:

# 软解
time ffmpeg -c:v hevc -i test.h265 -f null /dev/null

# 硬解
time ffmpeg -c:v h265_ascend -i test.h265 -f null /dev/null

第四步,查看解码器是否真的走NPU。可以在FFmpeg运行时通过命令查看NPU使用率,一个比较直观的方式是同时跑 npu-smi info 观察AI Core和视频编解码单元的工作状态。

确认硬解生效后,继续跑一个完整的转码链路,比如把硬解输出直接送到编码器:

ffmpeg -c:v h265_ascend -i test.h265 -c:v libx264 -preset veryfast -f mp4 output.mp4

如果这一步能顺利产出正常的MP4文件,说明整个FFmpeg集成NPU加速的流程已经闭环。

我自己前后试过几次才跑通完整流程,最大的心得是: 昇腾平台不像普通的CUDA生态那样有大量现成轮子可以套用;很多细节都需要自己去看源码、读文档、跑实验来验证。 但也正因为如此,一旦打通并沉淀出自己的编译脚本和部署方案,后面复制到其他机器上就非常顺了。希望这篇文章能让你在第一次搞昇腾FFmpeg时少一点无从下手的感觉,如果后续有时间,我还会把硬解帧数据直通NPU推理的内存管理细节单独整理出来再分享一篇。

更多推荐