Back to feed

Emergency video

For reasons that made sense at the time, and make slightly less sense now, I built a small emergency video system.

The question behind it was pretty simple: if a connection gets bad enough, how little video can you send before it stops being useful?

The repo is here: github.com/tgergo1/emergency-video.

The core of it is a custom C++ codec hooked up to a live webcam feed. Frames are shrunk to a tiny internal resolution, converted to grayscale, quantized to 4-bit luma, and encoded as periodic keyframes plus sparse interframes. If a block has not changed, it gets skipped, which is nice because bandwidth is a precious resource and so is my patience. If it has changed, it can be sent as coarse 4x4 cells, residuals against the previous reconstructed frame, or full raw 8x8 samples when the block is too messy for anything cheaper.

So yes, the result looks rough. Typical modes are 128x96 or 96x72 at only a few frames per second. That is deliberate. I was not trying to make nice-looking video. I was trying to keep enough scene information to answer basic questions: is somebody there, did something move, is that smoke, did the person just wave, is the situation getting worse? If it looks like security footage from a microwave, that is still within spec.

What started as a codec experiment slowly turned into a larger communication prototype. There is a browser dashboard with live raw, sent, and received views, plus controls for the link, text messages, relay import/export, and general status. Underneath that is a simple packet layer with fragmentation, CRCs, ACK and retry handling, presence messages, queue management, and config beacons. Video is only one payload type. The same system can also send text, snapshots, and low-rate fallback traffic, because once you are already making bad decisions, you may as well make them thoroughly.

The transport side also got a bit out of hand. The app can move data over acoustic bursts through a speaker and microphone, serial, optical patterns, and a file-relay mode. When the link gets worse, a fallback controller steps down through lower FPS, lower resolution, snapshot-only mode, and finally text-only mode. There is also a low-rate text path with plain text, Morse, and DTMF-style encoding, which is the sort of feature set you arrive at when “maybe this is enough” fails to stop you.

It is not hard to list the weak spots. This is not a standard video codec. It is not competing with real video compression, and that would be an embarrassing fight to pick anyway. The acoustic path depends heavily on the room, the hardware, and the amount of noise around it. The FEC is still fairly simple. Fast motion can still turn into stale or blocky output. But the upside is that the whole thing is small enough to understand, test, and package without turning into a giant black box.

A few practical extras made it in along the way: face-aware ROI prioritization, live bitrate and PSNR metrics, config hash checks before decode, browser-accessible HTTP endpoints, and tests for deterministic encoding, corruption handling, queue deduplication, communicator envelopes, and fallback logic. Somewhere along the way it stopped feeling like a codec toy and started feeling more like a rough field tool, or at least a very committed overreaction.

If I had to describe it in one line, it is a video system that accepts defeat slowly.

You can build and run it locally with:

cmake -S . -B build
cmake --build build -j
./build/emergency_video

Then open:

http://localhost:8080

// comments