Under Void *

As any masochistic logical person would do when we learned that our daughter would join us, i thought that we would have the need to spy on monitor her while she rests on the other room. So off i was, buying a raspberry pi 0 with a NoIR camera and a usb microphone! Like you, dear reader, i did my preliminary search and found a multitude of reported setups (most running rasbian) so i thought that this should be a project that would take max .. 3-4 days. Ha! Murphy was already laughing at me, from dimensions beyond. I wanted to go off the beaten path a bit by using Alpine linux (because it still is Linux) and putting the whole thing in a stuffed animal. After all my daughter will have all her future life to experience tech dystopia by herself, no need to accelerate things by having her look at a camera looking back at her.

Here is a parts list i got with links if you decide to go down that road:

Parts

software

Installing alpine on your SD card

partitioning your microSD

You will need an msdos partition label (did not try GPT) and 2 primary partitions, one vfat for /boot and the other ext4.

alpine linux

Download the the current as of feb 2025 3.21.2 armhf tar image mount your microSD in /mnt/flash, and untar it tar -xzpvf alpine-rpi-3.21.2-armhf.tar.gz -C /mnt/flash

Now you can edit the pi boot relevant file /boot/usercfg.txt

cat /boot/usercfg.txt
#camera
dtoverlay=imx219
camera_auto_detect=1

#audio for the microphone
dtparam=audio=on
#usb microphone and usb gadgets
dtoverlay=dwc_otg

#uncomment if you want to enable the serial console
#enable_uart=1

#you can also control how much memory you will give to the gpu via
#gpu_mem=32

If you want to enable the serial console you also need to edit /boot/cmdline.txt and add console=serial0,115200.

headless install over wifi

In case you want to only install via wifi without using the serial over usb as described above you can download the headless overlay from github place it at the root of the boot media. There you can also provide a wpa_supplicant.conf with your wifi ssid and psk, as well as an authorized_keys file with a pubkey to ssh in as the root user.

Then you can run setup-alpine to configure the system.

setting up video and audio

apk add libcamera-tools libcamera-raspberrypi libcamera-v4l will give us the cam package to test by grabbing a screenshot or listing the cameras via cam -l however looking around we see that there are also the libcamera-* apps that can stream video directly to either stdout or a socket and many many more. There is a package providing these but is currently (as of Feb 2025) in testing, so to add them we need to edit /etc/apk/repositories to something like below (if we want to follow the latest release. Otherwise we should stick to the version we have downloaded like 3.21.2)

http://mirrors.gigenet.com/alpinelinux/latest-stable/main
http://mirrors.gigenet.com/alpinelinux/latest-stable/community
@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing

Having done that, we can apk update and apk add rpicam-utils@testing

In order to also operate the usb microphone, we need to setup either alsa or pulseaudio. To do that we add the alsa packages apk add alsa-utils alsaconf and then we add our user to the audio group addgroup $USER audio (and even add the root user to the same group). Then running alsamixer should show us the soundcard and its respective number and we can configure the input levels of the mic. We also add alsa to the runlevel by rc-service alsa start and rc-update add alsa

a note on connections

The raspberry pi zero has 2 usb ports, but only one can also transfer data, the other is solely for charging. so the microphone needs to be plugged to the port that is farther away from the ribbon cable that goes to the camera. This was the source of much confusion during testing.

tuning the camera

Using libcamera-vid or libcamera-still (or cam) we can see that the pictures that we get using the default tuning parameters are a bit overexposed. For our case that we use the imx219 NoIR camera, we can run libcamera-vid with the following options libcamera-vid -t 0 --libav-format h264 --width 640 --height 480 --framerate 15 --profile baseline --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx219_noir.json also you will notice that without specifying a mode , the image appears cropped, or extremely zoomed in. In order to fix that we need to find a mode that is supported from –list-cameras and pass that libcamera-vid. in our case ----mode 1640:1232:10 does the trick.. Finally the –inline parameter adds a SPS/PPS (sequence/picture parameter sets) header on every frame so that the client can properly decode the data as the stream progresses. so we end up with

libcamera-vid -t 0 --inline --codec h264 --mode 1640:1232:10 --framerate 5 --profile baseline --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx219_noir.json -o -

things head south

At this point according to various similar projects you might see people using the libcam-vid application to either stream video directly from it to clients, or have it write to stdout and then pipe to cvlc in order to create an rtsp stream, like this one liner or this forum post. However no such thing ever worked for my case. Also, trying to cram all that functionality of listening for network connections and doing all the possible encodings inside the libcamera programs is…. (i think) very misguided. UNIX is designed around program composition.

go2rtc

go2rtc is a small golang program, that bundles a webapp, and can consume various input streams, and combine them into outuput ones. It can use RTMP, RTSP, ffmpeg, homekit, gopro, webrtc and many more as input. Then it can present these on the webapp, and also run commands that produce new strems for output. It worked wonders for me and was able to compose the two streams (video and audio) into one, and do it within the CPU constrains of the raspberry pi. Below you can find the final config

api:
  listen: ":1984"

ffmpeg:
  bin: "ffmpeg"

log:
  format: "color"
  level: "info"
  output: "stdout"
  time: "UNIXMS"

rtsp:
  listen: ":8554"
  default_query: "video&audio"

srtp:
  listen: ":8443"

webrtc:
  listen: ":8555/tcp"
  ice_servers:
    - urls: [ "stun:stun.l.google.com:19302" ]

streams:
  babycam:
    - "exec:libcamera-vid -t 0 --inline --codec h264 --mode 1640:1232:10 --framerate 5 --profile baseline --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx219_noir.json -o -"
    - "ffmpeg:device?audio=default&channels=1&sample_rate=16000&#audio=aac"

Here are some pictures of how the pi in police dog looks like img1: eye of the monitor img2: operating on the stuffed animal img3: cable management on the dog’s back img4: babymon with laptop

#Linux #RPi #Project