A NixOS module to stream video from the Raspberry Pi 4 Model B. The project is in a draft state and will probably remain there permanently. Only one particular set of hardware is supported; see the Hardware section. A number of problems have been revealed in the course of development. For some of them, workarounds were found and are described in the Problems section. Have fun!
In this setup, the Raspberry Pi board runs NixOS, initially obtained by cross-compiling the installation image. This image is later replaced by natively switching the system to its own configuration, which is not published for security reasons. In this repository, we declare a few components related to the camera service and its dependencies. The entry points of this repository are:
- raspi-camera.nix - NixOS module setting up a simple camera broadcasting service.
- libpisp.nix | libcamera-raspi.nix | pricam-apps.nix - Nix build expressions for main dependencies
Here is how to add the rapi-camera dependency to a third-party Nix system configuration.
Consider a typical flake.nix
. To use raspi-camera
, we add flake input [1], optionally link its
nixpkgs [2] to what other inputs use. Next we add corresponding output argument [3] and finally
include raspi-camera module to the system's configuration [4].
{
inputs = rec {
...
raspi-camera = { # [1]
url = "github:sergei-mironov/nixos-raspi-camera";
inputs.nixpkgs.follows = "nixpkgs"; # [2]
};
};
outputs = { self, ... , raspi-camera } : { # [3]
nixosConfigurations = {
raspi = nixpkgs.lib.nixosSystem rec {
system = "aarch64-linux";
modules = [
...
raspi-camera.nixosModules.raspi-camera # [4]
...
];
};
};
}
}
$ cam -l
[0:01:07.881818018] [957] INFO Camera camera_manager.cpp:316 libcamera v0.3.1
[0:01:07.988647665] [962] INFO RPI vc4.cpp:447 Registered camera /base/soc/i2c0mux/i2c@1/ov5647@36 to Unicam device /dev/media4 and ISP device /dev/media0
Available cameras:
1: 'ov5647' (/base/soc/i2c0mux/i2c@1/ov5647@36)
TODO
This is the preferred way which we encoded into the systemd streaming service.
Raspberry Pi:
rpicam-vid --width 320 --height 240 -t 0 --inline -o - | cvlc stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/stream1}' :demux=h264
Client:
ffplay rtsp://10.0.0.80:8554/stream1 -vf "setpts=N/30" -fflags nobuffer -flags low_delay -framedrop
https://www.raspberrypi.com/documentation/computers/camera_software.html#tcp
Raspberry PI:
$ rpicam-vid -t 0 --inline --listen -o tcp://0.0.0.0:5000
Client:
$ vlc tcp/h264://10.0.0.80:5000
Downsides:
- Only one connection at a time
- Server crashes on disconnect
- https://github.com/raspberrypi/libcamera?tab=readme-ov-file#using-gstreamer-plugin
- Same here https://www.raspberrypi.com/documentation/computers/camera_software.html#libcamerasrc-gstreamer-element
Raspi:
export LIBCAMERA_LOG_LEVELS=*:DEBUG
export GST_PLUGIN_SYSTEM_PATH_1_0=/nix/store/wlrmb5096gyi5xswy79kn6lpaj2b8p19-gstreamer-1.24.3/lib/gstreamer-1.0/
sudo gst-launch-1.0 libcamerasrc ! \
video/x-raw,colorimetry=bt709,format=NV12,width=1280,height=720,framerate=30/1 ! \
queue ! jpegenc ! multipartmux ! \
tcpserversink host=0.0.0.0 port=5000
Client:
TODO
In contrast to NixOS best practices, this repo includes a binary device tree overlay from the Raspberry Pi firmware repo. Where can one find the sources of this overlay?
A workaround in raspi-camera.nix
env = {
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
# Also required in addition to the above fix.
NIX_CFLAGS_COMPILE = "-I${lib.getDev boost}/include -L${lib.getDev boost}/lib";
};
Related reports:
Libcamera docs describe a neat way to run the streaming using Gstreamer alone.
Sadly, we see the TIMEOUT failures, similar to what is described in this raspi forum
thread. Unfortunately, removing arm64bit=1
from the /boot/config.txt
is not an option because NixOS only supports 64bit.
The workaround was to switch to rpicam-apps.