跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

RK3588 MIPI 摄像头采集与 WebRTC 低延迟推流实战

RK3588 平台利用 MIPI 接口采集摄像头数据,通过 GStreamer 对接底层驱动并调用硬件 ISP 进行图像预处理。结合 OpenCV 进行必要的图像处理或 AI 推理后,使用瑞芯微 MPP 硬件编码器将画面压缩为 H.264 流。借助轻量级流媒体服务器 MediaMTX 实现局域网内的 WebRTC 协议分发,达成网页端秒开与百毫秒级低延迟观看。客户端可直接通过 FFmpeg 录制原始流文件,全程无需消耗客户端算力。本文详细梳理了从环境搭建、脚本编写到避坑指南的完整链路,解决了内存映射异常、端口配置错误及画面丢帧等常见问题。

萤火微光发布于 2026/4/9更新于 2026/9/474 浏览

RK3588 MIPI 摄像头采集与 WebRTC 低延迟推流实战

在嵌入式开发中,打通从 MIPI 摄像头采集、硬件 ISP 处理、AI 推理到 WebRTC 低延迟推流的完整链路往往比想象中复杂。本文基于 RK3588 平台,分享一套经过验证的实战方案,涵盖环境搭建、核心脚本编写及常见坑点规避。

整体架构思路

本方案主要使用 Python 实现,流程如下:

  1. 画面采集:利用 GStreamer 对接底层驱动,通过 RK3588 的硬件 ISP 将 MIPI RAW 数据转换为彩色图像。
  2. 图像处理:OpenCV 获取图像后,可在此处接入 AI 推理或常规图像处理逻辑。
  3. 硬件编码推流:调用 mpph264enc(瑞芯微硬件编码器)压缩视频流,推送至本地流媒体服务器。
  4. 终端分发:使用轻量级 MediaMTX 作为流媒体服务器,客户端通过 WebRTC 协议实现网页端秒开与超低延迟观看。

第一步:环境准备

首先确认摄像头节点(例如单摄时通常为 /dev/video11)。确保系统安装了支持 GStreamer 的 OpenCV 及相关插件。注意 PyPI 上的默认 OpenCV 可能不支持 GStreamer,建议直接使用系统环境包或手动编译。

sudo apt-get update
sudo apt-get install python3-opencv
sudo apt-get install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-rtsp

第二步:部署轻量级流媒体服务器 (MediaMTX)

此服务器并非传统网站服务器,建议在板子上直接运行,这样客户端无需额外配置。下载 ARM64 版本并启动:

wget https://github.com/bluenviron/mediamtx/releases/download/v1.16.1/mediamtx_v1.16.1_linux_arm64.tar.gz
tar -zxvf mediamtx_v1.16.1_linux_arm64.tar.gz
./mediamtx

启动成功后应看到类似输出,表明 RTSP、WebRTC 等端口已监听:

INF MediaMTX v1.16.1, linux, arm64
INF [RTSP] listener opened on :8554
INF [WebRTC] listener opened on :8889

保持该终端运行,后续操作可在新终端进行。

第三步:核心 Python 脚本

新建脚本 stream.py。代码中包含了降分辨率、防缓存延迟和调用 MPP 硬件编码的核心参数。

import cv2
import time

class FPSCounter:
    """FPS 计数器类"""
    def __init__(self, buffer_size=20):
        self.timestamps = []
        self.buffer_size = buffer_size

    def update(self):
        """更新 FPS 计数"""
        current_time = time.time()
        self.timestamps.append(current_time)
        if len(self.timestamps) > self.buffer_size:
            self.timestamps.pop(0)

    def get_fps(self):
        """计算当前 FPS"""
        if len(self.timestamps) < 2:
            return 0.0
        time_span = self.timestamps[-1] - self.timestamps[0]
        if time_span <= 0:
            return 0.0
        return (len(self.timestamps) - 1) / time_span

# 1. 配置读取摄像头的 GStreamer Pipeline
# 根据你的 MIPI 摄像头节点调整,这里假设是 /dev/video11
# 强制设定分辨率和帧率,并转换为 BGR 格式给 OpenCV 处理
cap_pipeline = (
    "v4l2src device=/dev/video11 io-mode=2 ! "
    "video/x-raw, width=640, height=480, framerate=30/1, format=NV12 ! "
    "videoconvert ! video/x-raw, format=BGR ! "
    "appsink max-buffers=1 drop=true"
)

# 2. 配置推流的 GStreamer Pipeline
# appsrc 接收 OpenCV 的 BGR 图像,转为 NV12,交给 mpph264enc 硬编,然后推流给 MediaMTX
push_pipeline = (
    "appsrc is-live=true ! "
    "video/x-raw, format=BGR, width=640, height=480, framerate=30/1 ! "
    "videoconvert ! video/x-raw, format=NV12 ! "
    "mpph264enc bps=4000000 rc-mode=vbr ! "
    "h264parse ! "
    "rtspclientsink location=rtsp://127.0.0.1:8554/live protocols=tcp"
)

# 初始化视频读取
cap = cv2.VideoCapture(cap_pipeline, cv2.CAP_GSTREAMER)
if not cap.isOpened():
    print("错误:无法打开 MIPI 摄像头。请检查节点和 ISP 状态。")
    exit()

# 初始化视频推流器
out = cv2.VideoWriter(push_pipeline, cv2.CAP_GSTREAMER, 0, 30, (640, 480))
if not out.isOpened():
    print("错误:无法初始化 GStreamer 推流器。")
    exit()

