流数据(Streaming Data)处理

在看代码之前,我们应当首先知道流数据与webSocket 之间的区别(两者不能同一而论),因为存在区别所以在读取数据时使用相对较大的差距

下面我将概述我对两者区别的一个总结(若有不对,请斧正)

流数据(Streaming Data)和 WebSocket 是两种不同的技术,但它们在实时数据传输方面有一些相似之处。以下是它们的区别和相同点:

相同点 

1. 实时性 - 两者都支持实时数据传输,适合需要低延迟的场景,如聊天应用、实时监控等。

2. 双向通信 - WebSocket 和某些流数据技术(如 HTTP/2 流)都支持双向通信,客户端和服务器可以同时发送和接收数据。

3. 持续连接 - 两者都通过建立持久连接来传输数据,避免了传统 HTTP 请求的频繁连接和断开。

4. 适合大流量数据 - 两者都适合处理大流量或持续不断的数据流,如视频流、传感器数据等。

区别

        特性:

                协议:

                        1,WebSocket 基于 WebSocket 协议(独立的协议,建立在 TCP 之上)

                        2,流数据(Streaming Data)通常基于 HTTP/1.1 分块传输编码(Chunked                                 Transfer Encoding)或 HTTP/2 流。

                通信模式:

                        1,WebSocket  全双工通信,客户端和服务器可以同时发送和接收数据。

                        2,流数据(Streaming Data)通常是单向的(如服务器向客户端推送数据),但                                 HTTP/2 支持双向流。

                连接建立:

                        1,WebSocket  需要握手(Handshake)过程,建立 WebSocket 连接后保持长                                  连 接

                        2,流数据(Streaming Data)基于 HTTP 协议,无需额外握手,但可能需要特定                                 的流传输机制。

               数据格式:

                        1,WebSocket  支持二进制和文本数据格式。

                        2,流数据(Streaming Data)通常以分块形式传输数据,格式可以是文本、二进                                 制或其他自定义格式。

                应用场景:

                        1,WebSocket  实时聊天、在线游戏、协作编辑等需要双向通信的场景。

                         2,流数据(Streaming Data) 视频流、音频流、日志流、传感器数据等单向或双                                     向数据流场景。

                兼容性:

                        1,WebSocket  需要浏览器和服务器都支持 WebSocket 协议。

                        2,流数据(Streaming Data)基于 HTTP,兼容性更好,几乎所有浏览器和服务                                 器都支持

                性能:

                        1, WebSocket   由于是专用协议,性能较高,延迟更低

                        2,流数据(Streaming Data)性能依赖于 HTTP 协议,可能不如 WebSocket 高                                 效

接下来我将会先介绍  文本流数据 的读取

                流数据,通过 http 协议进行通信 就按照 正常的请求去获取数据

                eg:              

const response = await fetch('您的URL', {

      method: 'POST',

      headers: {

        'Content-Type': 'application/json'

      },

      body: JSON.stringify(data)

    });

//  获取响应体的读取器 reader,用于逐块读取流数据。(使用 response.body.getReader() 获取一个 ReadableStreamDefaultReader 实例)

const reader = response.body.getReader();

// 创建一个 TextDecoder 实例,用于将二进制数据解码为 UTF-8 格式的文本。

const decoder = new TextDecoder('utf-8');

  let result = ''; // 用于后续存储最后处理的结果

while (true) {  // 使用 while(ture) 循环逐快读取流数据

const { done, value } = await reader.read();  // 每次 调用 reader.read(); 返回一个对象(我是进行了解构) 

解构参数说明:

        done:表示流是否已经结束(true 表示结束)

   value:当前读取的数据块(二进制数据)。

if (done) break; // 如果 done 为 true,跳出循环,表示流数据读取完毕。就break 结束循环

// 解码当前块的数据为文本,并将其按行分割

       const chunk = decoder.decode(value, { stream: true }); // 使用 TextDecoder 将二进制数据块解码为 UTF-8 格式的文本 const decoder = new TextDecoder('utf-8'); 

  • { stream: true } 表示数据可能是不完整的,后续还会有更多数据块。

此时 chunk 就能进行 分割,去空白符等操作(这里我不给实例是因为每个后端可以定义的格式不一样,容易误导)

}

那么触类旁通关于音频流和视频流的相关处理也如上方式,我将分别给出一个实例

1 音频流

async function processAudioStream(url) {

try {

// 发起网络请求获取音频流

const response = await fetch(url);

// 获取响应体的读取器,用于逐块读取音频数据

const reader = response.body.getReader();

// 创建 AudioContext 实例,用于解码和播放音频

const audioContext = new AudioContext();

// 使用 while 循环逐块读取音频数据

while (true) {

// 读取一块数据,返回一个对象 { done, value }

const { done, value } = await reader.read();

// 如果流数据读取完成,跳出循环

if (done) break;

// 解码音频数据为 AudioBuffer

const audioBuffer = await audioContext.decodeAudioData(value.buffer);

// 创建音频源节点

const source = audioContext.createBufferSource();

// 将解码后的音频数据赋值给音频源节点

source.buffer = audioBuffer;

// 将音频源节点连接到音频上下文的目标节点(通常是扬声器) source.connect(audioContext.destination);

// 开始播放音频

source.start();

}

}

catch (error)

{ // 捕获并处理错误 console.error('Error processing audio stream:', error); } }

2 视频流 (使用MediaSource API将视频数据附加到

async function processVideoStream(url) {

try {

// 发起网络请求获取视频流

const response = await fetch(url);

// 获取响应体的读取器,用于逐块读取视频数据

const reader = response.body.getReader();

// 创建 MediaSource 实例,用于处理视频流

const mediaSource = new MediaSource();

// 获取页面中的 video 元素(请使用对应框架的方式来获取DOM元素,我这里是为了方便理解,不推荐)

const video = document.querySelector('video');

// 将 MediaSource 的 URL 赋值给 video 元素的 src

video.src = URL.createObjectURL(mediaSource);

// 监听 MediaSource 的 sourceopen 事件,表示可以开始添加视频数据 mediaSource.addEventListener('sourceopen', () => {

// 创建 SourceBuffer,用于存储视频数据

const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001e, mp4a.40.2"');

// 定义递归函数,逐块读取并添加视频数据

const appendChunk = async () => {

// 读取一块数据,返回一个对象 { done, value }

const { done, value } = await reader.read();

// 如果流数据读取完成,结束流并返回

if (done) { mediaSource.endOfStream(); return; }

// 将读取的视频数据块添加到 SourceBuffer

sourceBuffer.appendBuffer(value);

// 递归调用,继续读取下一块数据

appendChunk(); };

// 开始读取并添加视频数据

appendChunk();

});

}

catch (error)

{ // 捕获并处理错误 console.error('Error processing video stream:', error); } }

(请多多支持呀~)

你可能感兴趣的:(javascript)