bur1alrites

Period
2026
Contribution
Design and development
Status
Live client portfolio

A video-led portfolio for Allie's live lighting work, combining an interactive gallery, a 3D projector room, and an automated playback pipeline.

bur1alritesHomepage

A site that reacts

My friend Allie creates real-time, audio-reactive lighting for events. She wanted a site that responded like her shows.

I designed and developed the interface, scenes, and media pipeline. The background responds to video brightness and pointer input, with splashes on click. Allie chose the typeface and supplied visual references, giving us a starting point. Her lighting is audio-reactive; the site's visual response uses video and pointer input.

The bur1alrites wordmark glowing over a grainy, black-and-white video background.
The video-driven background and glowing wordmark.
An off-angle inspection of the actual home scene: a wireframe video plane, floating wordmark, floor artwork, grid, and camera guides.
The home scene from the side. A local inspection capture with a wireframe overlay and camera guides; bloom is disabled.

Moving through the work

The gallery introduces spatial depth before a visitor enters the projector room. Three.js, through React Three Fiber, places video previews in the scene with slight parallax. Inverted previews reveal their colour on hover; choosing a clip changes the scene and opens that video in the room.

Inverted video thumbnails arranged in columns over the reactive background.
Gallery previews reveal colour on hover; selecting a clip takes it from the gallery into the projector room.

The projector room

Opening a clip takes you into a room built around a projected image. Bloom lets the light spill beyond the screen.

The supplied footage was heavily compressed. I used animated grain to make the artifacts less conspicuous and give the projection its texture. Grain changes how the footage is presented; it does not restore lost image detail.

A video projected inside a dark 3D room, with grain, glowing highlights, and reflections.
Bloom extends the projected light beyond the screen, while animated grain works with the compressed source footage.

Balancing video and 3D rendering

Video decoding and the 3D scene compete for browser resources. An automated encoding worker prepares HLS playback renditions while preserving the masters. A viewport pool preloads visible previews at the lowest rendition, stops idle buffering, and lets only the active preview upload frames into the scene. Offscreen streams are released.

Rapid scrolling creates an ownership problem: a stream can finish attaching after its card has left and returned with a new player. The viewport video pool checks instance identity before accepting that completion and destroys stale controllers. Its lifecycle regression test recreates that sequence and asserts that the old controller is destroyed while the replacement remains alive. Another case protects rapid leave and re-entry while a play promise is pending.

Recovery is bounded: an active preview gets at most two delayed automatic retries, and leaving the viewport or hiding the page cancels recovery work. Autoplay denial does not start a retry loop; the poster remains until playback produces a frame. HTML/mobile previews and the WebKit-safe rendering path retain the same viewport loading policy. These are implementation provisions; the mocked player tests do not establish real-device codec support or frame rate.

A separate quality controller responds to sustained frame times. Lower presets reduce pixel ratio, reflections, geometry detail, and bloom work. Upgrades require a longer stable interval than downgrades, trading some visual detail for less frequent quality switching. Synthetic-frame tests check that policy; they are not measurements of GPU performance.

Maintaining the archive

Next.js keeps public pages and admin routes in one app. Allie can upload MOV or MP4 masters through multipart transfers to R2, then a separate worker creates playback versions. Failed parts and finalization can be retried while the page stays open; upload sessions are not restored after a reload.

The result is a maintainable clip archive with two connected viewing modes: a gallery for choosing work and a projector room for watching it. This was my first Three.js project, and coordinating browser video lifecycles with the spatial scene became as important as building the scene itself. The source examples here are pinned to the October implementation; browser and device measurements would be needed before making a broader performance claim.