Unfortunately, many blogs/tutorials on the internet will offer a MJPG based solution for streaming the Raspberry Pi4 camera to a browser. This does not scale, as mjpg is not efficient. Offering a h264 stream is a better idea.
We found an outdated project that does this, but it had to be forked in order to make it support newer version of the picamera library.
For our use-case, this project allows us to browse to an URL and remotely observe 3D printing projects, in 1080p 30fps, (near)realtime.
We have Raspbian bookworm:
Linux raspberrypi 6.1.0-rpi7-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.63-1+rpt1 (2023-11-24) aarch64 GNU/Linux
Install dependencies, clone repository:
sudo apt install -y rpicam-apps-lite python3-virtualenv python3-tornado python3-picamera2 libraspberrypi0 libraspberrypi-dev
cd ~/
git clone https://github.com/kroketio/pi-h264-to-browser.git
cd pi-h264-to-browser
There is one thing you need to change before starting the application, that is changing the websocket URL.
In src/main.py
there is:
wsURL = "ws://my_ip/ws/"
Replace it with the IP and port of your device. For example:
wsURL = "ws://192.168.0.7:8000/ws/"
If you proxy-forward behind a webbserver that does TLS, use wss://
instead.
Tip regarding bandwidth: Tweak qp
, e.g a value of 26
generates 5.3MBit/s of video data at 1080p, while 19
generates 30MBit/s. For raspberry pi cameras you can get away with lower compression because the cameras themselves are not super high quality. 26
is fine for our use-case.
We can use systemd to create a service so that this application runs automatically on system startup.
Create the following file: /etc/systemd/system/cam.service
Replace /home/user/
with the real path.
[Unit]
Description=pi4 cam web
[Service]
ExecStart=/usr/bin/python3 /home/user/pi-h264-to-browser/src/server.py
[Install]
WantedBy=multi-user.target
Reload systemd to load this new service file:
systemctl daemon-reload
Enable on system boot:
systemctl enable cam
Start the service:
systemctl start cam
The service should now be running on port 8000
. You can browse to it with your webbrowser.
You might need to allow port 8000 in the firewall:
ufw allow 8000
To view application logs:
journalctl -xefu cam
You can also run the application manually:
/usr/bin/python3 /home/user/pi-h264-to-browser/src/server.py
Verify there is a camera present by using libcamera-hello
:
libcamera-hello
[1:42:12.046456609] [1443] INFO Camera camera_manager.cpp:284 libcamera v0.1.0+118-563cd78e
[1:42:12.088202181] [1446] WARN RPiSdn sdn.cpp:39 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[1:42:12.091335080] [1446] INFO RPI vc4.cpp:444 Registered camera /base/soc/i2c0mux/i2c@1/imx477@1a to Unicam device /dev/media3 and ISP device /dev/media0
[1:42:12.091437949] [1446] INFO RPI pipeline_base.cpp:1142 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'
Preview window unavailable
Mode selection for 2028:1520:12:P
SRGGB10_CSI2P,1332x990/0 - Score: 3456.22
SRGGB12_CSI2P,2028x1080/0 - Score: 1083.84
SRGGB12_CSI2P,2028x1520/0 - Score: 0
SRGGB12_CSI2P,4056x3040/0 - Score: 887
Stream configuration adjusted
[1:42:12.093609472] [1443] INFO Camera camera.cpp:1183 configuring streams: (0) 2028x1520-YUV420 (1) 2028x1520-SBGGR12_CSI2P
[1:42:12.094110391] [1446] INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx477@1a - Selected sensor format: 2028x1520-SBGGR12_1X12 - Selected unicam format: 2028x1520-pBCC