You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何序列化GStreamer的Sample对象以通过Kafka发送?

问题描述

尝试用Kafka发送GStreamer的帧Sample对象时,触发序列化错误:

TypeError: cannot pickle 'Sample' object

使用的GStreamer管道:

"rtspsrc location=rtsp://admin:123456@192.168.6.28/sub latency=0 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! video/x-raw,format=BGR,width=640,height=640  ! appsink name=sink sync=false"

报错代码片段:

sample = self.appsink.try_pull_sample(Gst.SECOND)
producer.produce("testTopic", pickle.dumps(sample), "1", callback=delivery_callback)

已尝试json.dumps、bytes、ArrayBytes等方式,均未解决问题。


解决方案

GStreamer的Sample是包含缓冲区、格式元数据的复杂对象,无法直接序列化。正确思路是从Sample中提取原始图像数据和格式信息,再对这些基础数据进行序列化传输,接收端根据信息还原图像。

步骤1:从Sample中提取核心数据

从Sample中取出缓冲区,读取原始字节数据,同时提取图像宽、高、格式等关键信息:

sample = self.appsink.try_pull_sample(Gst.SECOND)
if sample:
    buffer = sample.get_buffer()
    # 映射缓冲区内存以读取数据
    success, map_info = buffer.map(Gst.MapFlags.READ)
    if success:
        # 原始BGR图像字节数据
        img_raw_data = map_info.data
        # 从Caps中提取图像格式参数
        caps = sample.get_caps()
        struct = caps.get_structure(0)
        width = struct.get_value("width")
        height = struct.get_value("height")
        img_format = struct.get_value("format")
        # 释放缓冲区映射
        buffer.unmap(map_info)

步骤2:封装并序列化数据

将原始数据和格式信息封装为可序列化结构,选择适合的序列化方式:

方式1:用Pickle序列化(Python环境下高效)

import pickle

# 封装成字典
frame_package = {
    "width": width,
    "height": height,
    "format": img_format,
    "raw_data": img_raw_data
}
# 序列化后发送到Kafka
serialized_data = pickle.dumps(frame_package)
producer.produce("testTopic", serialized_data, "1", callback=delivery_callback)

方式2:用JSON+Base64(跨语言友好)

由于JSON不支持直接存储字节数据,需先将原始数据转为Base64字符串:

import json
import base64

img_base64 = base64.b64encode(img_raw_data).decode('utf-8')
frame_package = {
    "width": width,
    "height": height,
    "format": img_format,
    "raw_data": img_base64
}
serialized_data = json.dumps(frame_package).encode('utf-8')
producer.produce("testTopic", serialized_data, "1", callback=delivery_callback)

步骤3:接收端还原图像

根据序列化方式反向操作,还原成可处理的图像:

Pickle方式还原

import pickle
import cv2
import numpy as np

# 解析Kafka消息
received_package = pickle.loads(message.value)
# 将字节数据转为numpy数组并reshape为图像
img_array = np.frombuffer(received_package["raw_data"], dtype=np.uint8)
img = img_array.reshape((received_package["height"], received_package["width"], 3))
# 后续处理示例
cv2.imshow("Received Frame", img)

JSON+Base64方式还原

import json
import base64
import cv2
import numpy as np

received_package = json.loads(message.value.decode('utf-8'))
img_raw_data = base64.b64decode(received_package["raw_data"])
img_array = np.frombuffer(img_raw_data, dtype=np.uint8)
img = img_array.reshape((received_package["height"], received_package["width"], 3))
cv2.imshow("Received Frame", img)

优化建议

如果追求传输效率,可修改GStreamer管道,直接传输H264编码后的帧(无需解码为BGR),大幅减少数据体积:

"rtspsrc location=rtsp://admin:123456@192.168.6.28/sub latency=0 ! rtph264depay ! h264parse ! appsink name=sink sync=false"

接收端再对H264数据进行解码即可,适合高帧率、大分辨率场景。

内容的提问来源于stack exchange,提问作者Suhaib Al Hindi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:52:14