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

使用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。

这个方案实现稍复杂,核心步骤是:

  1. 初始化FFmpeg解码器
  2. 将UDP收到的H264 NALU单元喂给解码器
  3. 将解码出的YUV帧转换为Bitmap格式
  4. 更新PictureBox显示

总结

你当前的核心问题是发送的视频流格式和C#端的解码方式不匹配,根据你的场景选对应的方案即可:简单监控用JPEG单帧,流畅视频用H264解码。

备注:内容来源于stack exchange,提问作者Slash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 11:58:09