Developed by Ravi Dudhagra (@rdudhagra)
The new Raspberry Pi HQ Camera promised super-high-quality images and video from the Raspberry Pi; however, most tutorials and projects used slow, outdated protocols like MJPG, barely maxing out at 720p and maybe 15fps if lucky.
Recently, I stumbled upon a repo called raspilive, which uses a modern streaming protocol called HLS. HLS works by streamings chunks of the video at a time, which are stiched together by the player/client. This results in a high-quality stream that, while suffering from large latency, is much more reliable...perfect for a wildlife camera.
FishCam will stream the video feed from an attached camera to a website hosted on the Pi (works on desktop and mobile). Authentication will prevent unauthorized users from accessing the feed.
-
You will need:
- Raspberry Pi 4B or newer
- Adequate power supply
- (optional) 5V 40mm CPU fan, heatsink
- SD Card (>8GB)
- Raspberry Pi HQ Camera and compatible lens
-
(optional) Download, 3D-print, and assemble the camera case
- Case: https://a360.co/3cvIJva (modified from Adafruit's design to include mounting for a CPU fan and extra brackets for strength)
- Assembly Guide: https://learn.adafruit.com/raspberry-pi-hq-camera-case/assembly
-
Flash the Raspberry Pi with the latest build of Raspberry Pi OS, set up headless if desired
-
Connect camera to Pi, enable camera in
raspi-config
-
(optional) Change the hostname to something friendlier (mine is
fishcam
) -
(optional) If you chose to use a 40mm cpu fan, you can either:
- Connect the fan directly to the 5V and GND terminals of the Pi
- Use a transistor to drive the fan and connect the gate to some GPIO pin, then download FanGPIO to control the fan speed based on CPU temperature
-
Download the raspilive repo
- You can download the pre-built binary, but I found that I needed to adjust the camera settings to get the best quality
- After downloading, you can adjust those settings by editing the
args
variable ininternal/raspivid/raspivid.go
- Here's mine:
args := []string{ "-o", "-", "-t", "0", "-b", "20000000", "--ISO", "250", "--sharpness", "6", "--contrast", "-7", "--brightness", "50", "--saturation", "-7", "--imxfx", "denoise", "--drc", "high", "--nopreview", "--level", "4.2", "--irefresh", "both", "--timeout", "0", "--profile", "baseline", }
- We will also disable their file server, as we will be using nginx...comment out that part of the code in
cmd/raspilive/hls.go
:
. . . osStopper(stop) // // Serve files generated by the video stream // go func() { // err := srv.ListenAndServe() // if errors.Is(err, server.ErrInvalidDirectory) { // log.Fatal().Msg("Directory does not exist") // } // if err != nil { // log.Debug().Err(err).Msg("Encountered an error serving video") // log.Fatal().Msg("Encountered an error serving video") // } // stop <- struct{}{} // }() // Stream video go func() { if err := muxHls(raspiStream, &muxer); . . .
- Build raspilive per their instructions, note the path of the resulting executable
-
Create a RAM disk at
/var/ram_tmp
by following the instructions here, be sure to modify the directory used in the instructions to match above, and make the disk at least 100MB in size.- A RAM disk is highly recommended and will reduce load on the SD card, as the temporary video files will be stored in memory instead of on the disk itself.
-
Create a file called
fishcam.bash
, add the following:#!/bin/bash rm -f /var/ram_tmp/* (/home/pi/raspilive/raspilive/raspilive hls --width 1920 --height 1080 --fps 30 --port 3000 --directory /var/ram_tmp --segment-time 5 --playlist-size 3 2>&1 &> /home/pi/raspilive/raspilive.log)
- Be sure to modify the above command to match the path to the
raspilive
code and executable - Set the file's permissions to executable with
chmod +x /path/to/fishcam.bash
- Be sure to modify the above command to match the path to the
-
Clone this repo to the Pi. Note the directory that it's cloned to...
-
Now we will set up NGINX. First, install it with
sudo apt-get install nginx
. Then, replace the contents of/etc/nginx/sites-available/defualt
with the following:server { listen 80; listen [::]:80; server_name _; # Edit to match the directory that you cloned this repo to root /home/pi/fishcam_website; index index.html; auth_basic "Restricted Content"; auth_basic_user_file /etc/nginx/.htpasswd; location /stream { alias /var/ram_tmp; sendfile on; sendfile_max_chunk 1m; } location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # # Custom headers and headers various browsers *should* be OK with but aren't # add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; # # Tell client that this pre-flight info is valid for 20 days # add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; } } }
- Create a username/password for your website by following the tutorial here(using the
htpasswd
utility is the easiest way) - Restart nginx:
sudo systemctl restart nginx
- Create a username/password for your website by following the tutorial here(using the
-
Now, run
fishcam.bash
and verify that you can see your camera's video feed by going tohttp://[Pi's IP address]
in a web browser on the same network- If you do not see anything, try checking the
raspilive
logs for any errors, also checksudo systemctl status nginx
for any errors there
- If you do not see anything, try checking the
-
If all that is working, let's add this to the
rc.local
file so FishCam runs on boot!- Edit
/etc/rc.local
and add the following beforeexit 0
(changing the path accordingly):/path/to/fishcam.bash
- Edit
-
Try rebooting your Pi...if you see the website/video feed after a minute or two, you're done!
Built upon the work from these sources: