Tuesday, July 8, 2025

How to Stream RTSP IP Cameras and USB Webcams to the Browser with JSMpeg and WebSockets

Commercial NVRs and cloud-based streaming services often impose high latency, heavy resource overhead, or recurring subscriptions. If you have an IP camera (such as a Hikvision IPC-B120 with an RTSP stream) or a USB webcam (such as a Logitech BRIO), you can stream live video directly to any modern browser with low latency and zero plugins.

Architecture Overview

This lightweight pipeline converts video on-demand using three core components:

  • FFmpeg: Pulls the RTSP feed or V4L2 webcam stream, encodes it as an MPEG-TS container with MPEG-1 video (mpeg1video) and MP2 audio, and pipes stdout to websocat.
  • websocat: Listens as an on-demand WebSocket server. When a browser client connects, websocat launches FFmpeg and streams the video chunks over WebSocket. When the browser tab closes, websocat terminates FFmpeg automatically—consuming 0% CPU when idle!
  • JSMpeg: A tiny JavaScript decoder that renders MPEG-1 video frames directly onto an HTML5 <canvas> element in the browser.

1. RTSP Camera Service (/etc/systemd/system/rtsp-ws.service)

Create a systemd service for your Hikvision or ONVIF RTSP camera:

[Unit]
Description=On-demand WebSocket->FFmpeg bridge for JSMpeg RTSP
After=network.target

[Service]
User=pi
Group=pi
ExecStart=/usr/local/bin/websocat \
  --binary \
  --exit-on-eof \
  -s 127.0.0.1:10000 \
  sh-c:'/usr/bin/ffmpeg -hide_banner -loglevel error -rtsp_transport tcp -i "rtsp://user:pass@192.168.1.100:554/Streaming/Channels/101" -f mpegts -codec:v mpeg1video -bf 0 -r 25 pipe:1'
Restart=on-failure

[Install]
WantedBy=multi-user.target

2. USB Webcam Service (/etc/systemd/system/webcam-ws.service)

Create a systemd service for a local V4L2 USB camera (e.g. Logitech BRIO) with ALSA microphone audio:

[Unit]
Description=On-demand WebSocket->FFmpeg bridge for Logitech Brio
After=network.target

[Service]
User=pi
ExecStart=/usr/local/bin/websocat \
  --binary \
  --exit-on-eof \
  -s 127.0.0.1:10001 \
  sh-c:'WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/user/1000 /usr/bin/ffmpeg -hide_banner -loglevel error \
    -f v4l2 -framerate 30 -video_size 1920x1080 -i /dev/video0 \
    -f alsa -ac 2 -ar 44100 -i default \
    -f mpegts -codec:v mpeg1video -bf 0 -r 30 -codec:a mp2 pipe:1'
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and start the services:

sudo systemctl daemon-reload
sudo systemctl enable --now rtsp-ws webcam-ws

3. Frontend HTML5 Player (player.html)

Serve this minimalist HTML5 page with JSMpeg to view the stream from any desktop or mobile browser:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Live Camera Stream (JSMpeg)</title>
  <style>
    html, body {
      margin: 0; padding: 0;
      width: 100vw; height: 100vh;
      background: #000;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .player-container {
      width: 90vw;
      max-width: 1280px;
      max-height: 90vh;
    }
    .player-container canvas {
      width: 100%;
      height: auto;
      display: block;
    }
  </style>
</head>
<body>
  <div class="player-container">
    <canvas id="videoCanvas"></canvas>
  </div>

  <script src="/jsmpeg.min.js"></script>
  <script>
    const protocol = location.protocol === 'https:' ? 'wss://' : 'ws://';
    const url = protocol + location.host + '/my-ws-prefix';

    new JSMpeg.Player(url, {
      canvas: document.getElementById('videoCanvas'),
      autoplay: true,
      audio: false
    });
  </script>
</body>
</html>

5 comments:

  1. This guide made streaming so simple! I finally got my IP camera working live on my website thanks to the clear steps. Hosting Mastery Hub is a real game-changer for beginners like me!

    ReplyDelete
  2. Mos’s Blog in Technology shares insights, tutorials, and innovations shaping the future of the tech world. With switch free game , readers can explore interactive content that makes learning about technology more engaging and practical.

    ReplyDelete
  3. Fast internet powers modern lifestyles. page

    ReplyDelete
  4. This was an enjoyable and educational read. link

    ReplyDelete

How Google Antigravity Solved the Mysterious NVIDIA Sleep Reboot on My Dell Inspiron 7567 (Ubuntu Linux)

If you run modern Ubuntu or Linux on a Dell Inspiron 15 Gaming (7567) or a similar 7th-gen Intel laptop paired with an NVIDIA GeForce GTX ...