fugu.estate
SIGNAL OUT / FIELD SYSTEMS
/////////////
>>>> SIGNAL OUT / FIELD SYSTEMS
DIV. 01
<< BACK
video / embedded PRECRIME
UNIT >> PRECRIME / 2026
PRECRIME
video embedded
Rust · GStreamer · Swift · iOS · Raspberry Pi
>> REPO

PRECRIME is a redeployable multi-camera video switching rig for live performance and livestreaming, built around a surveillance aesthetic. It handles heterogeneous sources — iPhones, vintage analog CCTV cameras, modern IP cameras — and routes them to a Raspberry Pi 5 switcher with dual HDMI output: program feed and multiview preview. The whole stack is FOSS, written in Rust, with no proprietary SDK dependencies.

The Problem

Professional video switching for live performance typically means NDI (NewTek's proprietary protocol), which requires a closed SDK, per-seat licensing, and a macOS or Windows host. PRECRIME replaces that stack with H.264 over RTP on a standard LAN — the same transport used by IP cameras for decades — running on a $55 Raspberry Pi 5. The goal is a rig that can be rebuilt, repaired, and modified without a license agreement.

Key Decisions

RTP/multicast as the transport layer. Each camera source publishes H.264 on its own IPv4 multicast group (239.42.x.y, TTL=1, admin-scoped to the LAN). The switcher subscribes to all groups simultaneously. RTP gives ~80ms end-to-end latency on a local gigabit switch, which is acceptable for live performance, and the protocol is fully open with mature GStreamer support.

TEMPLE: decentralized discovery via UDP beacon. Rather than maintain a registry server, each source broadcasts a JSON "ball" to a fixed multicast channel (239.42.0.1:9999) every two seconds. The switcher (REPORT) listens and registers sources as they announce themselves. No central coordinator, no DNS, no per-source configuration — sources just appear.

iOS uses Bonjour instead of TEMPLE. iOS blocks multicast sends without an Apple entitlement not available on the App Store. The iOS camera app (WITNESS) discovers REPORT via Bonjour, opens a TCP connection to register, and receives an assigned UDP port for unicast RTP. From REPORT's perspective the pipeline is identical: same jitter buffer, same depayloader, same decoder, regardless of source type.

One GStreamer pipeline for all source types. All sources — multicast Pi encoders and unicast iPhones alike — feed the same rtpjitterbuffer → rtph264depay → avdec_h264 → input-selector chain. The input-selector element handles live switching; the pipeline doesn't rebuild on a cut.

Cross-compile on Mac, deploy binary to Pi. All Rust compilation runs on the macOS dev machine via cross (Docker-based cross-compilation). The Pi receives pre-built aarch64 binaries over rsync. No rustup, no cargo on the Pi — this frees ~1.5 GB of RAM per node, which matters when GStreamer's H.264 decode at four concurrent sources takes 600 MB on a 2 GB Pi 5.

Architecture

[WITNESS (iPhone)] ──┐
[PRECOG Pi+EasyCap] ─┼── WiFi/LAN ── [REPORT (Pi 5)] ──┬─▶ HDMI Program
[PRECOG Pi+...]  ────┘                                  └─▶ HDMI Multiview

Four named components. PRECOG is any H.264/RTP source on the LAN. TEMPLE is a Rust library crate providing the ball wire format and UDP multicast sender/receiver. REPORT is the Pi 5 switcher daemon: GStreamer pipelines, source registration, dual HDMI output. WITNESS is the iOS camera app — zero-config Bonjour discovery, H.264/RTP unicast, tap-to-focus, zoom, white balance lock, and a stage mode dashboard showing the REPORT connection state.

Status / What's Next

Software is complete and tested across 42 unit tests. Hardware procurement is pending: Pi 5s, a GL.iNet Flint 3 WiFi 7 router, and EasyCap USB analog capture cards. Phase 2 verifies the full stack on real hardware — Pi composite cameras, dual HDMI output, keyboard switching latency under 200ms, and a 2-hour soak test watching for RTP jitter buffer underruns.