📺 B站 嵌入式孙老师:博主个人介绍
📘 博主书籍-京东购买链接:Yocto项目实战教程
📘 加博主微信,进技术交流群:jerrydev
大家好,我是孙杰。

最近我和 与非网、贸泽电子 合作,做了一套 Jetson 边缘嵌入式实战课程。前面六讲,我们把 Jetson 的硬件平台、JetPack、L4T、Yocto、Secure Boot,以及 OP-TEE 安全体系都逐步讲清楚了。第七讲,我们又专门讲了 GStreamer 是什么,先把 Pipeline、Element、Caps、Plugin 这些基础概念梳理了一遍。
到了第八讲,课程开始从“理解 GStreamer”进入“真正跑视频流”。
这一讲的主题是:
GStreamer 视频流实战:在 Jetson 上把 USB 摄像头画面跑起来,并搞清楚 YUY2 和 MJPEG 到底怎么选。
很多同学在 Jetson 上接摄像头时,最容易遇到的问题不是模型推理,而是视频链路本身:
- 摄像头能识别,但画面打不开;
/dev/video0存在,但 Pipeline 报错;- 同样是 30fps,为什么 YUY2 只能低分辨率?
- 为什么 MJPEG 可以跑到 2K 30fps?
- 画面显示出来了,怎么判断 Jetson 的硬件负载是否正常?
这一讲我尽量用工程视角,把视频流里的分辨率、FPS、V4L2 格式查询、GStreamer Caps、YUY2/MJPEG 对比,以及 Jetson 硬件负载观察讲清楚。

本文基于第八讲课程 PPT 内容整理。
一、为什么要讲 GStreamer 视频流实战
第七讲我们讲的是 GStreamer 的基础概念,重点是建立“流水线思维”:
Source → Convert → Encoder → Mux → Sink
到了第八讲,就要把这条流水线真正跑起来。
在边缘 AI、机器人、工业相机、智能摄像头这些场景里,视频链路通常是这样的:
摄像头采集
↓
格式转换 / 解码
↓
显示 / 编码 / 保存 / 推流
↓
AI 推理
如果前面的视频流没有打通,后面的 AI 推理、目标检测、录像、推流都无从谈起。
所以这一讲的核心不是背命令,而是建立一个调试顺序:
先确认摄像头支持什么格式
↓
再写对应的 GStreamer Caps
↓
把画面显示出来
↓
最后观察 Jetson 硬件负载
很多 GStreamer 问题,本质上不是命令复杂,而是格式、分辨率、帧率和带宽没有匹配好。
二、这一讲主要讲什么
这一讲内容可以压缩成四件事:
- 视频流中的分辨率、像素数量、FPS 到底影响什么;
- 如何用 V4L2 查看摄像头支持哪些格式;
- YUY2 和 MJPEG 两种格式在 Jetson 上怎么显示;
- 如何用 GPU Power GUI 和
tegrastatus观察 Jetson 硬件状态。
把这四件事理顺,后面再做视频录制、网络推流、多路摄像头、AI 推理,思路就会清楚很多。
三、几个核心知识点
1. 视频流最基础的三个参数:分辨率、像素数量、FPS

