r_e_c_u_r is a Rust port of langolierz/r_e_c_u_r, a video sampler for Raspberry Pi from the live video performance community. It plays back video files from banks of ten sample slots, applies GLSL shaders live, and supports frame-accurate scrubbing via an in-memory frame ring. The original is Python; this port targets the same Pi hardware with substantially less RAM usage and compile-time feature flags that select hardware codec paths for Pi 3 B+ versus Pi 5.
The Problem
The original r_e_c_u_r is a well-regarded tool in the video performance community, but its Python runtime and GStreamer bindings consume meaningful memory on constrained Pi hardware, and the hardware decode paths for Pi 3 and Pi 5 are meaningfully different — the Pi 5 adds H.265, VP9, and AV1 that the Pi 3 lacks. A Rust port eliminates interpreter overhead, allows compile-time selection of hardware codec paths, and makes the byte budget of the frame scrub ring an enforced constraint rather than an approximation.
Key Decisions
Compile-time hardware targeting via Cargo features. Pi 3 B+ and Pi 5 have different hardware H.264 decode implementations, and the Pi 5 adds codecs the Pi 3 doesn't support. Selecting these at runtime via config strings risks silent fallback to software decode under load. Rust Cargo features (pi3 and pi5, mutually exclusive, enforced by build.rs) make the hardware target an explicit compile-time decision. build.rs fails fast if neither or both features are set, preventing ambiguous builds.
Byte-budgeted frame ring. The detour phase holds decoded video frames in memory for scrubbing and speed/direction manipulation. On embedded hardware, unbounded memory growth is a reliability failure. The ring is capped by a byte budget determined at compile time: 128 MB on Pi 3 B+, 256 MB on Pi 5, 512 MB on desktop. Frame eviction is FIFO once the budget is reached.
GLSL shader layer with per-target profile filtering. Shaders compile against the GLSL ES profile appropriate for the target: Pi 3 uses GLSL ES 1.00, Pi 5 uses GLSL ES 3.10. The shader browser filters available shaders by the active profile at startup — a shader requiring texelFetch (ES 3.00+) is hidden and refused on Pi 3. This prevents the common failure mode of distributing shaders that silently degrade or error on constrained hardware.
10 slots × 26 banks. The bank/slot system mirrors the original: 26 banks (A–Z) each holding ten video slots. This matches the muscle memory of the existing r_e_c_u_r community — people who already own the hardware and know the workflow.
macOS/Linux dev parity. The full feature set except hardware codecs runs on macOS and Linux x86_64. 257 unit tests run on desktop CI without any hardware. Pi-specific code paths are behind feature flags and aren't compiled on desktop targets, so the CI signal is reliable.
Architecture
r_e_c_u_r is structured in four additive phases. core handles file playback and the bank/slot system. conjur adds the GLSL shader layer with hot-reload. detour adds the byte-budgeted in-memory frame ring and scrub mode. captur adds live USB camera input via v4l2, concurrent splitmuxsink recording, and auto-import of recordings into bank slots.
Each phase is a compile-time feature that extends the previous. A Pi 3 build with all phases enabled is still a single binary that fits in the 1 GB RAM envelope.
Status / What's Next
Phases core, conjur, and detour are complete with 257 tests passing. Phase 4 (captur — live USB camera input and recording) requires a Pi with a USB camera for hardware verification of the v4l2 capture path.