本节以 FFMedia SDK 2.6.1 为例,使用预编译的 ffmedia CLI,搭建摄像头采集 → 窗口预览 → H.265 硬件编码 → MP4 录制的完整管线。
准备环境
硬件环境
准备以下硬件:
- Firefly RK 平台(例如 ROC-RK3588-RT Firefly Ubuntu 22.04)
- USB 摄像头或其他可被 Firefly 平台识别为 video 设备的视频源
目标平台接入摄像头后,可先检查 video 设备路径、权限与支持的格式:
ls -l /dev/video*
v4l2-ctl -d /dev/video0 --all # 查看设备详情
v4l2-ctl -d /dev/video0 --list-formats-ext # 查看支持的格式
软件环境
解压 SDK 发布包并确认 CLI 可用:
tar -xzvf ffmedia_release-2.6.1.tar.gz
cd ffmedia_release-2.6.1
./bin/ffmedia --help
./bin/ffmedia run --help
确认运行时哪些模块可用:
./bin/ffmedia modules
./bin/ffmedia params cam
./bin/ffmedia params mpp-enc
./bin/ffmedia params renderer-video
./bin/ffmedia params file-writer
本节管线用到的四个模块:
| 模块 | 类别 | 作用 |
|---|---|---|
cam |
输入(vi) | 通过 V4L2 采集摄像头原始视频帧 |
renderer-video |
输出(vo) | 通过窗口显示摄像头画面 |
mpp-enc |
处理(vp) | 使用 Rockchip MPP 将原始帧编码为 H.265 |
file-writer |
输出(vo) | 将编码码流封装为 MP4 文件 |
验证摄像头可用(仅采集)
先跑最简管线——只采集、不显示,验证摄像头能正常工作:
./bin/ffmedia run \
-m src=cam \
-p 'src:device=/dev/video0;capture{width=1920;height=1080}'
该命令:
- 用
-m src=cam声明一个名为src的采集模块实例 - 用
-p设置设备路径与采集分辨率(子参数用;分隔) - 不连接任何 Consumer,所以不会有窗口、没有输出文件
如果该命令运行后无报错,说明摄像头已被正确识别。
加入窗口预览
在采集的基础上加入显示模块,预览采集到的画面。
管线结构
完整命令
./bin/ffmedia run \
-m src=cam \
-p 'src:device=/dev/video0;capture{width=1920;height=1080}' \
-m dis=renderer-video \
-c src=dis
命令拆解
| 部分 | 含义 |
|---|---|
-m src=cam |
声明采集模块实例 src |
-p 'src:device=...;capture{...}' |
指定设备路径与采集分辨率,多个子参数用 ; 分隔 |
-m dis=renderer-video |
声明窗口渲染模块实例 dis |
-c src=dis |
连接 src → dis;省略通道号时使用默认通道,等价于 src@0=dis |
配置预览窗口的位置与大小
可通过 window 参数配置预览窗口的位置与大(例如位置 (200, 0)、大小 640×480):
./bin/ffmedia run \
-m src=cam \
-p 'src:device=/dev/video0;capture{width=1920;height=1080}' \
-m dis=renderer-video \
-c src=dis \
-p 'dis:window{x=200;y=0;width=640;height=480}'
预览窗口将按设定的位置和大小显示。按 Ctrl + C 停止预览。
同时预览与录制(分支管线)
FFMedia 的核心特性之一是一个 Producer 可以连接多个 Consumer。这一步让 cam 的输出分支为两路:
- 支路 1:直接送
renderer-video,用于窗口预览 - 支路 2:送
mpp-enc编码为 H.265,再由file-writer封装为 MP4 文件
两条支路互不影响,共享同一份采集数据。
管线结构
完整命令
./bin/ffmedia run \
-m src=cam \
-p 'src:device=/dev/video0;capture{width=1920;height=1080}' \
-m dis=renderer-video \
-p 'dis:window{x=200;y=0;width=640;height=480}' \
-c src=dis \
-m enc=mpp-enc \
-p 'enc:encode/codec=6' \
-c src=enc \
-m mux=file-writer \
-p 'mux:path=/home/firefly/Videos/test.mp4' \
-c enc=mux
新增项命令拆解
| 部分 | 含义 |
|---|---|
-m enc=mpp-enc |
声明硬件编码模块实例 enc |
-p 'enc:encode/codec=6' |
编码格式设为 6,代表 H.265(encode/codec 是子参数写法) |
-c src=enc |
采集输出分支接入编码模块(同一 Producer 的第二个 Consumer) |
-m mux=file-writer |
声明文件输出模块实例 mux |
-p 'mux:path=...' |
指定 MP4 输出路径 |
-c enc=mux |
编码码流接入封装写文件模块 |
整个命令中,cam 的实例名始终是 src,而它通过 -c src=dis 和 -c src=enc 同时连接了两个 Consumer。这是「一个 Producer → 多个 Consumer」的最直白体现——不需要额外写分发逻辑,框架自动完成。
编码格式枚举对照表
encode/codec 参数的取值对应不同的视频编码格式,常见值如下:
| 枚举名称 | 整数值 | 说明 |
|---|---|---|
MEDIA_CODEC_UNKNOWN |
0 | 未知编码格式 |
MEDIA_CODEC_VIDEO_VCM |
1 | VCM 视频编码 |
MEDIA_CODEC_VIDEO_MPEG4 |
2 | MPEG-4 视频编码 |
MEDIA_CODEC_VIDEO_MPEG1 |
3 | MPEG-1 视频编码 |
MEDIA_CODEC_VIDEO_MPEG2 |
4 | MPEG-2 视频编码 |
MEDIA_CODEC_VIDEO_H264 |
5 | H.264 (AVC) 视频编码 |
MEDIA_CODEC_VIDEO_H265 |
6 | H.265 (HEVC) 视频编码 ← 本节示例使用 |
MEDIA_CODEC_VIDEO_VP8 |
7 | VP8 视频编码 |
MEDIA_CODEC_VIDEO_VP9 |
8 | VP9 视频编码 |
MEDIA_CODEC_VIDEO_AV1 |
9 | AV1 视频编码 |
MEDIA_CODEC_VIDEO_MJPEG |
10 | Motion JPEG 视频编码 |
MEDIA_CODEC_VIDEO_H266 |
11 | H.266 (VVC) 视频编码 |
MEDIA_CODEC_VIDEO_RAW |
12 | 原始视频数据 |
具体可以参考 SDK 的 include/ffmedia/base/ff_type.hpp。
验证录制结果
运行后可以同时观察到:
- 显示窗口:实时预览摄像头画面
Videos文件夹:test.mp4文件在录制过程中持续增长
使用 Ctrl + C 正常停止管线后,用系统播放器打开 test.mp4,即可回放之前摄像头采集的画面。
注意:MP4 是封装格式,需要正常停止(
Ctrl+C或kill -INT <PID>)才能完整写入文件索引。如果进程被强制杀死(例如kill -9),文件可能大小为零、时长异常或完全无法播放。日常调试时务必使用Ctrl+C优雅退出。
小结
本节用一条真实管线把第一节的 CLI 三要素落地为可运行的命令:
- 第一步(仅采集):用
cam验证摄像头可用,作为后续步骤的基础; - 第二步(加预览):加入
renderer-video,通过-c src=dis完成第一路连接,实现窗口预览; - 第三步(加录制):在第二步基础上,新增
mpp-enc+file-writer,通过-c src=enc与-c enc=mux接入第二路连接——一个 Producer → 多个 Consumer。






