A suite of microservices that provide a highly scaleable, reliable birdfeeder livestream
  • Go 68.2%
  • Python 7.3%
  • Go Template 6.1%
  • CSS 6.1%
  • JavaScript 3.3%
  • Other 9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-26 21:16:20 +00:00
bin Initial project implementation 2026-04-23 18:29:39 -04:00
cmd Adapt to generic git server url 2026-09-26 17:09:59 -04:00
docs Update README with diagram and more details 2026-05-09 13:24:11 -04:00
helm Remove proxy code as it's no longer needed 2026-08-01 12:50:07 -04:00
pkg Adapt to generic git server url 2026-09-26 17:09:59 -04:00
.containerignore Add a .containerignore 2026-05-30 11:41:08 -04:00
.gitignore Add jwt-factory helper to generate new signed JWTs 2026-07-15 18:15:54 -04:00
build.sh Build multiarch images 2026-08-14 18:40:11 -04:00
capture.py Clean up capture.py and use a sinusoidal function 2026-09-20 07:26:43 -04:00
Dockerfile Only copy in required source when building 2026-09-12 19:53:29 -04:00
gen_proto_files.sh Reformat project to handle better docker caching 2026-08-15 19:17:38 -04:00
go.mod Adapt to generic git server url 2026-09-26 17:09:59 -04:00
go.sum Adapt to generic git server url 2026-09-26 17:09:59 -04:00
Makefile Adapt to generic git server url 2026-09-26 17:09:59 -04:00
README.md Add streams to .gitignore and update README 2026-05-30 11:55:19 -04:00
run_tests.sh Add a few unitests 2026-05-09 15:24:30 -04:00

Birb Cam

The Birb Cam project contains four microservices that work together in tandem to create a livestream of my birdfeeder using a raspberry pi with a camera, plus a kubernetes cluster to host process that require heavier processing.

Birb Cam Diagram

Capturer

This component is just a python script: capture.py. It's designed to run directly on a raspberry pi with a camera connected. It just captures the footage and feeds it directly into ffmpeg to convert it into an hls stream. It is scheduled to start the stream at sunrise and stop the stream at sundown in approximation with data collected in Charlotte, NC in 2026. If capturer starts after sunrise, it will calculate the time until sundown and stream from now until then.

Streamer

The streamer is a standalone compiled go binary that also runs on the raspberry pi and services the hls stream files. The goal of the streamer is to take the load off of the python capturer and serve the files to a more powerful suite of servers.

Biffer - The Bird Buffer

Biffer runs as a singleton in a kubernetes cluster. It's a rest server that acts as a buffer for the hls stream. This way, multiple requests made be made for the stream content, but the raspberry pi does not have to handle them. Instead Biffer talks to the raspberry pi and stages the file contents in memory to allow quick serving to the frontend component.

Frontend

The frontend component serves the html page that displays the stream as well as acts as a proxy to fetch stream files directly from Biffer. Frontend is designed to be horizontally scalable with caching to keep minimal traffic to biffer and support serving to more users simultaneously.

Development

Development is naturally difficult without a raspberry pi and camera, however, using microservices allows us to test each component separately or altogether. This is done through the usage of command line flags when executing a component.

Testing Capturer

To test the capturer, install Raspbian OS on a raspberry 4 or newer with a pi camera attached.

To use the capturer.py script, install the following dependencies:

apt install --no-install-recommends python3-picamera2 ffmpeg

Then execute the script with python directly. Streams will be automatically output to the same directory as the script is running in.

Testing Biffer

Biffer is a prerequisite for the other components so it's important to have biffer running locally first. There's helpful make targets for each of these binaries based on name. So you can build and run biffer with:

make run-biffer

You can also build and run it with go directly:

go run cmd/biffer/main.go --tls=false

Testing Streamer

Streamer is intended to run on the raspberry pi and point to the output directory of the capturer. You can either test streamer on the raspberry pi or locally by following these steps.

Testing on the Pi

Use a containerization platform like podman to build and push the streamer image. In both cases, streamer attempts to reach out to biffer to publish files so a biffer instance is required to test streamer.

podman build -t <some-docker-repo>/birb-cam/streamer:<unique tag>
podman push <some-docker-repo>/birb-cam/streamer:<unique tag>

Then run the image on the raspberry pi using any preferred container runtime. The execution flags instruct startup behavior. For example:

podman run -it -v <stream-output-dir>:/streams \
    <some-docker-repo>/birb-cam/streamer:<unique tag> \
    --tls=false --stream-dir /streams

Testing Locally

Create or import your own stream files to a designated stream directory. Then use go to run the main entrypoint directly. For example:

go run cmd/streamer/main.go --tls=false \
    --stream-dir ./streams --biffer-url localhost:6767

Testing Frontend

Frontend, like biffer, runs locally with go. It also requires an instance of biffer to reach out to. For example:

make run-frontend

Or you can build and run it using go directly.

go run cmd/frontend/main.go --tls=false \
    --biffer-url localhost:6767 \
    --stream-url localhost:8080

Running Unit Tests

There's a suite of unittests that require no external dependencies to run. There's a helper script called run_tests.sh that will generate a coverage report to /tmp/birb-cam/ for review. You can open /tmp/birb-cam/result.html to see a full report of what lines are covered and what are not.