核心概念

  1. RTSP (Real Time Streaming Protocol / 实时流协议)

    html网页调用监控视频播放器
    (图片来源网络,侵删)
    • 这是最常见的监控摄像头(如海康、大华等品牌)使用的流媒体协议。
    • 不能直接在网页浏览器中播放,因为浏览器原生不支持RTSP协议。
    • 解决方案:需要一个中间服务器(或网关)来接收RTSP流,并将其转换成浏览器可以识别的格式(如 HLS 或 WebRTC)。
  2. HTTP 直播流

    • 一些摄像头或NVR(网络录像机)可以直接提供HLS (HTTP Live Streaming) 或 WebRTC 格式的视频流。
    • HLS (.m3u8 文件) 是目前最广泛兼容的方案,几乎在所有现代浏览器中都能播放。
    • WebRTC 提供最低延迟,但兼容性配置稍复杂。

使用 HLS.js 播放 RTSP / HLS 流 (推荐)

这是最通用、兼容性最好的方案,它需要一个中间服务(如 ffmpeggb28181 等开源流媒体服务器)将RTSP流转换为HLS流。

工作流程: RTSP摄像头 -> 流媒体服务器 (转码) -> HLS流 (.m3u8) -> HTML网页 (HLS.js播放器)

步骤 1:搭建流媒体服务器(以 ffmpeg 为例)

如果你已经有NVR或能提供HLS流的服务,可以跳过此步。

html网页调用监控视频播放器
(图片来源网络,侵删)
  1. 安装 FFmpeg:在你的服务器上安装FFmpeg。

  2. 执行转码命令:在命令行中运行以下命令,将RTSP流持续转换为HLS流并保存到指定目录。

    # 将 'your_rtsp_url' 替换为你的摄像头RTSP地址
    #  rtsp://username:password@ip:port/path
    ffmpeg -i "your_rtsp_url" \
    -c:v copy -c:a aac \
    -f hls \
    -hls_time 4 \          # 每个切片的时长(秒)
    -hls_list_size 6 \      # 播放列表中包含的切片数量
    -hls_flags delete_segments \ # 删除旧切片
    /path/to/output/stream.m3u8

    执行后,FFmpeg会不断生成 .m3u8 播放列表文件和 .ts 视频切片文件。

步骤 2:在HTML中集成 HLS.js

我们可以在网页中播放这个生成的HLS流了。

  1. 引入 HLS.js 库:在HTML文件的 <head> 中引入HLS.js的库文件。
  2. 创建视频容器:在 <body> 中创建一个 <video> 标签,并给它一个 id
  3. 编写初始化脚本:在 <script> 标签中,编写代码来加载和播放视频流。

完整代码示例 (index.html):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">监控视频播放器</title>
    <!-- 引入 HLS.js 库 -->
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .video-container {
            width: 80%;
            max-width: 800px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            border-radius: 8px;
            overflow: hidden;
        }
        video {
            width: 100%;
            display: block;
            background-color: #000;
        }
        .info {
            padding: 10px;
            background-color: #333;
            color: white;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="video-container">
        <video id="videoPlayer" controls autoplay muted></video>
        <div class="info">
            <p>监控画面 - 摄像头 1</p>
        </div>
    </div>
    <script>
        var video = document.getElementById('videoPlayer');
        // 检查HLS.js是否支持
        if (Hls.isSupported()) {
            var hls = new Hls();
            // 将你的HLS播放列表URL (.m3u8) 替换到这里
            hls.loadSource('http://your-server.com/path/to/output/stream.m3u8');
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, function() {
                video.play();
            });
        }
        // 对于支持原生HLS的浏览器(如Safari)
        else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = 'http://your-server.com/path/to/output/stream.m3u8';
            video.addEventListener('loadedmetadata', function() {
                video.play();
            });
        }
    </script>
</body>
</html>

使用 WebRTC 播放(低延迟方案)

WebRTC (Web Real-Time Communication) 提供近乎实时的视频传输,延迟非常低(通常在1秒以内),但搭建和配置相对复杂。

工作流程: RTSP摄像头 -> WebRTC网关/服务器 -> HTML网页 (WebRTC播放器)

步骤 1:搭建 WebRTC 网关

你需要一个能够接收RTSP并将其转换为WebRTC流的服务,有很多开源项目可以实现,

  • LiveWebRTC: 一个简单易用的工具。
  • Ant Media Server: 一个功能强大的专业级媒体服务器。
  • Janus Gateway: 一个通用的WebRTC服务器,需要较多配置。

