封装 WebRTC 低延迟视频流与 WebSocket 实时状态驱动的大屏可视化

Vue3 实战:封装 WebRTC 低延迟视频流与 WebSocket 实时状态驱动的大屏可视化

在工业互联网和智慧安防领域,实时监控大屏是核心业务场景之一。本文将分享在最近的"油罐车作业智能监控系统"中,如何利用 Vue3 + TypeScript 技术栈,实现低延迟的 WebRTC 视频流播放,以及基于 WebSocket 的全链路作业状态实时同步。

一、 业务背景与挑战

我们需要开发一个监控大屏,实时展示油罐车在卸油作业过程中的监控画面,并同步显示 AI 识别出的作业状态(如:是否佩戴安全帽、是否连接静电球、卸油操作步骤等)。

核心挑战:

  1. 低延迟视频流 :传统的 HLS/FLV 延迟较高(3-10秒),无法满足实时风控需求,必须使用 WebRTC(延迟 < 500ms)。
  2. 信令交互复杂 :WebRTC 需要处理 Offer/Answer、ICE Candidate 等复杂的信令交换流程。
  3. 状态实时同步 :作业流程长、状态多,需要后端 AI 实时推送检测结果,前端界面必须毫秒级响应并刷新 UI。

二、 WebRTC 播放器的优雅封装

为了复用逻辑并隔离底层复杂度,我们封装了一个 WebRTCPlayer 类,专门负责与信令服务器交互和流媒体渲染。

1. 核心类设计 (WebRTCPlayer.ts)

我们采用 WebSocket 作为信令通道,设计了一套标准的信令交互协议。

复制代码
// src/components/Ljh/WebRTC/index.ts

class WebRTCPlayer {
  ws: WebSocket | null = null;
  pc: RTCPeerConnection | null = null;
  // ... 其他属性

  constructor(videoElement: HTMLVideoElement, 
  serverIp: string, taskId: string) {
    this.videoElement = videoElement;
    // 动态构建信令服务器地址
    this.serverUrl = `ws://${serverIp}:8080/ws`;
    this.taskId = taskId;
    // 配置 ICE 服务器 (STUN/TURN)
    this.rtcConfig = { 
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        // 内网环境可配置自建 TURN 服务器
      ]
    };
  }

  // 启动流程:重置状态 -> 连接 WS
  start() {
    this.retryCount = 0;
    this.connectWs();
  }
}

2. 信令交互流程

WebRTC 的核心在于 SDP (Session Description Protocol) 的交换。我们的实现流程如下:

  1. 前端发起请求 :连接 WS 成功后,发送 request_stream 指令。

  2. 后端响应 Offer :后端创建 WebRTC Peer,发送 offer SDP。

  3. 前端应答 Answer :前端收到 Offer,设置 Remote Description,创建 Answer SDP 并发送给后端。

  4. ICE 穿透 :双方交换 ICE Candidate 信息,建立 P2P 连接(或通过 TURN 中转)。

    // 处理信令消息的核心逻辑
    async handleSignalingMessage(msg: any) {
    if (!this.pc) this.createPeerConnection();
    const pc = this.pc!;

    switch (msg.type) {
    case 'offer':
    // 1. 设置远端描述
    await pc.setRemoteDescription({ type:
    'offer', sdp: msg.sdp });
    // 2. 创建本地应答
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    // 3. 发送应答给服务端
    this.send({ type: 'answer', sdp: answer.
    sdp });
    break;

    复制代码
     case 'ice_candidate':
       // 处理 ICE 候选者
       if (msg.candidate) {
          await pc.addIceCandidate({ 
            candidate: msg.candidate, 
            sdpMLineIndex: msg.sdpMLineIndex 
          });
       }
       break;

    }
    }

3. 视频流渲染与自动重连

监听 ontrack 事件将流绑定到
标签,并实现了健壮的 心跳检测 与 断线重连 机制。