print("成功启动采集和推流,按 'Ctrl+C' 停止。")
try:
    fps_counter = FPSCounter()
    while True:
        ret, frame = cap.read()
        if not ret:
            print("未能读取到画面")
            break

        # ==========================================
        # ★ 在这里加入你的 AI 推理代码 ★
        # ==========================================
        # 例如:results = rknn_model.inference(frame)
        # frame = draw_bounding_boxes(frame, results)

        fps_counter.update()
        fps = fps_counter.get_fps()

        # 作为演示,我们在这里加上时间戳和 fps
        cv2.putText(frame, f"Time: {time.ctime()}", (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1)
        cv2.putText(frame, f"Fps: {fps}", (30, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1)

        # 将画好框的处理后图像,写入推流管道(由 mpp 硬件编码)
        out.write(frame)
except KeyboardInterrupt:
    print("停止推流...")
finally:
    cap.release()
    out.release()

运行脚本:python3 stream.py

第四步:如何在客户端观看与保存?

此时,你的开发板已经变成了一个 IP 摄像头。假设你的板子局域网 IP 是 <设备 IP>。

1. 低延迟观看(网页直开)

直接在电脑或手机浏览器输入:http://<设备 IP>:8889/live(端口号参考 MediaMTX 启动日志)。利用 WebRTC 协议,延迟基本在百毫秒以内。

2. 在客户端无损录像

想要在电脑上把监控视频存下来?只需一行命令,直接将底层编好的 H.264 流封装成文件,完全不消耗客户端算力:

ffmpeg -rtsp_transport tcp -i rtsp://<设备 IP>:8554/live -c copy -f mp4 record_video.mp4

注意这里的端口号选的是 8554(RTSP)。

避坑指南

分享几个过程中最容易卡住的问题:

  1. 使用 GStreamer 无法打开摄像头
    • 原因:RK3588 的 V4L2 驱动在处理 MIPI 摄像头和 ISP 内存时,默认的 mmap 内存映射方式有时会在 GStreamer 中引发异常。
    • 解法:给 v4l2src 加上 io-mode=4(使用 DMABUF)或 io-mode=2(USERPTR)往往能瞬间解决问题。
  2. MediaMTX 报错 invalid rtmp version (71)
    • 原因:进错端口了!用 HTTP 浏览器去访问了 1935 (RTMP) 或 8554 (RTSP) 端口。
    • 解法:浏览器观看必须要访问 8889 端口。
  3. 推流成功了,但是画面全是'纯绿色'
    • 原因:OpenCV 推入的画面分辨率和推流器配置的分辨率不匹配;或者忘记启动 rkaiq ISP 服务导致画面全是空数据。
    • 解法:严格检查 cap_pipeline、cv2.VideoWriter 和 push_pipeline 三个地方的分辨率参数是否完全一致。
  4. 延迟越来越大,跑久了像看回放
    • 原因:加入 AI 推理后处理速度跟不上采集速度,OpenCV 把旧画面全缓存在了内存里。
    • 解法:务必在读取管道末尾加上 appsink max-buffers=1 drop=true。

小贴士

如果单纯想流畅地观看调试图像而不需要 WebRTC,可以直接用 OpenCV 自带的编码函数传 JPEG 到 PC 端,虽然性能不如硬编推流,但简单直接方便:

success, encoded_img = cv2.imencode(".jpg", img)

之后可通过 Flask 等框架进行网络传输。

目录

  1. RK3588 MIPI 摄像头采集与 WebRTC 低延迟推流实战
  2. 整体架构思路
  3. 第一步:环境准备
  4. 第二步:部署轻量级流媒体服务器 (MediaMTX)
  5. 第三步:核心 Python 脚本
  6. 1. 配置读取摄像头的 GStreamer Pipeline
  7. 根据你的 MIPI 摄像头节点调整,这里假设是 /dev/video11
  8. 强制设定分辨率和帧率,并转换为 BGR 格式给 OpenCV 处理
  9. 2. 配置推流的 GStreamer Pipeline
  10. appsrc 接收 OpenCV 的 BGR 图像,转为 NV12,交给 mpph264enc 硬编,然后推流给 MediaMTX
  11. 初始化视频读取
  12. 初始化视频推流器
  13. 第四步:如何在客户端观看与保存?
  14. 1. 低延迟观看(网页直开)
  15. 2. 在客户端无损录像
  16. 避坑指南
  17. 小贴士

更多推荐文章

查看全部
  • 基于 Vue3 与.NET Core 的企业级大文件断点续传及信创适配方案
  • SimVascular 医学影像到血流仿真全流程解析
  • 利用 Python 进行网络接单与兼职赚钱的渠道分析
  • ERNIE-4.5-0.3B 超轻量模型部署与实战测评
  • C/C++ 命名规范:风格、规则与实践详解
  • Python 类方法、实例方法与静态方法深度解析
  • 使用 Whisper-large-v3 搭建本地语音转文字服务
  • C++ 继承机制详解:派生类函数、虚继承与菱形继承案例
  • 2026年AI辅助毕业论文写作工具盘点与使用指南
  • llama.cpp 核心特性、技术原理及部署实践
  • 开源 AI 短剧生成工具 Horseplay 介绍
  • Transformer 在小目标检测领域的应用与发展综述
  • AI 编程工具选型:Copilot、Cursor、Codex 核心差异
  • 35 岁程序员失业危机:现状分析与破局策略
  • 大模型预训练 PT 与有监督微调 SFT 原理详解
  • 25 个降低 AI 检测率的提示词技巧与方法
  • Windows 下使用 WSL2 创建 Ubuntu 子系统并配置图形桌面
  • 大模型技术快速入门指南与学习路径
  • OpenClaw 漏洞预警:如何为 AI 代理构建日志可追溯的安全防线
  • AI 时代为何“人人都是产品经理”成为现实

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online