RK3588 MIPI 摄像头采集与 WebRTC 低延迟推流实战
在嵌入式开发中,打通从 MIPI 摄像头采集、硬件 ISP 处理、AI 推理到 WebRTC 低延迟推流的完整链路往往比想象中复杂。本文基于 RK3588 平台,分享一套经过验证的实战方案,涵盖环境搭建、核心脚本编写及常见坑点规避。
整体架构思路
本方案主要使用 Python 实现,流程如下:
- 画面采集:利用 GStreamer 对接底层驱动,通过 RK3588 的硬件 ISP 将 MIPI RAW 数据转换为彩色图像。
- 图像处理:OpenCV 获取图像后,可在此处接入 AI 推理或常规图像处理逻辑。
- 硬件编码推流:调用
mpph264enc(瑞芯微硬件编码器)压缩视频流,推送至本地流媒体服务器。 - 终端分发:使用轻量级
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=):
.timestamps = []
.buffer_size = buffer_size
():
current_time = time.time()
.timestamps.append(current_time)
(.timestamps) > .buffer_size:
.timestamps.pop()
():
(.timestamps) < :
time_span = .timestamps[-] - .timestamps[]
time_span <= :
((.timestamps) - ) / time_span
cap_pipeline = (
)
push_pipeline = (
)
cap = cv2.VideoCapture(cap_pipeline, cv2.CAP_GSTREAMER)
cap.isOpened():
()
exit()
out = cv2.VideoWriter(push_pipeline, cv2.CAP_GSTREAMER, , , (, ))
out.isOpened():
()
exit()
()
:
fps_counter = FPSCounter()
:
ret, frame = cap.read()
ret:
()
fps_counter.update()
fps = fps_counter.get_fps()
cv2.putText(frame, , (, ), cv2.FONT_HERSHEY_SIMPLEX, , (, , ), )
cv2.putText(frame, , (, ), cv2.FONT_HERSHEY_SIMPLEX, , (, , ), )
out.write(frame)
KeyboardInterrupt:
()
:
cap.release()
out.release()