视频流里最关键的三个参数是:
| 参数 | 含义 | 影响 |
|---|---|---|
| 分辨率 | 画面宽高,例如 1920×1080 | 决定画面细节 |
| 像素数量 | 宽 × 高 | 决定单帧数据量 |
| FPS | 每秒帧数 | 决定流畅度和吞吐压力 |
比如 1080P:
1920 × 1080 = 2,073,600 像素
如果是 30fps,就意味着系统每秒要处理 30 张 1080P 图像。
在 GStreamer Pipeline 中,这些参数通常会写在 Caps 里:
gst-launch-1.0 v4l2src ! \
"video/x-raw,width=1920,height=1080,framerate=30/1" ! \
videoconvert ! autovideosink
这条命令里的核心含义是:
分辨率:1920×1080
帧率:30fps
格式:RAW 原始视频流
这里要注意,分辨率越高、FPS 越高,不只是画面更清晰,也意味着数据量更大,对 USB 带宽、内存搬运、格式转换、显示和编码都会带来压力。
所以视频流调试不要一上来就追求最高规格,更合理的方式是:
先低分辨率跑通链路
↓
再提高分辨率
↓
再提高 FPS
↓
最后观察系统负载
2. 写 Pipeline 之前,先用 V4L2 查摄像头能力
在 Jetson 上调试 USB 摄像头,第一步不是直接写复杂的 GStreamer 命令,而是先确认摄像头到底支持什么格式。
常用命令如下。
查看设备列表:
v4l2-ctl --list-devices
查看当前格式:
v4l2-ctl -d /dev/video0 --get-fmt-video
查看全部支持格式:
v4l2-ctl -d /dev/video0 --list-formats-ext
常见视频格式大致可以分为三类:
| 类型 | 常见格式 | 特点 |
|---|---|---|
| 未压缩 RAW | RGB888、YUYV、NV12 | 数据量大,质量好 |
| 压缩格式 | MJPG、H.264、H.265 | 数据量小,需要解码 |
| 传感器 RAW Bayer | SRGGB10、BGGR12 | 需要 ISP 处理 |
本节课使用的是 USB UVC 摄像头。通过 v4l2-ctl 查询可以看到一个很典型的现象:
MJPEG:最高支持 2560×1440@30fps
YUYV:30fps 下仅支持 640×480
这也是本节课最核心的问题来源:
同一个摄像头,为什么 MJPEG 可以跑 2K 30fps,而 YUY2 只能跑 640×480@30fps?
答案不在 Jetson 算力,而在数据格式。
3. 一个容易误解的点:一个 video 节点可以支持多种格式
USB UVC 摄像头通常只暴露一个 /dev/video0 节点。
但这不代表它只有一种输出能力。
不同格式不是通过多个 /dev/video 节点区分,而是通过同一个 video 节点里的 pixel format 选择:
/dev/video0
├── YUYV / YUY2
├── MJPEG
└── 其他格式
所以调试时,不能只看有没有 /dev/video0。
真正要看的,是这个节点支持哪些:
format
width
height
framerate
很多 Pipeline 报错,根源都是 Caps 写了摄像头不支持的格式组合。
4. YUY2:RAW 原始流,适合调试链路
YUY2 / YUYV 属于未压缩 RAW 视频格式。
它的特点是:
- 数据没有压缩;
- 每一帧都是原始像素;
- 链路简单,延迟低;
- 但数据量大,对 USB 带宽和内存压力高。
课程中的 YUY2 显示命令如下:
gst-launch-1.0 v4l2src device=/dev/video0 ! \
"video/x-raw,format=YUY2,width=640,height=480,framerate=30/1" ! \
nvvidconv ! nveglglessink
这条 Pipeline 可以拆成:
v4l2src
↓
YUY2 RAW 帧
↓
nvvidconv
↓
nveglglessink
每个模块的作用如下:
| 模块 | 作用 |
|---|---|
v4l2src | 从 USB 摄像头采集视频 |
video/x-raw,format=YUY2 | 指定摄像头输出 YUY2 RAW |
640×480@30fps | 限制分辨率,降低带宽压力 |
nvvidconv | Jetson 上进行格式 / 内存转换 |
nveglglessink | GPU 显示输出 |
YUY2 更适合:
- 摄像头驱动验证;
- Pipeline 基础调试;
- 底层链路问题定位;
- 低延迟、小分辨率预览。
一句话总结:
YUY2 更适合看链路是否通。
5. MJPEG:压缩流,适合高分辨率应用
MJPEG 是压缩格式。
它的特点是:
- 摄像头端已经完成 JPEG 压缩;
- USB 上传输的是压缩后的图像;
- 带宽压力比 RAW 小很多;
- 可以支持更高分辨率;
- 显示前需要先解码。
课程中的 MJPEG 显示命令如下:
gst-launch-1.0 v4l2src device=/dev/video0 ! \
'image/jpeg,width=2560,height=1440,framerate=30/1' ! \
jpegdec ! nvvidconv ! nveglglessink
这条 Pipeline 可以拆成:
v4l2src
↓
MJPEG 压缩帧
↓
jpegdec
↓
nvvidconv
↓
nveglglessink
每个模块的作用如下:
| 模块 | 作用 |
|---|---|
v4l2src | 从 USB 摄像头采集视频 |
image/jpeg | 指定摄像头输出 MJPEG |
2560×1440@30fps | 启用 2K 分辨率 |
jpegdec | 对 MJPEG 进行解码 |
nvvidconv | 转换为适合 Jetson 显示的格式 |
nveglglessink | GPU 显示输出 |
MJPEG 更适合:
- 实际产品显示;
- 高分辨率预览;
- USB 摄像头工程交付;
- 需要稳定 2K 30fps 的场景。
一句话总结:
MJPEG 更适合真正跑应用。
6. YUY2 和 MJPEG 怎么选

