Skip to content

Latest commit

 

History

History
163 lines (148 loc) · 8.25 KB

README.md

File metadata and controls

163 lines (148 loc) · 8.25 KB

FishCam

A wildlife-streaming camera based on the Raspberry Pi HQ Camera and the HLS streaming protocol

Developed by Ravi Dudhagra (@rdudhagra)

About

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.

Instructions

  1. 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
  2. (optional) Download, 3D-print, and assemble the camera case

  3. Flash the Raspberry Pi with the latest build of Raspberry Pi OS, set up headless if desired

  4. Connect camera to Pi, enable camera in raspi-config

  5. (optional) Change the hostname to something friendlier (mine is fishcam)

  6. (optional) If you chose to use a 40mm cpu fan, you can either:

    1. Connect the fan directly to the 5V and GND terminals of the Pi
    2. 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
  7. 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 in internal/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
  8. 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.
  9. 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
  10. Clone this repo to the Pi. Note the directory that it's cloned to...

  11. 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
  12. Now, run fishcam.bash and verify that you can see your camera's video feed by going to http://[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 check sudo systemctl status nginx for any errors there
  13. 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 before exit 0 (changing the path accordingly):
      /path/to/fishcam.bash
  14. Try rebooting your Pi...if you see the website/video feed after a minute or two, you're done!

Credits

Built upon the work from these sources: