mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
2221 字
11 分钟
WebSocket 实时视频流传输技术实践
2026-04-02
2026-05-13

WebSocket 实时视频流传输技术实践:从连接建立到画质控制#

引言#

本文将介绍我们在物联网设备管理平台中,WebSocket 实时视频流传输功能的开发历程。通过四个阶段的渐进式迭代,我们实现了一套稳定、支持双端的实时视频流系统,支持动态画质控制、分辨率切换,同时解决了连接稳定性、内存泄漏等问题。

系统架构背景#

我们的项目是基于 Vue3 + TypeScript 的物联网设备管理平台,核心需求包括:

  • 设备的实时视频流监控

  • 温湿度等传感器数据展示

  • 设备的远程管理与控制

  • 同时支持桌面端与移动端的双端访问

为了实现低延迟的实时视频传输,我们选择了 WebSocket 协议,相比传统的 HTTP 轮询,它可以实现更低的延迟,同时支持双向的实时控制。

渐进式开发阶段#

我们采用了渐进式的开发策略,从基础功能开始,逐步迭代优化,每个阶段都保证系统可正常运行:

阶段一:基础 WebSocket 连接实现#

开发的第一步,我们先实现了最基础的 WebSocket 连接与数据接收功能,这是整个功能的基础:

// 核心状态管理
const currentFrameImage = ref<string>('');
const isStreamDisconnected = ref<boolean>(false);
const currentFps = ref<number>(0);
let ws: WebSocket | null = null;
let currentImageUrl: string = '';
// 连接建立流程
const startRealtimeMonitoring = async () => {
// 先关闭旧的连接,避免连接泄漏
stopRealtimeMonitoring();
// 获取Token,建立连接
const token = await refreshToken();
const wsUrl = `/api/stream/viewer/ws/${deviceId}?token=${token}`;
ws = new WebSocket(wsUrl);
// 连接状态检测:2.5秒检查一次,2秒无新帧标记为断开
ws.onopen = () => {
streamCheckInterval = window.setInterval(() => {
if (Date.now() - lastFrameTimestamp > 2000) {
isStreamDisconnected.value = true;
}
}, 2500);
};
};

最核心的是图片数据的处理,我们需要兼容多种数据格式,同时做好内存管理:

const handleFrameData = (data: any) => {
// 兼容多种数据格式:base64、Blob、ArrayBuffer、Uint8Array
let blob: Blob;
if (typeof data === 'string') blob = base64ToBlob(data);
else if (data instanceof Blob) blob = data;
else if (data instanceof ArrayBuffer) blob = new Blob([data], { type: 'image/jpeg' });
else if (data instanceof Uint8Array) blob = new Blob([data], { type: 'image/jpeg' });
// 释放旧的URL,防止内存泄漏
if (currentImageUrl) URL.revokeObjectURL(currentImageUrl);
// 创建新的URL用于图片展示
currentImageUrl = URL.createObjectURL(blob);
currentFrameImage.value = currentImageUrl;
// 计算实时帧率
const now = Date.now();
currentFps.value = Math.round(1000 / (now - previousFrameTimestamp));
previousFrameTimestamp = now;
lastFrameTimestamp = now;
};

同时我们配置了 Vite 的代理,支持 WebSocket 的代理转发,解决了开发环境的跨域问题。这一步我们修改了 6 个文件,新增了 404 行基础代码。

阶段二:画质与分辨率控制#

完成了基础的连接后,我们添加了动态的画质与分辨率控制功能,让用户可以根据网络状况调整: 核心的逻辑是通过 WebSocket 发送控制命令,实时调整设备的摄像头参数:

// 发送画质设置到设备
const sendStreamQuality = async (quality: number) => {
if (!ws || ws.readyState !== WebSocket.OPEN) return;
// 双向控制协议
const message = JSON.stringify({
code: 1,
item: 'camera',
key: 'jpeg_quality',
values: quality.toString()
});
ws.send(message);
};
// 监听滑块变化,自动反转值适配用户直觉
watch(imageQuality, (newQuality) => {
// 设备的参数是值越小质量越高,所以我们反转UI的值
// UI滑块:1-63(低-高),实际发送:63-1
const invertedQuality = 63 - newQuality;
sendStreamQuality(invertedQuality);
});

同样的,我们也实现了分辨率的切换,支持 7 种不同的分辨率,从 128x128 到 FHD,用户可以根据需求选择。 UI 界面我们做了简单的控制面板,包含滑块和下拉选择,这一步我们新增了 110 行代码。