两者对比如下:
| 对比项 | YUY2 / RAW | MJPEG |
|---|---|---|
| 数据形态 | 未压缩原始像素 | JPEG 压缩帧 |
| 数据量 | 大 | 小 |
| USB 带宽压力 | 高 | 低 |
| 是否需要解码 | 不需要 | 需要 jpegdec |
| 延迟 | 较低 | 略高 |
| 高分辨率支持 | 受带宽限制明显 | 更容易支持 |
| 本节课示例 | 640×480@30fps | 2560×1440@30fps |
| 适合场景 | 调试链路 | 产品预览 |
核心结论:
YUY2 是原始像素流,MJPEG 是压缩后的图像流。
YUY2 更适合调试,MJPEG 更适合高分辨率应用。
7. Jetson 上不能只看画面,还要看硬件负载
Jetson 的视频和 AI 性能,不是只由 GPU 决定。
它是一套异构并行架构,视频链路中可能涉及 CPU、GPU、NVDEC、NVENC、VIC、内存和温度等多个模块。
| 模块 | 关注指标 | 常见异常 |
|---|---|---|
| GPU / GR3D | 利用率、频率、温度、功耗 | 频率不上升、利用率低 |
| CPU | 每核频率、占用率 | 单核 100%、频率偏低 |
| NVDEC | 解码利用率 | 解码瓶颈导致掉帧 |
| NVENC | 编码利用率 | 编码占满导致延迟 |
| VIC | 缩放、格式转换负载 | 转换过多导致推理延迟 |
| RAM | 内存、Swap | 内存不足导致卡顿 |
| 温度 | CPU/GPU/SoC 温度 | 高温导致降频 |
所以视频流调试不能只问:
画面有没有出来?
还要继续看:
CPU 是否跑满?
GPU 是否被限制?
VIC 是否压力过高?
温度是否导致降频?
功耗模式是否限制性能?
课程中提到两个工具:
| 工具 | 特点 | 适合场景 |
|---|---|---|
| GPU Power GUI | 图形化,直观看 GPU 状态 | 快速观察、课堂展示 |
tegrastatus | 命令行,信息更完整 | 长时间监控、定位瓶颈 |
GPU Power GUI 适合快速看 GPU 利用率、频率、温度、功耗,以及 NVENC / NVDEC 是否 online。
但如果要进一步分析系统瓶颈,还是要结合命令行工具:
sudo tegrastats
重点观察:
- CPU 是否长期低频;
- GR3D 频率是否正常;
- NVENC / NVDEC 是否启用;
- RAM 是否接近满;
- 温度是否过高;
- 电源轨功耗是否变化。
一句话总结:
GPU Power GUI 适合快速看状态,
tegrastatus更适合定位瓶颈。
四、这一讲的重点
如果把这一讲再压缩,必须抓住下面几条:
- 视频性能由分辨率、像素数量和 FPS 共同决定;
- 写 GStreamer Pipeline 之前,先用 V4L2 查清摄像头支持格式;
- YUY2 是 RAW 未压缩流,数据量大,适合调试;
- MJPEG 是压缩流,带宽压力小,适合高分辨率预览;
- Jetson 上显示建议结合
nvvidconv和nveglglessink; - 画面显示出来不代表系统稳定,还要看 GPU Power GUI 和
tegrastatus; - Pipeline 报错时,优先检查 Caps 是否和摄像头能力匹配。
这一讲的难点,主要在格式匹配和工程判断:
不是看到
/dev/video0就说明摄像头没问题,也不是画面显示出来就说明系统性能没问题。
真正的调试习惯应该是:
查格式
↓
写 Caps
↓
跑 Pipeline
↓
看负载
↓
再优化
五、适合哪些人学习
如果你正处在下面这些阶段,这一讲会很适合你:
- 想在 Jetson 上跑 USB 摄像头;
- 想理解 YUY2、MJPEG、RAW、压缩流的区别;
- 想搞清楚 GStreamer Caps 为什么重要;
- 想做摄像头预览、录像、推流;
- 想用 Jetson 做机器人视觉、工业相机、AI Box;
- 后面准备把视频链路接到 AI 推理或 DeepStream 上。
哪怕你现在还写不出复杂 Pipeline,也没关系。
先把 YUY2 和 MJPEG 这两条链路跑通,很多视频流问题就已经能看懂一半了。
六、视频与课程入口
B站视频地址:
https://www.bilibili.com/video/BV1RS8i6zEEu
与非网课程入口:
https://www.eefocus.com/course/1993803.html
本系列课程《Jetson 嵌入式系统定制与边缘计算实战》,围绕 Jetson 平台的系统定制、边缘计算、多媒体处理和工程实战展开。
第七讲主要讲 GStreamer 的基础概念。
第八讲开始进入视频流实战。
建议大家重点把下面两条 Pipeline 亲自跑一遍:
gst-launch-1.0 v4l2src device=/dev/video0 ! \
"video/x-raw,format=YUY2,width=640,height=480,framerate=30/1" ! \
nvvidconv ! nveglglessink
gst-launch-1.0 v4l2src device=/dev/video0 ! \
'image/jpeg,width=2560,height=1440,framerate=30/1' ! \
jpegdec ! nvvidconv ! nveglglessink
一条是 RAW 原始流,一条是压缩视频流。
把这两条链路对比清楚,后面再看录像、推流、多路摄像头和 AI 推理,思路会顺很多。
七、最后想分享的话
我一直觉得,Jetson 边缘嵌入式开发里,视频流是一道绕不开的坎。
第一次把摄像头画面稳定显示出来,第一次搞清楚为什么同一个摄像头不同格式表现完全不同,第一次能从 v4l2-ctl、Caps、Pipeline、tegrastatus 这些信息里判断问题,这个过程会让你真正理解“工程调试”是什么。
GStreamer 看起来是一长串命令,本质上还是搭积木。
你需要先搞清楚每块积木的作用:
v4l2src 负责采集
Caps 负责指定格式
jpegdec 负责解码
nvvidconv 负责转换
nveglglessink 负责显示
再搞清楚它们之间的数据格式是否能接上。
第七讲我们建立了流水线思维,第八讲开始把这条流水线真正跑起来。后面无论是做视频录制、RTSP 推流、多路摄像头,还是接 AI 推理,这些基础都会反复用到。
如果你对 Jetson、GStreamer、Yocto、边缘 AI 和嵌入式 Linux 系统定制感兴趣,欢迎继续关注这个系列,后面我会把这些内容继续更新下去。
460

被折叠的 条评论
为什么被折叠?



