Showing posts with label Video. Show all posts
Showing posts with label Video. Show all posts

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>

Friday, April 18, 2025

How to Compile the Latest wf-recorder from Source on Raspberry Pi 5 (Debian 12 Wayland)

On Debian 12 Bookworm (Raspberry Pi OS), the desktop environment runs natively on Wayland. Consequently, traditional X11 screen capture utilities (like FFmpeg's -f x11grab) no longer work.

The standard tool for recording Wayland sessions is wf-recorder. However, the stock wf-recorder v0.3 package provided in Debian's default repository lacks several modern enhancements, most notably the --overwrite flag. Compiling the latest version from source gives you full feature support, hardware-accelerated encoding, and audio capture.

1. Install Build Dependencies

Install the required C++ compilers, Meson build system, PipeWire, and FFmpeg development headers:

sudo apt-get update
sudo apt-get install -y g++ meson ninja-build libavutil-dev libavcodec-dev     libavformat-dev libswscale-dev libpulse-dev wayland-protocols libpipewire-0.3-dev wget

2. Download, Configure, and Build wf-recorder

mkdir -p ~/src && cd ~/src
wget https://github.com/ammen99/wf-recorder/releases/download/v0.5.0/wf-recorder-0.5.0.tar.xz
tar -xf wf-recorder-0.5.0.tar.xz
cd wf-recorder-0.5.0

# Configure release build with Meson
meson setup build --prefix=/usr --buildtype=release --reconfigure

# Compile with Ninja
ninja -C build

# Install binary to /usr/local/bin
sudo cp build/wf-recorder /usr/local/bin/

3. Recording Desktop Video and Audio

To record your full Wayland desktop screen with system audio output:

wf-recorder --overwrite -a default -f capture.mp4
Flag Breakdown:
  • --overwrite: Automatically overwrites existing destination files without prompting.
  • -a default: Captures audio from the default PulseAudio / PipeWire monitor source.
  • -f capture.mp4: Output file path. Stop recording at any time by pressing Ctrl + C.

Sunday, December 30, 2018

Fixing WebM Audio/Video Desync and Import Issues in FFmpeg, Shotcut, and OpenShot

Screen recordings saved in the WebM format (commonly exported by browser extensions like Nimbus Screenshot, Loom, or Screencastify) often use variable frame rates (VFR) and non-standard Opus/Vorbis audio packet chunking. When importing these files into open-source video editors like Shotcut, OpenShot, or processing them directly with FFmpeg, users frequently experience severe audio desynchronization or corrupted frame rendering.

Root Cause: Variable Frame Rate (VFR) container timing drift in libavformat demuxers.

The FFmpeg Solution: Transcode to Constant Frame Rate (CFR) MP4

Rather than relying on proprietary editors, use FFmpeg to normalize the video timeline to a fixed 30 or 60 fps stream with synchronized AAC audio:

ffmpeg -i input_recording.webm   -vsync cfr -r 30   -c:v libx264 -preset slow -crf 20   -c:a aac -b:a 192k -ar 48000   output_fixed.mp4

The resulting MP4 file maintains crystal-clear audio quality and imports into Shotcut, OpenShot, or Premiere Pro with flawless audio-video synchronization.

Wednesday, July 31, 2013

How to Install mod_flvx and mod_h264_streaming on cPanel Apache 2

Serving progressive download video files (such as MP4 and FLV) with seeking capabilities directly from Apache on a cPanel/WHM server requires compiling custom Apache modules: mod_flvx for FLV streaming and mod_h264_streaming for pseudo-streaming H.264/MP4 files.

Environment: cPanel / WHM • EasyApache • Apache 2.2 / 2.4 • H.264 / FLV Streaming

1. Persistent Hook Script

To ensure modules are compiled and reinstalled automatically whenever cPanel runs EasyApache, add the build commands to /scripts/after_apache_make_install:

#!/bin/bash
cd /usr/local/src

# Compile mod_flvx
wget http://people.apache.org/~pquerna/modules/mod_flvx.c
/usr/local/apache/bin/apxs -i -c mod_flvx.c

# Compile mod_h264_streaming
wget http://h264.code-shop.com/download/apache_mod_h264_streaming-2.2.7.tar.gz
tar -zxvf apache_mod_h264_streaming-2.2.7.tar.gz
cd mod_h264_streaming-2.2.7
./configure --with-apxs='/usr/local/apache/bin/apxs'
make && make install

# Update cPanel Apache configuration distiller
/usr/local/cpanel/bin/apache_conf_distiller --update

Ensure the hook script is executable:

chmod +x /scripts/after_apache_make_install

2. Apache Global Configuration

Add the module declarations and file extension handlers to /usr/local/apache/conf/includes/pre_virtualhost_global.conf:

LoadModule h264_streaming_module modules/mod_h264_streaming.so
<IfModule mod_h264_streaming.c>
    AddHandler h264-streaming.extensions .mp4
</IfModule>

LoadModule flvx_module modules/mod_flvx.so
<IfModule mod_flvx.c>
    AddHandler flv-stream .flv
</IfModule>

3. Rebuild with EasyApache

Execute EasyApache through WHM or the command line to finalize the build. Once complete, video seeking will work seamlessly over HTTP.

Tuesday, April 16, 2013

How to Compile the Latest FFmpeg with x264 and libvpx on CentOS 6

Compiling FFmpeg with high-performance H.264 (libx264) and VP8/VP9 (libvpx) encoding support on CentOS 6 often encounters dependency version collisions and compilation errors if older library packages remain installed on the host.

Environment: CentOS 6.x • FFmpeg • x264 • libvpx • faac

1. Removing Conflicting RPM Packages

Before compiling from source, remove older distribution codec libraries to prevent undefined reference linker errors like libx264.c: undefined reference to 'x264_encoder_open_130':

yum remove libvpx libogg libvorbis libtheora libx264 x264 x264-devel x264-libs ffmpeg -y

2. Patching and Compiling faac 1.28

If building the faac AAC encoder, a syntax error occurs in mpeg4ip.h: error: new declaration 'char* strcasestr(const char*, const char*)'. Remove line 126 from ./common/mp4v2/mpeg4ip.h before building:

sed -i '/strcasestr/d' common/mp4v2/mpeg4ip.h
./configure && make && make install

3. Compiling x264 and libvpx

# Build x264
cd x264
./configure --enable-static --enable-shared
make && make install

# Build libvpx
git clone https://chromium.googlesource.com/webm/libvpx
cd libvpx
./configure
make && make install
ldconfig

Once libraries are installed into /usr/local, configure FFmpeg with --enable-gpl --enable-libx264 --enable-libvpx for a fully modern encoding stack.

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 ...