使用Image.FromStream()时抛出“Parameter is not valid”异常——UDP树莓派摄像头视频流传输问题
Image.FromStream()时抛出“Parameter is not valid”异常——UDP树莓派摄像头视频流传输问题
嘿,我仔细看了你遇到的问题,咱们来捋清楚为啥会报错,以及怎么解决:
问题根源:编码格式不匹配
你在Python端用H264Encoder输出的是H264编码的视频流数据,而C#的Image.FromStream()只能识别完整的静态图像格式(比如JPEG、PNG这类带文件头的图像文件),它根本不认识H264这种视频编码的帧数据——这就像你把一段MP4视频的字节直接拖进图片查看器,它肯定打不开对吧?所以抛出“Parameter is not valid”是必然的结果。
解决方案分两种思路,按需选择:
思路1:改成发送单帧JPEG图片(适合简单监控场景,实现成本低)
放弃H264编码,让树莓派直接捕获JPEG格式的图像帧,通过UDP发送。这种方式不需要复杂的视频解码,C#端可以直接用Image.FromStream()处理。
修改后的Python服务端代码:
import socket import time import cv2 from picamera2 import Picamera2 host = "你的IP地址" port = 24325 with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as server_socket: server_socket.bind((host, port)) print("UDP Server is listening...") while True: data, addr = server_socket.recvfrom(1024) rx = data.decode() if rx == "STREAM": tx = "STREAMING" server_socket.sendto(tx.encode(), addr) print("Starting stream") picam1 = Picamera2(0) # 配置为JPEG格式的输出 config1 = picam1.create_still_configuration(main={"size": (640, 480), "format": "RGB888"}) picam1.configure(config1) picam1.start() try: while True: # 捕获帧并转成JPEG字节 frame_array = picam1.capture_array("main") _, jpeg_bytes = cv2.imencode('.jpg', frame_array) # 发送JPEG数据 server_socket.sendto(jpeg_bytes.tobytes(), addr) # 控制帧率,避免发送过快 time.sleep(0.033) # 约30帧/秒 except KeyboardInterrupt: picam1.stop() else: print(f"Received from {addr}: {rx}") tx = "Your message received" server_socket.sendto(tx.encode(), addr)
注意:需要先安装opencv-python依赖,执行
pip install opencv-python
对应的C#客户端优化代码(增加数据合法性判断,避免丢包导致的解码失败):
// 接收 livestream 数据 IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0); bool isReceiving = true; if (rx == "STREAMING") { logToConsole("Stream started"); try { while (isReceiving) { byte[] streamData = udpClient.Receive(ref serverEndPoint); // 简单校验是否为JPEG格式(JPEG开头两个字节是0xFF 0xD8) if (streamData.Length >= 2 && streamData[0] == 0xFF && streamData[1] == 0xD8) { using (MemoryStream ms = new MemoryStream(streamData)) { try { Image receivedImage = Image.FromStream(ms); pictureBoxStream.Invoke(new Action(() => { // 释放旧图像资源,防止内存泄漏 if (pictureBoxStream.Image != null) pictureBoxStream.Image.Dispose(); pictureBoxStream.Image = receivedImage; })); } catch (Exception imgEx) { logToConsole("解码图像失败: " + imgEx.Message); } } } else { logToConsole("收到不完整或非JPEG格式的数据"); } } } catch (Exception ex) { logToConsole("接收视频流出错: " + ex.Message); } }
思路2:保留H264视频流,在C#端解码(适合高帧率流畅视频场景)
如果需要真正的低延迟视频流,H264编码的体积优势更明显,这时候需要在C#端用专门的视频解码器处理H264数据。可以借助FFmpeg相关的.NET库(比如FFmpeg.AutoGen)来解码H264流,将解码后的帧转成Bitmap再显示到PictureBox。
这个方案实现稍复杂,核心步骤是:
- 初始化FFmpeg解码器
- 将UDP收到的H264 NALU单元喂给解码器
- 将解码出的YUV帧转换为Bitmap格式
- 更新PictureBox显示
总结
你当前的核心问题是发送的视频流格式和C#端的解码方式不匹配,根据你的场景选对应的方案即可:简单监控用JPEG单帧,流畅视频用H264解码。
备注:内容来源于stack exchange,提问作者Slash
相关产品推荐
相关产品推荐

