rtsp-to-web-video-live-streaming

Video source must be h264 encoded for max compatibility. Set the camera to encode h264 at source so transcoding can be avoided later.

Used the HikVision camera model DS-2CD3026G2-IS ip-camera to streaming the video.

Step 1.1 Docker Compose

# Filename: /srv/livevideo.example.com/docker-compose.yaml

name: livevideo-example-com

services:
  rtsp-to-web:
    image: ghcr.io/deepch/rtsptoweb:latest
    container_name: rtsp-to-web.example.com
    restart: always

    volumes:
      - ./config.json:/config/config.json

  livevideo:
    image: nginx:latest
    container_name: livevideo.example.com

    volumes:
      - ./html:/usr/share/nginx/html:ro
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

    labels:
      - com.centurylinklabs.watchtower.enable=true
      - traefik.enable=true
      - traefik.http.routers.livevideo.rule=Host(`livevideo.example.com`)
      - traefik.http.routers.livevideo.tls=true
      - traefik.http.routers.livevideo.tls.certresolver=lets-encrypt

    depends_on:
      - rtsp-to-web

Step 1.2 rstp-to-web configuration

Filename: /srv/livevideo.example.com/config.json

{
  "channel_defaults": {
    "on_demand": true
  },
  "server": {
    "debug": true,
    "http_debug": false,
    "http_demo": true,
    "http_dir": "",
    "http_login": "api-username",
    "http_password": "api-password",
    "http_port": ":8083",
    "https": false,
    "https_auto_tls": false,
    "https_auto_tls_name": "",
    "https_cert": "",
    "https_key": "",
    "https_port": "",
    "ice_credential": "",
    "ice_servers": [],
    "ice_username": "",
    "log_level": "info",
    "rtsp_port": ":5541",
    "token": {
      "backend": "",
      "enable": false
    },
    "webrtc_port_max": 0,
    "webrtc_port_min": 0
  },
  "streams": {
    "mystream": {
      "channels": {
        "0": {
          "name": "camera-1",
          "url": "rtsp://rtsp-username:rtsp-password@host-ip"
        },
        "1": {
          "name": "camera-2",
          "url": "rtsp://rtsp-username:rtsp-password@host-ip"
        }
      },
      "name": "Live Video Stream"
    }
  }
}

Step 1.3 Nginx configuration

# Filename: /etc/nginx/nginx.conf

events {
  worker_connections 1024;
}

http {
    server {
        listen 80;

        include /etc/nginx/mime.types;

        location / {
          root /usr/share/nginx/html;
          index index.html;

          try_files $uri /index.html;
          add_header 'Access-Control-Allow-Origin' '*';
        }

        location /stream/ {
          proxy_pass http://rtsp-to-web:8083;
          proxy_http_version 1.1;

          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

Step 1.4 HLS Low latency player

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>RTSPtoWeb HLS-LL</title>
  </head>
  <body>
    <h1>RTSPtoWeb HLS-LL</h1>
    <div>
        <p></p>
        <video id="hlsll-video" autoplay muted playsinline controls style="width: 100%; height: 100%;"></video>
    </div>
    

    <script>
      document.addEventListener('DOMContentLoaded', function () {
        const videoEl = document.querySelector('#hlsll-video')

        var path = window.location.pathname;
        var parts = path.split('/'); // livevideo.example.com/stream-name/channel/1 4-3
                                     // 0 - stream name
                                     // 1 - channel name
                                     // 2 - channel no

        var url = window.location.protocol + '//' + window.location.hostname;
        var stream_name = parts[parts.length - 3] + '/';
        var channel = parts[parts.length - 2] + '/'; 
        var channel_no = parts[parts.length - 1];

                                     
        // https://livevideo.example.com/stream/{0}/{1}/{2}/hlsll/live/index.m3u8
        var stream_url = url + '/stream/' + stream_name + channel + channel_no + '/hlsll/live/index.m3u8';

        console.log(stream_url);

        if (Hls.isSupported()) {
          const hls = new Hls()
          hls.loadSource(stream_url)
          hls.attachMedia(videoEl)
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
          videoEl.src = hlsllUrl
          videoEl.addEventListener('loadedmetadata', function() {
          videoEl.play();
          });
        }
      })
    </script>

    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>

  </body>
</html>

Play video stream with HLS low latency player: https://livevideo.example.com/mystream/channel/0

References

  1. RTSPtoWeb
  2. RTSPtoWeb API