复制代码
createPeerConnection() {
  const pc = new RTCPeerConnection(this.
  rtcConfig);
  
  // 收到视频流,自动播放
  pc.ontrack = (event) => {
    const stream = event.streams[0];
    this.videoElement.srcObject = stream;
    this.videoElement.play().catch(e => console.
    error("Autoplay failed", e));
  };

  // 监听连接状态,异常时触发重连
  pc.onconnectionstatechange = () => {
    if (['failed', 'disconnected'].includes(pc.
    connectionState)) {
      this.scheduleReconnect();
    }
  };
}

三、 WebSocket 实时状态驱动 UI

在大屏端,我们需要实时展示作业的各个阶段(准备、检查、卸油、收尾)及其子项状态。

1. 全局 WebSocket Hook (useWebSocket.ts)

使用 @vueuse/core 提供的 useWebSocket 进行二次封装,实现全局单例模式,避免多组件重复连接。

// src/hooks/web/useWebSocket.ts

import { useWebSocket } from '@vueuse/core';

const listeners = new Map(); // 发布订阅中心

export function connectWebSocket(url: string) {

useWebSocket(url, {

autoReconnect: { retries: 10, delay: 5000 },

heartbeat: { message: "ping", interval: 55000 },

onMessage: (_ws, e) => {

if (e.data === 'ping') return;

const data = JSON.parse(e.data);

// 广播消息给所有订阅者

for (const callback of listeners.keys()) {

callback(data);

}

}

});

}

// 组件使用的订阅函数

export function onWebSocket(callback: Function) {

listeners.set(callback, null);

}

2. 数据驱动的动态 UI (Analysis/index.vue)

在 Vue 组件中,我们定义了响应式的 groups 数据结构,通过 WebSocket 推送的数据实时更新状态。

数据结构设计:

const groups = ref([

{

name: '准备阶段',

children: [

{ name: '油罐车进入区域', status: '0', no: 1, icon: truckIcon },

{ name: '静电释放检测', status: '0', no: 2, icon: boltIcon }

]

},

// ... 其他阶段

]);

// 监听 WebSocket 消息

onWebSocket((data) => {

// 收到消息后,重新拉取最新状态(或直接使用 data 更新)

getCurrentStatusData();

});

const getCurrentStatusData = async () => {

const res = await getCurrentStatus({});

if (res.code === 200) {

// 动态映射图标与状态

const data = res.result;

data.forEach(group => {

group.children.forEach(item => {

// 根据名称动态匹配本地 SVG 图标

item.icon = getIconByName(item.name);

});

});

groups.value = data; // 触发视图更新

}

};

四、 总结

通过 WebRTC ,我们将视频流延迟控制在了 500ms 以内,实现了"所见即所得"的监控体验;通过 WebSocket + Vue3 响应式系统 ,我们构建了一套高效的状态同步机制,让复杂的作业流程数据能够实时、准确地呈现在用户面前。

这种"实时流 + 实时信令"的架构模式,不仅适用于智慧安防,在远程医疗、在线教育等对实时性要求极高的场景中也具有广泛的应用价值。

相关推荐
持续升级打怪中2 小时前
WebSocket:从“写信”到“打电话”的实时通信革命
网络·websocket·网络协议
懒人村杂货铺12 小时前
✅ WebSocket 接口从本地开发到生产部署的关键步骤与常见问题
websocket
liwulin050615 小时前
【JAVA】创建一个不需要依赖的websocket服务器接收音频文件
java·服务器·websocket
meichao921 小时前
springboot3.5.8集成websocket问题
网络·spring boot·websocket·网络协议
metaRTC1 天前
metaRTC 8.0 重磅发布:专为新一代 AI 终端而生的实时通信引擎
ai·webrtc
shughui2 天前
OSI 七层 / TCP/IP 四层模型详解 + HTTP 与 WebSocket 接口分类:从协议本质 到 设计规范
websocket·网络协议·tcp/ip·http·设计规范
泡泡以安2 天前
【爬虫教程】第5章:WebSocket协议解析与长连接管理
爬虫·websocket·网络协议
JavaGuru_LiuYu3 天前
Spring Boot 整合原生 WebSocket
spring boot·后端·websocket·即使通信