Growcast: Replacing OBS with a Single Container for 24/7 Grow Streaming

How I replaced a Guacamole + OBS Studio stack with a single Go container that streams my grow tent 24/7 using FFmpeg, GPU acceleration, and live sensor overlays.

Live Growcast stream showing grow tent camera feed with temperature, humidity, and plant stats overlay
The live 24/7 grow stream powered by Growcast

For a while now I've been running a 24/7 live stream of my grow tent. What started as a simple "point a camera at some plants" setup gradually turned into a multi-layered mess of services — and eventually, a custom Go application that replaced all of it. That project is Growcast, and it's now public on GitHub.

The Old Setup

The original streaming rig was... a lot. I had a Guacamole server providing remote access to an Ubuntu desktop that was running OBS Studio. OBS handled compositing the camera feeds, and I used plugins for scene rotation to cycle through different views automatically. It worked, sort of, but it required constant babysitting. OBS would crash, the scene rotation plugin would get confused, the remote desktop session would hang — there was always something that needed manual intervention to keep the stream alive.

For a "set it and forget it" 24/7 stream, it was anything but. I wanted something simpler: a single container that could pull in my RTSP camera feeds, composite them with overlays, pipe in background music, and push a continuous stream to my Owncast server — all without a desktop environment, without OBS, and ideally without me needing to touch it.

What Growcast Does

Growcast is a Go application that orchestrates FFmpeg to produce a continuous livestream from multiple camera sources. The key trick is using FFmpeg's streamselect filter controlled via ZMQ — this lets Growcast switch between scenes (different camera layouts) without ever dropping or reconnecting the output stream. The stream just keeps rolling, and the view changes seamlessly underneath.

Live Growcast stream showing grow tent camera feed with temperature, humidity, and plant stats overlay
The live stream running on grow.dwot.io — camera feed with live stats and now-playing info

It supports several layout modes: a single full-frame camera, picture-in-picture with a small inset, and 2×2 grids for up to four cameras. Scenes rotate automatically on a configurable timer, so the stream cycles through different views of the tent throughout the day without any intervention.

Live Stats from Isley

One of the features I'm most happy with is the overlay system. Growcast polls the API from Isley, my grow tracking project, and renders live sensor data directly onto the stream. Temperature, humidity, VPD — it's all there in real time. It also rotates through plant information, showing details about what's currently growing along with soil moisture readings when available.

There's also audio integration. Growcast pulls an HTTP audio stream from my Azuracast radio station and mixes it into the stream as background music, complete with now-playing metadata displayed on screen. It's a nice touch that makes the stream feel more like something you'd actually want to leave on in the background.

GPU Acceleration and Docker

One of the original goals was to leverage my GPU to keep the CPU load manageable. Growcast supports NVIDIA hardware acceleration via NVENC for encoding and CUVID for decoding, and the whole thing ships as a Docker container with both CPU and GPU variants. The GPU image uses the nvidia-container-toolkit so it can access the host GPU.

Docker container details for growcast-gpu showing CPU usage at 143.8%, memory at 1.3%, and 130GB network received
The growcast-gpu container chugging along — low memory footprint, heavy network I/O from the continuous stream

The container setup is straightforward — a YAML config file defines your cameras, scenes, outputs, and overlay settings, and you just bring it up with docker compose. It also has a REST API for manual control: switching scenes, checking status, restarting camera connections. Handy when you want to force a specific view without waiting for the rotation.

Reliability: A Work in Progress

I'll be upfront — it's not perfect yet. RTSP camera feeds are inherently finicky, and hiccups happen. Sometimes a camera connection drops and things hang momentarily. I'm not entirely convinced there isn't some network gremlin on my LAN causing some of the instability, but I haven't tracked it down yet.

That said, the recovery story is solid. When something does go wrong, Growcast detects it and bounces back quickly. It has background health checks on camera connections and the stream recovers without manual intervention. For a project that started as "I just want to stop babysitting OBS," the improvement is massive. I essentially never touch it now — it just runs.

The Result

The live stream runs 24/7 on my self-hosted Owncast instance at grow.dwot.io. It cycles through camera angles, shows live environmental data from the tent, plays music, and recovers from hiccups on its own. All from a single container.

GitHub repository page for dwot/growcast showing project files and structure
Growcast on GitHub — the full source is public under MIT license

Compared to the old Guacamole → Ubuntu Desktop → OBS → Plugins stack, this is night and day. Fewer moving parts, fewer things to break, and when something does break it fixes itself. If you're running cameras and want a lightweight, containerized streaming solution that doesn't need a desktop environment, check it out. It's MIT licensed and the config is pretty well documented in the README.

Next steps are continued reliability improvements — better RTSP reconnection logic, maybe some smarter error handling around the FFmpeg pipeline — and possibly adding more overlay customization options. But for now, it does what I built it to do: stream my grow, hands-off, 24/7.