All Projects

3D Music Visualiser

A live, music-reactive VJ app: real-time generated visuals on real-time 3D surfaces, running in the browser on WebGPU

Client Self-Initiated BuildYear 2026Duration 7 days

The Challenge

I wanted visuals for my own gigs and for background screens at concerts: generated, reacting to the music, and mapped onto 3D surfaces the way projection-mapping shows are. Desktop VJ tools do this. The browser can now drive the GPU directly through WebGPU, so the question was whether a web app could do the same job on a real stage. That sets a high bar. It has to react to music it can actually hear, hold a steady 60 fps on a projector for hours, run on two screens at once, and be usable by one person in the dark. It also has to stay inside the rules: YouTube's terms ban downloading or separating its audio, and Spotify's ban analysing it.

The Solution

The app runs as two windows. The control window sits on the laptop and does all the listening. The output window goes fullscreen on the projector and only draws. They talk over BroadcastChannel, and the output window runs on its own main thread, so a busy control screen cannot stall the show. Audio is analysed by my own FFT in an AudioWorklet. Local files are also analysed in full before they play, so the app knows the tempo, the beat grid and where the drops are. For anything else, it simply listens, like a microphone would. Visuals are written in WGSL shaders and run on three.js's WebGPU renderer, with my own pass graph and post-processing chain. The control UI is React, but the render loop is plain TypeScript and never runs inside React. I built it with Claude Code in staged sessions. Each stage ended with tests and a written handoff, and every performance claim had to be measured before it went in.

The Show

43 scenes, each made of a generated texture, a 3D surface, a camera path, post effects and a palette. Every parameter can be driven by the music.

  • 30 core scenes

    Aurora skies over a dome, fractal tunnels, a disco ball, a building facade of extruding blocks, neon terrain, kaleidoscopes, reaction-diffusion growth, mirror rooms and more. Built from 23 generators, 9 surfaces and 25 palettes.

  • Black and white with a streak of colour

    7 mono variants, plus a Mono key that turns any scene black and white with a single colour accent, in 6 different forms.

  • Your own mark

    6 pattern scenes are made from an uploaded logo or image: tiled walls, mandalas, stamps and a tunnel through the mark. It can be swapped mid-show without dropping a frame.

  • Heavy GPU work

    About a million GPU particles following a flow field, and a Mandelbrot deep zoom to 1e-12 using perturbation, both inside the frame budget.

  • Built for projection

    A post-processing chain of feedback trails, bloom, chromatic aberration, tone mapping and film grain.

Listening to the Music

The app reacts to sound it can read. That rules out Spotify's API and YouTube downloads, so it is designed around what is allowed.

  • Local files first

    Drop in a folder of tracks. Each one is decoded and analysed in a background worker: tempo, beat grid, downbeats, energy and sections such as build, drop and breakdown.

  • Listen mode for everything else

    A microphone, a line-in from the DJ mixer, a loopback device, or a captured browser tab. Spotify plays as normal and the visuals follow what the app hears.

  • YouTube, by the rules

    The official YouTube player opens in a small visible window, and the app listens to that window's sound.

  • Real-time features

    Bass, mids and highs, level, onsets, tempo, beat phase, brightness and change, all smoothed so the visuals pulse without flicker.

  • Sets that flow

    Gapless playback or crossfades, with a choice of image, video, colour or scene between songs.

The Auto-Director

Left alone, the app runs the show itself.

  • Scenes that fit the music

    It scores every scene against the music's energy, tempo and brightness, and picks from the set's own pool of scenes.

  • Cuts on the drop

    For analysed files it changes scene on drops, breakdowns and new songs, landing on the downbeat. In the control-window recording on this page it cuts from Aurora Dome to Stamp on the drop.

  • It explains itself

    The Director page lists every change and the reason for it, so the performer can trust it or take over.

  • Always overridable

    One key locks the current scene, another hands control back.

For the Performer

The interface is designed as an instrument panel, not a dashboard. I prototyped three directions and chose "Patchbay".

  • A patch bay on the main screen

    Audio features are output jacks and visual controls are input jacks. Drawn cables connect them and glow with the signal, so you can see what the music is doing to the picture.

  • Made for a dark room

    Warm off-white legends on graphite, one accent colour that follows the visuals, and red used only for blackout. Single-key controls, large targets, and no pop-up dialogs during a show.

  • Fit it to the venue

    Corner-pin and mesh warp to fit the picture to a real wall, masks for windows and doors, saved per venue, and up to 4 outputs.

  • Hands on

    MIDI learn, tap tempo, freeze, blackout, and a panic key with a 10-second undo.

  • Ready before doors open

    Show profiles, a 7-step setup wizard, a preflight check, and built-in guides. Output can be recorded to MP4.

  • Tablets and phones

    On narrow screens the panel becomes one scrolling column, with the page buttons in a fixed bar at the bottom. Checked in Chrome at phone and tablet widths.

Built to Run All Night

A visualiser that stutters or crashes mid-set is worse than none. Performance was measured, not assumed.

  • A steady 60 fps

    All 30 core scenes ran at 60 fps with 0 dropped frames at 1920×1080 and at the MacBook's full 3456×2234, on an M4 Max in Chrome (production build, headless).

  • On the beat

    Beats reach the output window within one display frame of being heard, measured from Chrome's audio clock.

  • Long runs

    A headed 17-minute run at 1080p drew 60,166 frames with 0 dropped and no errors. The app has a soak-test runner for full-night tests.

  • Recovers by itself

    If the GPU resets, it rebuilds and carries on. A lost audio source, an output window that crashes or reloads, or a broken scene each has its own recovery path.

The Results

A working VJ app, live on this site. Open it in desktop Chrome (it needs WebGPU), load some audio files or point it at a sound source, and press 1 to 0 to change scenes. The output window can go to a second screen or a projector. Measured on the target MacBook, every core scene holds 60 fps at full Retina resolution and beats land within one display frame. Still to do: an 8-hour soak test, and checks with a real projector and a real MIDI controller.