阶段三:移动端适配#

完成了桌面端的功能后,我们对移动端做了适配,核心的业务逻辑完全复用桌面端的,仅 UI 层做了差异化:

  • 布局调整:移动端使用垂直堆叠的布局,替代桌面端的水平排列,适配小屏

  • 交互适配:增大了控件的尺寸,适配触摸操作

  • 网络适配:针对移动端的网络环境,默认使用适中的画质,同时提供手动重连按钮

  • 简化界面:移除了不必要的信息,简化了控制面板,保证移动端的简洁

这一步我们修改了移动端的组件,新增了 187 行适配代码,保证了双端的功能一致性。

阶段四:连接模式优化#

最后,我们对连接模式做了优化,解决了之前的一些问题: 我们将原来的多设备共享连接的模式,改为了单设备单连接的模式,每个设备的视频流使用独立的 WebSocket 连接,服务器会自动根据 URL 中的设备 ID 开始推流,不需要额外的请求开启推流,简化了流程。 同时我们优化了消息的处理,支持区分控制命令响应和视频帧数据:

ws.onmessage = (event) => {
// 先处理文本消息:控制命令响应、断开通知
if (typeof event.data === 'string') {
try {
// 尝试解析为JSON,处理控制响应
const data = JSON.parse(event.data);
// 处理画质、分辨率的设置响应
} catch {
// 普通文本消息,比如断开通知
connectionError.value = event.data;
}
} else {
// 二进制数据,处理为视频帧
handleFrameData(event.data);
}
};

这一步我们还修复了设备切换时旧连接未关闭的问题,优化了连接状态的管理,同时精简了 10 行冗余代码。

核心技术架构#

连接生命周期#

整个视频流连接的生命周期非常清晰:

1. 用户选择要监控的设备
2. 获取访问Token,保证连接的安全性
3. 建立WebSocket连接:/api/stream/viewer/ws/{deviceId}?token={token}
4. 连接成功,开始接收视频帧,同时可以发送控制命令
5. 用户切换设备或离开页面时,自动关闭连接

双向消息协议#

我们设计了一套简单的双向消息协议,支持数据传输与控制:

消息类型 方向 格式 说明
视频帧数据 Server → Client Binary JPEG 二进制图像数据
画质设置 Client → Server JSON 动态调整 JPEG 压缩质量
分辨率设置 Client → Server JSON 动态调整视频分辨率
控制响应 Server → Client JSON 控制命令的执行结果
状态通知 Server → Client Text 设备断开、错误等通知

性能优化策略#

为了保证系统的稳定与高效,我们做了这些优化:

  1. 内存管理:每次更新帧的时候,都会释放旧的 Blob URL,避免内存泄漏

  2. 连接状态检测:定期检查帧的接收状态,2 秒无新帧自动标记为断开

  3. 动态画质调整:支持用户根据网络状况实时调整画质,无需重新连接

  4. 多格式兼容:兼容多种数据格式,保证不同环境下的兼容性

实现中的挑战与解决方案#

在开发过程中,我们遇到了一些挑战,对应的解决方案如下:

  1. 多数据格式兼容:WebSocket 可能传输多种格式的图片数据,我们通过类型判断,兼容了所有常见的格式

  2. 用户直觉适配:设备的画质参数是反的(值越小质量越高),我们通过 UI 值的反转,让用户的操作符合直觉

  3. 移动端网络适配:针对移动端的不稳定网络,我们提供了手动重连,同时默认使用适中的画质

  4. 连接稳定性:我们实现了连接状态检测,同时在切换设备时自动关闭旧连接,避免连接泄漏

总结#

通过这四个阶段的迭代开发,我们实现了一个稳定、高效的 WebSocket 实时视频流系统,目前这套系统支持:

  • 低延迟的实时视频流传输

  • 63 级的动态画质控制

  • 7 种分辨率的实时切换

  • 桌面端与移动端的双端自适应

  • 稳定的连接状态管理

这次开发的关键经验是:

  1. 渐进式迭代:先实现基础连接,再添加控制功能,最后优化体验,降低开发风险

  2. 核心逻辑复用:双端共享所有的业务逻辑,仅 UI 层做差异化,减少重复代码

  3. 双向协议设计:简单清晰的双向消息协议,支持数据传输与实时控制

  4. 细节优化:内存管理、连接状态检测这些细节,保证了系统的长期稳定运行

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

WebSocket 实时视频流传输技术实践
https://localhost/posts/websocket_video_stream_development/
作者
青蝶半染
发布于
2026-04-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时