Over the years I’ve accumulated a few Raspberry Pis of different versions, each of which I’ve used for certain things, some of them I’ve retired or upgraded to newer versions. Consequently, I have a few Raspberry Pi 1 and 1B still around, and they’re not doing much aside from collecting dust. I also have an old Raspberry Pi NoIR camera that I haven’t been using much.

Over the years I’ve tried different things, including PIR-triggered recording of the camera feed, sort of to build a device that records what’s happening when the infrared sensor is triggered. While that actually worked just fine, I also wanted to be able to get a steady video stream from the camera that can be observed over the internet, if necessary.

Here’s how I ended up doing that. My setup is

  • Raspberry Pi 1
  • Pi NoIR Camera Rev 1.3
  • Raspbian 11 (bullseye) with Linux kernel 6.1 (it’s a while since I’ve re-imaged the SD card ;-))

Set up the camera

My Pi NoIR camera has certain defaults that I don’t quite like. I use the following setup.sh script to change these defaults to use my preferred values. First I print the current values. In a next step, I update the video bitrate mode, set the video bitrate to 800 kbps and reset the color effects to the default. Here’s where you could turn on things like black-and-white, negative, and so on. Finally, I let v4l2-ctl print the updated settings for confirmation.

The updates are applied to the device, so even if you restart the stream afterwards, these settings will stay in effect until overwritten, or until you reboot.

$ cat ~/setup.sh 
#!/bin/bash

echo 'Current settings:'
v4l2-ctl --list-ctrls

echo
echo 'Updating bit rate ...'
v4l2-ctl -d /dev/video0 --set-ctrl=video_bitrate_mode=1 \
         --set-ctrl=video_bitrate=800000 --set-ctrl=color_effects=0

echo
echo 'Updated settings:'
v4l2-ctl --list-ctrls

Start the video stream

The stream.sh script is used to start the stream with the help of VLC. I use the command-line tool cvlc as you can see below. The script has VLC capture the feed from /dev/video0, which is my Pi NoIR camera. It’s instructed to capture a Full HD feed at 30 frames per second, and use the H.264 video coding. Because I mounted the camera in a way that does not need the ribbon cable to be twisted, I also need to flip the captured image both horizontally and vertically to match what a humand would see.

And last but not least, the --sout '...' argument tells VLC that I’d like the feed to be made available over RTP with RTSP as the session description protocol, using port 8554. The default port for RTSP is 554, so binding to that TCP port typically requires more permissions which I didn’t want to fiddle with for this toy.

$ cat ~/stream.sh 
#!/bin/bash

echo 'Open RTSP streaming server on port 8554 ...'
cvlc v4l2:///dev/video0 --v4l2-width 1920 --v4l2-height 1080 --v4l2-fps 30 \
    --v4l2-chroma h264 --v4l2-vflip 1 --v4l2-hflip 1 \
    --sout '#rtp{sdp=rtsp://:8554}' :no-sout-all :sout-keep :demux=264

Start the stream automatically on reboot

To start the stream automatically after the Rasberry Pi has booted, I rely on cron. Here’s what my crontab looks like:

$ crontab -l
# [... irrelevant stuff ...]
@reboot /home/pi/start-stream.sh

And here’s what that start-stream.sh script looks like:

$ cat ~/start-stream.sh
#!/bin/bash

sleep 15
/home/pi/setup.sh
nohup /home/pi/stream.sh &

The sleep with 15 seconds is, as you would probably expect, a work-around for delays in other dependencies on the system. Perhaps there’s a way to use signals instead, but I didn’t bother to invest a lot of time here, so for now this does the trick.

Watch the stream

Supposedly any software that can show an RTP stream initiated over RTSP can be used to watch the stream. For instance, on Linux I use ffplay as follows:

$ ffplay rtsp://host-address:8554/

If you’re streaming over the internet, do not forget to address the following:

  • Security: With the above instructions, you’ll get a feed that anybody knowing the address (and port) can watch too.
  • Port-forwarding: You’ll probably not have the Raspberry Pi connected to the internet directly, so port-forwarding may be needed. That goes for the RTSP port (tcp/8554 in my setup) as well as the UDP port used for the actual RTP stream. I haven’t found a way to fix the UDP port (I also didn’t care much, TBH) with VLC, so typically it selects a random port. Keep that in mind when setting up port forwarding for UDP.

Conclusion

It’s really quite easy to turn your Raspberry Pi with camera into a video streaming device. The quality is quite decent, and CPU consumption is below 10% for the first streaming client, but grows with additional clients. With my 800 kbps for a 30 fps Full HD stream I get a pretty decent quality: I can easily see the branches and leaves of trees 50 meters away, and I can see fluent motions of people and cars. I think the hardware for this cost less than 100 $ total (many years ago). The benefit is what you make of it ;-)