RK3588——网口实时传输视频

由于通过流媒体服务器传输画面延迟太高的问题,不知道是没有调试到合适的参数还是其他什么问题。诞生了这篇博客。

RK3588板端上接摄像头,采集画面,通过网口实时传输给上位机并显示。

第一代版本

RK3588代码
python 复制代码
import cv2
import socket
import struct

# 配置
SERVER_IP = '192.168.137.1'  # 上位机的IP地址
PORT = 5000  # 端口号

# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 打开摄像头
cap = cv2.VideoCapture(23)

if not cap.isOpened():
    print("无法打开摄像头")
    exit()

while True:
    # 读取摄像头帧
    ret, frame = cap.read()
    if not ret:
        print("无法读取帧")
        break
    frame = cv2.resize(frame,(320,240))
    # 对帧进行编码
    encoded, buffer = cv2.imencode('.jpg', frame)

    if not encoded:
        print("编码帧失败")
        break

    # 发送数据
    data = buffer.tobytes()
    print(len(data))
    print(len(struct.pack('L', len(data))))
    print(struct.pack('L', len(data)))
    # 发送数据大小
    client_socket.sendto(struct.pack('L', len(data)), (SERVER_IP, PORT))
    # 发送数据
    client_socket.sendto(data, (SERVER_IP, PORT))

# 释放资源
cap.release()
client_socket.close()
上位机代码(windows系统)
python 复制代码
import cv2
import socket
import numpy as np

# 配置
PORT = 5000  # 端口号

# 创建一个socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', PORT))

# 创建窗口并设置为全屏模式
cv2.namedWindow('Video Stream', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('Video Stream', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

while True:
    # 接收数据大小
    data_size, _ = server_socket.recvfrom(8)

    # 接收的视频数据长度
    data_size = int.from_bytes(data_size, byteorder='little')

    # 接收视频数据
    data, _ = server_socket.recvfrom(data_size)

    # 解码
    np_data = np.frombuffer(data, dtype=np.uint8)
    frame = cv2.imdecode(np_data, cv2.IMREAD_COLOR)

    if frame is None:
        print("解码帧失败")
        continue

    # 显示帧
    cv2.imshow('Video Stream', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
server_socket.close()
cv2.destroyAllWindows()

测试视频

遗留问题:视频每帧只能一次传输完毕,且每帧的大小不能过大,不然会报错。

第二代版本

通过分组发送帧图像的方式,即segment_size,优化了帧图像必须要一次传输的问题。

并且把b'\xff\xff'当作一帧画面传输完成的表中,暂时还没发现什么问题。

RK3588代码
python 复制代码
import cv2
import socket

# 配置
SERVER_IP = '192.168.137.1'  # 上位机的IP地址
PORT = 5000  # 端口号

# 创建一个socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 打开摄像头
cap = cv2.VideoCapture(23)

if not cap.isOpened():
    print("无法打开摄像头")
    exit()

frame_count = 0
segment_size = 65000 #32678 # 一组数据的大小
while True:
    # 读取摄像头帧
    ret, frame = cap.read()
    if not ret:
        print("无法读取帧")
        break

    # 对帧进行编码
    encoded, buffer = cv2.imencode('.jpg', frame)

    if not encoded:
        print("编码帧失败")
        break

    # 发送数据
    data = buffer.tobytes()
    data_len = len(data) # 一帧图像的数据大小
    print(data_len)
    # 发送数据

    time = data_len // segment_size # 需要发多少组
    left = data_len % segment_size # 剩下多少个
    if time > 0:
        for i in range(time): # 遍历发送所有的组
            start_pos = i*segment_size 
            end_pos = (i+1)*segment_size
            client_socket.sendto(data[start_pos:end_pos], (SERVER_IP, PORT))
    # 发送剩下的,并且加上结束帧标识符
    client_socket.sendto(data[time*segment_size:data_len] + b'\xff\xff', (SERVER_IP, PORT))

    frame_count +=1
# 释放资源
cap.release()
client_socket.close()
上位机代码(windows系统)
python 复制代码
import cv2
import socket
import numpy as np

# 配置
PORT = 5000  # 端口号

# 创建一个socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', PORT))
# 一组数据的大小
segment_size = 65000 #32678

while True:
    data_byte = b''
    # 接收视频数据
    data, _ = server_socket.recvfrom(segment_size)
    while (b'\xff\xff' not in data):
        data_byte += data
        data, _ = server_socket.recvfrom(segment_size)
    # 把分组发送的字节相加
    data_byte += data
    #去除最后两个结束帧标识符
    rev_data = data_byte[:-2]

    # 解码
    np_data = np.frombuffer(rev_data, dtype=np.uint8)
    frame = cv2.imdecode(np_data, cv2.IMREAD_COLOR)

    if frame is None:
        print("解码帧失败")
        continue

    # 显示帧
    cv2.imshow('Video Stream', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
server_socket.close()
cv2.destroyAllWindows()

后续优化方向:可以通过多线程的方式去发送每组的数据,这样能进一步增加实时性。

相关推荐
EasyGBS13 小时前
国标GB28181视频分析平台EasyGBS视频质量诊断让监控故障“可防可控可溯源“
人工智能·音视频·gb28181·视频质量诊断
Terasic友晶科技15 小时前
1-DE10-Nano的HDMI音频传输案例——I2S通信协议
音视频·de10-nano·hdmi音频传输·i2s通信协议
MonkeyKing_sunyuhua16 小时前
借助openClaw的架构开发短视频生成平台的思路
架构·音视频
非凡ghost16 小时前
proDAD ReSpeedr:专业视频变速编辑的利器
java·网络·windows·python·音视频·软件需求
愚公搬代码18 小时前
【愚公系列】《剪映+DeepSeek+即梦:短视频制作》013-剪辑:把碎片素材串联成片(知识拓展:剪辑点的选择)
音视频
电商API&Tina18 小时前
淘宝商品视频的采集需要注意哪些问题||item_video-获得淘宝商品视频
大数据·网络·数据库·人工智能·python·音视频
雾江流19 小时前
HDx播放器1.0.195 | 4K视频播放器,解码强,内置视频嗅探下载
音视频·软件工程
非凡ghost19 小时前
Smart Launcher安卓版(安卓桌面启动器)
android·windows·学习·音视频·软件需求
EasyDSS19 小时前
EasyDSS以视频点播VOD/高清直播/WebRTC视频会议/语音转写STT技术创新,解决校园数字化核心难题
音视频·webrtc·语音识别·点播技术·流媒体直播
NGBQ1213820 小时前
K-Lite_Codec_Pack_1957_Mega.exe 全解析:Windows 端全能音视频解码器深度指南
windows·音视频