FullHD Livestream on 64-bit Raspberry Pi Zero 2W Bookworm The Raspberry Pi Zero 2W is a compact yet powerful solution for various IoT and streaming projects. In this guide, we demonstrate how to optimize a
FullHD Livestream on 64-bit Raspberry Pi Zero 2W Bookworm
The Raspberry Pi Zero 2W is a compact yet powerful solution for various IoT and streaming projects. In this guide, we demonstrate how to optimize a FullHD streaming setup using libcamera to run stably on an RTMP server. By applying targeted optimizations such as overclocking, zram swap, and system adjustments, performance can be significantly improved. Additionally, we address challenges with USB audio and sporadic ALSA buffer XRUNs.
1. Overview: How Does the System Work?
The system consists of several components:
Raspberry Pi with Camera as a Streaming Client
- Capturing video (camera) and audio (microphone)
- Encoding in H.264 (video) and AAC (audio)
- Streaming via RTMP (Real-Time Messaging Protocol) to the server
NGINX RTMP Server as a Central Streaming Hub
- Receives streams from one or multiple Raspberry Pis
- Provides streams via RTMP, HLS, or WebRTC for further processing
Motion (Home Surveillance Software)
- Analyzes RTMP streams in real-time
- Detects motion and saves events as images/videos
- Sends notifications upon movement detection
2. Installing the RTMP Server with NGINX
The NGINX RTMP server works best on a powerful machine within the network (e.g., Raspberry Pi 4, Mini PC, or NAS).
Step 1: Install NGINX with RTMP Module
On the server, execute:
sudo apt update
sudo apt install -y nginx libnginx-mod-rtmp
Step 2: Configure the RTMP Server
The NGINX configuration file is located at:
/etc/nginx/nginx.conf
Replace or extend it with the following RTMP settings:
rtmp {
server {
listen 1935; # Default RTMP port
application live {
live on;
record off;
push rtmp://127.0.0.1:1935/motion; # Forward stream to Motion
}
application motion {
live on;
record off;
}
}
}
Restart NGINX:
sudo systemctl restart nginx
Your RTMP server is now running and ready to receive streams from Raspberry Pis.
3. Setting up the Raspberry Pi as an RTMP Streaming Client
3.1 Required Hardware
- Raspberry Pi Zero 2W
- Raspberry Pi Camera Module 3 (with HDR support)
- MicroSD card (at least 32 GB, preferably high-speed or high-endurance)
- USB power adapter (at least 5V/2A)
- Cooling (optional but recommended)
- Network connection (Wi-Fi or Ethernet adapter for more stable connections)
3.2 Required Software
- Raspberry Pi OS (Lite recommended to save resources)
- libcamera (for modern camera control)
- ffmpeg & rpicam-vid (for processing and streaming)
- zram (to reduce SD card wear and improve memory management)
4. Installing Required Packages
4.1 Update System
Before installation, update the system:
sudo apt update && sudo apt upgrade -y
4.2 Install libcamera and ffmpeg
sudo apt install -y rpicam-apps ffmpeg
4.3 Switch to PipeWire for Better Audio Latency
PipeWire is a modern alternative to PulseAudio, improving latency:
sudo apt install -y pipewire pipewire-pulse pipewire-audio-client-libraries
Enable PipeWire:
systemctl --user enable pipewire pipewire-pulse
systemctl --user start pipewire pipewire-pulse
Verify PipeWire is running:
pactl info | grep "Server Name"
If the output shows “PipeWire,” the switch was successful.
5. System Optimization for Stable Streaming
5.1 Disable Unnecessary Services
Since the Zero 2W has limited RAM, disable unused services:
sudo systemctl disable --now lightdm
sudo systemctl disable --now hciuart
sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now triggerhappy
5.2 Optimized Memory Management with ZRAM
ZRAM creates compressed swap space in RAM, improving performance and reducing SD card wear.
Installing ZRAM Swap:
sudo apt update
sudo apt install git -y
git clone https://github.com/foundObjects/zram-swap
cd zram-swap/
sudo ./install.sh
Check ZRAM status:
zramctl
free -h
5.3 Optimizing the Filesystem
Modify /etc/fstab
to reduce write operations:
PARTUUID=82df2a3b-02 / ext4 defaults,noatime,commit=600 0 1
6. Overclocking for Better Performance
Edit /boot/config.txt
and add:
arm_boost=1
arm_freq=1200
core_freq=400
over_voltage=3
gpu_freq=500
sdram_freq=400
temp_limit=80
gpu_mem=76
A cooling solution is recommended, though my temperatures rarely exceed 50°C.
7. Streaming with libcamera and rpicam-vid
Create the following script /usr/bin/streamfull
for FullHD streaming with low latency:
#!/bin/bash
nice -16 rpicam-vid -t 0 --width 1920 --height 1080 --nopreview --low-latency 1 --flush --buffer-count 2 --hdr sensor --metadata - \
--profile high --level 4.2 --codec libav --libav-audio --audio-source alsa --audio-device hw:0,0 --audio-channels 1 --audio-codec aac -g 16 \
--audio-samplerate 48000 --audio-bitrate 64000 --libav-video-codec h264_v4l2m2m --libav-video-codec-opts "num_output_buffers=2;num_capture_buffers=8;strict=-2" \
--libav-format flv -n --framerate 30 -b 4800000 --autofocus-mode manual --lens-position 0.75 --av-sync 0 \
--denoise cdn_hq --autofocus-window 0.25,0.25,0.5,0.5 --inline 1 -o "rtmp://<NGINX_SERVER_IP>/zero/test"
7.1 Key Parameter Explanations
--low-latency 1
: Reduces latency for real-time streaming.--buffer-count 2
: Minimizes buffer lag.--hdr sensor
: Uses the HDR mode of Camera Module 3.--autofocus-mode manual
: Fixes focus at 0.75 for sharper images.--av-sync 0
: Minimizes audio-video drift (adjust as needed).--denoise cdn_hq
: Enhances image quality with hardware denoising.
This setup enables stable and high-quality FullHD livestreaming on a Raspberry Pi Zero 2W!
Here the detailed explanations:
General Settings
#!/bin/bash
→ Defines the script language as Bash.
nice -16
→ Sets the process priority to -16, giving it a higher CPU priority.
Video Recording with rpicam-vid
rpicam-vid
→ Starts the Libcamera video tool for the Raspberry Pi.
-t 0
→ Unlimited recording time (0 means “infinite”).
–width 1920 –height 1080
→ Sets the video resolution to 1920×1080 (Full HD).
–nopreview
→ Disables the preview on the display to save resources.
–low-latency 1
→ Enables a low-latency streaming mode for minimal delay.
–flush
→ Forces immediate sending of video data without waiting for full buffers.
–buffer-count 2
→ Sets the number of video buffers to 2 to minimize delays.
–hdr sensor
→ Activates the HDR mode of the camera sensor for better dynamic range.
–metadata –
→ Sends metadata (such as exposure time or ISO) to the standard output.
Video Encoding & Streaming
–profile high –level 4.2
→ H.264 encoding profile:
High: Best quality
Level 4.2: Supports Full HD @ 30 fps
–codec libav
→ Uses Libav as the video codec framework.
–libav-video-codec h264_v4l2m2m
→ Uses the H.264 hardware encoder (v4l2m2m) to offload the CPU.
–libav-video-codec-opts “num_output_buffers=2;num_capture_buffers=8;strict=-2”
→ Encoder fine-tuning:
num_output_buffers=2 → Minimal waiting time
num_capture_buffers=8 → More memory for decoding
strict=-2 → Allows non-standard parameters
–libav-format flv
→ Saves/streams the video in FLV format, optimized for RTMP streaming.
-n
→ No standard output, prevents unnecessary outputs.
–framerate 30
→ Sets the frame rate to 30 fps.
-b 4800000
→ Bitrate 4.8 Mbps, ensures high quality.
Audio Settings
–libav-audio
→ Enables audio recording via Libav.
–audio-source alsa
→ Uses ALSA as the audio source.
–audio-device hw:0,0
→ Sets the audio device to ALSA device hw:0,0.
–audio-channels 1
→ Mono audio to save bandwidth.
–audio-codec aac
→ Encodes the audio stream with AAC.
–audio-samplerate 48000
→ Sets the sample rate to 48 kHz (broadcast standard).
–audio-bitrate 64000
→ Sets the audio bitrate to 64 kbps (a compromise between quality and bandwidth).
Autofocus & Image Quality
–autofocus-mode manual
→ Disables autofocus, instead setting a fixed focus.
–lens-position 0.75
→ Sets the camera focus to 75% of the maximum distance.
–autofocus-window 0.25,0.25,0.5,0.5
→ Defines an autofocus area in the middle of the image.
–denoise cdn_hq
→ Enables high-quality denoising (cdn_hq) for clearer images.
–inline 1
→ All frames include SPS/PPS headers, important for smooth streaming.
Streaming Output
Stream name: zero/test.
-o “rtmp://192.168.178.25/zero/test”
→ Streaming target:
Sends the video to the local RTMP server at 192.168.178.25.
5. USB Audio Issues with ALSA and XRuns
A known issue is that USB audio on the Raspberry Pi causes sporadic buffer XRuns. These errors may cause short dropouts that are often not noticeable in the final stream. The following measures can help:
bashKopierenBearbeitenecho "defaults.pcm.dmix.rate 48000" >> /etc/asound.conf
echo "defaults.pcm.dmix.period_time 100000" >> /etc/asound.conf
Additionally, rtprio can be adjusted in /etc/security/limits.conf:
bashKopierenBearbeiten@audio - rtprio 95
@audio - memlock unlimited
This gives the audio driver higher priority.
With these optimizations, a Full HD stream can be surprisingly stable on the Raspberry Pi Zero 2W. Despite the limited hardware resources, the system works reliably and without noticeable lag with the correct configuration.
The same setup works on a Raspberry Pi 4 and Pi 5 even without optimizations to Zram, the file system, and other areas. These are only necessary for the Pi Zero 2W, where the limited 512 MB memory is the bottleneck.
For the ALSA buffer XRuns (overruns and underruns), I will test other microphones in the future, as they may provide more stable and smaller audio packets. So far, these errors are not noticeable in the streams.
If you have any questions or further optimization ideas, leave a comment!
On the Pi Zero 2W, I got rid of these errors in the stream:
[mp4 @ 0x1692c10] Encoder did not produce proper pts, making some up.
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=105, track[105]=233
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=106, track[106]=234
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=107, track[107]=235
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=108, track[108]=236
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=109, track[109]=237
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=110, track[110]=238
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=111, track[111]=239
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=116, track[116]=244
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=117, track[117]=245
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=118, track[118]=246
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=119, track[119]=247
[h264_v4l2m2m @ 0x1692830] Pkt tracking failure: pts=120, track[120]=248
And also the ALSA buffer xrun errors mostly. (but they are not killing the stream in general).