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

React如何处理WebSocket接收的流式视频与文件数据及判断方案探讨

数据类型区分与处理方案

一、核心思路:给数据打"类型标签"

不管用哪种方案,核心都是在传输数据时附加类型标识,让客户端能快速判断数据用途,再做对应处理。你提到的JSON封装、多路复用都是完全可行的,下面是具体实现细节:


二、JSON封装方案(快速落地首选)

这种方案用统一的JSON结构包裹数据,实现简单,无需额外协议处理:

服务器端(C#)实现

  1. 定义统一的消息结构:
public class WebSocketMessage
{
    public string Type { get; set; } // 类型标识:"video_frame"或"image_file"
    public string Data { get; set; } // 二进制数据转Base64字符串
    public string Metadata { get; set; } // 可选:存图片文件名、视频帧时间戳等元数据
}
  1. 发送视频帧:将FFmpeg输出的二进制帧转成Base64,包装成Type="video_frame"的JSON后发送文本帧。
  2. 发送图片文件:读取本地压缩图片的二进制数据,转Base64后包装成Type="image_file"的JSON发送。

优化点:如果视频流体积大,Base64会带来约30%的带宽损耗,可改用**"文本标识+二进制帧"**组合:先发送一条文本帧(如{"type":"video_frame"}),紧接着发送对应视频帧的二进制数据;图片同理,先发送类型标识文本帧,再发二进制图片。

客户端(React)处理

  1. 监听WebSocket消息:
const ws = new WebSocket('ws://your-server-url');
let lastMsgType = ''; // 缓存上一条文本标识的类型

ws.onmessage = (event) => {
    if (typeof event.data === 'string') {
        const msg = JSON.parse(event.data);
        lastMsgType = msg.type;
    } else {
        // 处理二进制帧
        switch (lastMsgType) {
            case 'video_frame':
                handleVideoStream(event.data);
                break;
            case 'image_file':
                const imgUrl = URL.createObjectURL(event.data);
                setLatestImage(imgUrl);
                break;
        }
    }
};
  1. 视频流处理:使用MediaSource API将接收到的帧拼接成可播放的流,挂载到<video>标签。
  2. 图片处理:直接生成Blob URL,更新<img>的src属性。

三、多路复用方案(高性能场景首选)

如果对带宽和延迟要求高,推荐用单WebSocket连接实现多路复用,通过通道ID区分数据类型:

服务器端(C#)实现

  1. 自定义二进制帧格式:头部用固定长度字节存储通道ID(比如前2字节:0x0001代表视频流,0x0002代表图片),后面跟实际数据。
public void SendMultiplexedData(int channelId, byte[] data)
{
    // 前2字节存通道ID(统一大端/小端格式)
    byte[] header = BitConverter.GetBytes(channelId);
    byte[] frameData = new byte[header.Length + data.Length];
    Buffer.BlockCopy(header, 0, frameData, 0, header.Length);
    Buffer.BlockCopy(data, 0, frameData, header.Length, data.Length);
    // 发送二进制帧
    webSocket.SendAsync(new ArraySegment<byte>(frameData), WebSocketMessageType.Binary, true, CancellationToken.None);
}
  1. 发送视频流调用SendMultiplexedData(1, videoFrameBytes),发送图片调用SendMultiplexedData(2, imageBytes)。

客户端(React)处理

  1. 解析二进制帧头部:
ws.onmessage = (event) => {
    if (event.data instanceof Blob) {
        const reader = new FileReader();
        reader.onload = () => {
            const buffer = new Uint8Array(reader.result);
            // 读取前2字节的通道ID
            const channelId = new DataView(buffer.buffer).getInt16(0);
            const data = buffer.slice(2);

            switch (channelId) {
                case 1:
                    handleVideoStream(new Blob([data], { type: 'video/mp4' }));
                    break;
                case 2:
                    const imgUrl = URL.createObjectURL(new Blob([data], { type: 'image/jpeg' }));
                    setLatestImage(imgUrl);
                    break;
            }
        };
        reader.readAsArrayBuffer(event.data);
    }
};
  1. 视频和图片的后续处理逻辑与JSON方案一致。

四、额外优化建议

  • 视频流优先用二进制传输,避免Base64的带宽损耗;
  • 图片提前在服务器端压缩到合适尺寸,减少传输体积;
  • 客户端添加消息队列,避免高并发时数据处理阻塞;
  • 若无需严格单连接,可直接建立两个独立WebSocket连接:一个传视频流,一个传图片,这种方式最直观,无需额外封装逻辑。

内容的提问来源于stack exchange,提问作者Minwoo Kim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:07:34