news 2026/5/1 6:17:35

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
封装 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 作为信令通道,设计了一套标准的信令交互协议。

/* by yours.tools - online tools website : yours.tools/zh/unixtime.html */ // 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 中转)。
/* by yours.tools - online tools website : yours.tools/zh/unixtime.html */ // 处理信令消息的核心逻辑 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 响应式系统 ,我们构建了一套高效的状态同步机制,让复杂的作业流程数据能够实时、准确地呈现在用户面前。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 23:57:42

跨平台地址匹配:基于MGeo实现微信小程序与Web端数据统一

跨平台地址匹配&#xff1a;基于MGeo实现微信小程序与Web端数据统一 为什么需要解决地址匹配问题&#xff1f; 最近在做一个O2O项目时&#xff0c;遇到了一个典型问题&#xff1a;同一用户在小程序端和PC端填写的地址明明指向同一个位置&#xff0c;系统却识别为两个不同地址。…

作者头像 李华
网站建设 2026/4/26 12:17:00

提升开发效率:自动化处理‘内容请求失败‘

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 设计一个自动化脚本&#xff0c;能够在开发过程中实时监控内容请求失败错误&#xff0c;并自动尝试修复。脚本应支持多种编程语言和框架&#xff0c;如JavaScript、Python等&#…

作者头像 李华
网站建设 2026/5/1 6:08:50

地理文本处理新范式:揭秘MGeo多模态预训练技术应用

地理文本处理新范式&#xff1a;揭秘MGeo多模态预训练技术应用 你是否遇到过这样的场景&#xff1a;在处理用户地址数据时&#xff0c;"北京市海淀区中关村大街27号"和"北京海淀中关村大街27号"明明指向同一个地点&#xff0c;却因为表述差异被系统判定为不…

作者头像 李华
网站建设 2026/4/28 3:12:01

功能全解析,最强智能AI雷达名片小程序源码系统

温馨提示&#xff1a;文末有资源获取方式在智能名片小程序竞争日益激烈的今天&#xff0c;一款功能全面、性能卓越的系统是成功的关键。我们自豪地推出智能AI雷达名片小程序企业商业运营版&#xff0c;经过全新升级&#xff0c;集多项强大功能于一身&#xff0c;满足企业各种需…

作者头像 李华
网站建设 2026/4/22 21:51:58

【风电光伏功率预测】阵风(Gust)预测到底差在哪?把“阵风”当一等公民:从气象输入到功率风险的工程落地方案

关键词&#xff1a;风电功率预测、光伏功率预测、新能源功率预测、阵风预测、gust预报、阵风风险预警、风电短临预测、15分钟功率预测、ramp爬坡、尾部风险P95、概率预测P10P50P90、高精度气象预报、3km气象数据、多源气象融合、NWP偏差订正、轮毂高度风速风向、湍流强度TI、风…

作者头像 李华
网站建设 2026/4/27 18:20:37

Service Mesh 下的流量治理:灰度、熔断、限流的深度实践与代价剖析

文章目录一、灰度发布&#xff1a;从“模糊切流”到“精准分发”的技术革命✅ 核心机制&#xff1a;**基于流量标签的智能路由**&#x1f527; 关键实现细节与致命陷阱二、熔断机制&#xff1a;从“代码硬编码”到“策略动态下发”✅ 核心机制&#xff1a;**基于 Envoy 的动态熔…

作者头像 李华