HTML5原生的video标签仅支持HTTP-FLV、HLS、WebRTC等协议,并不支持RTSP协议,因此无法直接播放RTSP流。而WebSocket可以作为中间传输通道,配合流媒体服务器实现RTSP流转为HTML5可识别的格式,让前端完成RTSP流的播放。

HTML5无法直接播放RTSP的原因
RTSP是实时流传输协议,主要用于控制流媒体的播放、暂停、停止等操作,其传输层通常采用TCP或UDP,和HTML5 video标签支持的基于HTTP的流协议完全不同。浏览器的video标签没有内置RTSP协议的解码和传输逻辑,所以直接传入RTSP地址无法播放。
WebSocket在RTSP播放中的作用
WebSocket本身也不是用来直接传输RTSP协议的,它的核心作用是建立浏览器和流媒体服务器之间的全双工通信通道,让服务器可以把处理好的RTSP流数据转发给前端。整个流程的核心原理可以分为几个步骤:
- 流媒体服务器先通过RTSP协议拉取摄像头的RTSP流,完成流的接收和解码
- 服务器把解码后的视频数据重新编码为HTML5支持的格式,比如WebRTC支持的编码格式,或者封装为FLV格式
- 服务器通过WebSocket通道把处理好的视频数据实时推送给浏览器端
- 浏览器端通过JavaScript接收WebSocket传来的数据,交给video标签或者对应的播放器组件渲染播放
WebSocket是否必须
WebSocket并不是唯一的选择,也不是必须的。如果采用WebRTC方案,浏览器可以直接和流媒体服务器建立WebRTC连接传输RTSP转码后的流,不需要WebSocket参与。但如果采用HTTP-FLV或者私有协议传输的场景,WebSocket是常用的中间通道,因为HTTP协议本身不支持服务端主动推送实时流数据,而WebSocket可以满足这个需求。
简单实现示例
流媒体服务器(Node.js + ws模块)示例
这里模拟服务器接收RTSP流后通过WebSocket推送给前端,实际场景中需要对接真实的RTSP拉流逻辑:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// 模拟RTSP流数据,实际场景替换为真实的RTSP拉流逻辑
function mockRTSPStream() {
return Buffer.from('模拟视频帧数据');
}
wss.on('connection', function connection(ws) {
console.log('前端WebSocket连接建立');
// 定时推送模拟的流数据给前端
const timer = setInterval(() => {
const streamData = mockRTSPStream();
ws.send(streamData);
}, 40); // 模拟25帧每秒的推送频率
ws.on('close', () => {
clearInterval(timer);
console.log('前端连接关闭');
});
});
前端接收播放示例
前端通过WebSocket接收数据后,使用flv.js播放FLV格式的流,这里仅展示WebSocket接收部分逻辑:
// 建立WebSocket连接
const ws = new WebSocket('ws://127.0.0.1:8080');
// 存储接收到的流数据
let videoChunks = [];
ws.onopen = function() {
console.log('WebSocket连接成功');
};
ws.onmessage = function(event) {
// 接收服务器推送的流数据
const chunk = event.data;
videoChunks.push(chunk);
// 实际场景中可以把数据喂给flv.js等播放器
console.log('接收到流数据,长度:' + chunk.byteLength);
};
ws.onerror = function(err) {
console.error('WebSocket错误:', err);
};
ws.onclose = function() {
console.log('WebSocket连接关闭');
};
注意事项
实际开发中需要注意流媒体服务器的转码性能,RTSP流转码会消耗一定的服务器资源,高并发场景下需要做好负载均衡。另外WebSocket传输的是二进制流数据,前端接收时需要注意数据格式的解析,避免解析错误导致播放异常。如果选择WebRTC方案,不需要WebSocket也可以实现RTSP流的播放,具体可以根据项目需求选择对应的方案。