这里以概念性描述为主,具体部署请参考所选工具的文档,部署完成后,它会提供一个WebRTC的连接URL。

步骤 2:在HTML中播放 WebRTC 流

WebRTC在浏览器中主要通过 <video> 元素和 RTCPeerConnection API 来播放,使用现成的库可以大大简化代码。

完整代码示例 (index-webrtc.html):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">WebRTC 监控视频播放器</title>
    <!-- 引 adapter-latest.js,它包含了所有浏览器前缀的兼容性代码 -->
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        .video-container {
            width: 80%;
            max-width: 800px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
            border-radius: 8px;
            overflow: hidden;
        }
        video {
            width: 100%;
            display: block;
            background-color: #000;
        }
        .info {
            padding: 10px;
            background-color: #333;
            color: white;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="video-container">
        <video id="videoPlayer" autoplay playsinline></video>
        <div class="info">
            <p>WebRTC 实时监控画面</p>
        </div>
    </div>
    <script>
        const video = document.getElementById('videoPlayer');
        // 将你的WebRTC服务器提供的URL替换到这里
        // 这个URL通常以 "wss://" 或 "ws://" 开头
        const webrtcUrl = 'wss://your-webrtc-server.com/path';
        const pc = new RTCPeerConnection({
            iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] // 使用公共STUN服务器
        });
        pc.ontrack = function(event) {
            if (event.track.kind === 'video') {
                video.srcObject = event.streams[0];
            }
        };
        // 创建一个DataChannel用于信令(如果服务器需要)
        // const dc = pc.createDataChannel('chat');
        // dc.onopen = () => console.log('Data channel is opened');
        // dc.onmessage = (event) => console.log('Message:', event.data);
        // 连接WebSocket到信令服务器
        const socket = new WebSocket(webrtcUrl);
        socket.onopen = () => {
            console.log('WebSocket connected to signaling server.');
            // 如果服务器需要先发送一个'join'消息,在这里发送
            // socket.send(JSON.stringify({ type: 'join', room: 'room1' }));
        };
        socket.onmessage = async (event) => {
            const message = JSON.parse(event.data);
            console.log('Received message:', message);
            if (message.type === 'offer') {
                await pc.setRemoteDescription(new RTCSessionDescription(message.offer));
                const answer = await pc.createAnswer();
                await pc.setLocalDescription(answer);
                socket.send(JSON.stringify({ type: 'answer', answer: pc.localDescription }));
            } else if (message.type === 'candidate') {
                try {
                    await pc.addIceCandidate(new RTCIceCandidate(message.candidate));
                } catch (e) {
                    console.error('Error adding received ice candidate', e);
                }
            }
        };
        // 将本地的ICE Candidate发送给服务器
        pc.onicecandidate = (event) => {
            if (event.candidate) {
                socket.send(JSON.stringify({ type: 'candidate', candidate: event.candidate }));
            }
        };
        // 连接错误处理
        socket.onerror = (error) => {
            console.error('WebSocket Error:', error);
        };
        socket.onclose = () => {
            console.log('WebSocket connection closed.');
        };
    </script>
</body>
</html>

注意:WebRTC的信令过程比较复杂,上面的代码是一个简化的示例,实际项目中,信令服务器(通常用Node.js + Socket.io实现)需要处理offeranswerice-candidate的交换过程,很多商业WebRTC网关会封装掉这些复杂性,提供一个简单的URL或SDK。


总结与对比

特性 HLS.js 方案 WebRTC 方案
延迟 较高 (3-10秒) 极低 (0.5-1秒)
兼容性 非常好 (所有现代浏览器) 良好 (Safari支持最好,Chrome/Firefox需注意)
实现复杂度 简单 (仅需一个转码服务器,播放端代码少) 复杂 (需要专门的WebRTC网关和信令服务器)
适用场景 大多数监控、点播、直播场景 对实时性要求高的场景,如视频通话、远程控制、实时安防
核心依赖 FFmpeg (转码) + HLS.js (播放) WebRTC网关 + 原生API或库

给你的建议

  • 如果你是新手或项目对延迟不敏感:强烈推荐 方案一 (HLS.js),它是目前监控视频网页化最成熟、最稳定的解决方案,社区支持也最好。
  • 如果你是专业人士,项目对实时性有严苛要求:可以考虑 方案二 (WebRTC),虽然搭建复杂,但能带来无与伦比的低延迟体验。

在实际部署时,请务必将 your_rtsp_urlhttp://your-server.com/path/to/output/stream.m3u8wss://your-webrtc-server.com/path 等占位符替换为你自己的实际地址。