Pure code-based music-reactive visual system for live performances. Built with Three.js and Web Audio API.
✨ 4 Unique Visual Scenes
- Starfield: Fly through cosmic star fields
- Galaxy: Spiral galaxy with rotating arms
- Whirlpool: Fluid color vortex
- Point Clouds: Abstract 3D forms (sphere, humanoid, terrain)
🎵 Real-time Audio Reactivity
- FFT frequency analysis (bass/mid/treble)
- Beat detection
- Dynamic visual response to music
🖥️ Multi-Screen Support
- Single display
- Spanning mode (one visual across multiple screens)
- Independent mode (different content per screen)
# Install dependencies
npm install
# Run development server
npm run dev
# Open browser to http://localhost:5173Controls:
SPACE- Next sceneA- Activate audio input (grant mic permissions)D- Toggle debug overlayF- Fullscreen
Allow microphone access when prompted. The system will analyze room sound.
Use loopback audio to route DJ software directly:
macOS:
- Install BlackHole (free): https://github.com/ExistentialAudio/BlackHole
- Create Multi-Output Device in Audio MIDI Setup
- Set browser to use BlackHole as input
Windows:
- Install VB-Audio Cable (free): https://vb-audio.com/Cable/
- Set DJ software output to CABLE Input
- Set browser to use CABLE Output
Linux:
pactl load-module module-loopbackConnect DJ mixer booth/record output to computer line-in, select as input device.
Modern browsers (Chrome 100+) support Window Placement API. The system will auto-detect displays.
Edit src/config/screens.js:
// Example: 3 displays side-by-side
export const mySetup = {
mode: SCREEN_MODES.SPAN,
screens: [
{ width: 1920, height: 1080, x: 0, y: 0 },
{ width: 1920, height: 1080, x: 1920, y: 0 },
{ width: 1920, height: 1080, x: 3840, y: 0 }
]
};- Run app in fullscreen (
Fkey) - Use browser's "use window as display" feature
- Or manually position window to span screens
# Build static site
npm run build
# Deploy to any HTTP server
# Or run locally with:
npm run previewPros: Easy updates, works everywhere Cons: Browser overhead, potential crashes
# Install Electron
npm install --save-dev electron
# Create electron-main.js (see below)
# Package for tour
npx electron-packager . VisualBackdrop --platform=darwin,win32 --arch=x64Create electron-main.js:
const { app, BrowserWindow } = require('electron');
app.whenReady().then(() => {
const win = new BrowserWindow({
fullscreen: true,
webPreferences: {
nodeIntegration: false
}
});
win.loadFile('dist/index.html');
});Pros: Stable, no browser UI, better performance Cons: Larger file size, OS-specific builds
# Install simple server globally
npm install -g serve
# Build and serve
npm run build
serve -s dist -l 3000
# Access from any device: http://laptop-ip:3000Edit visual scenes to reduce particle counts:
// In each scene file, reduce counts:
const particleCount = 5000; // Instead of 15000Increase quality:
// In main.js, increase pixel ratio:
this.renderer.setPixelRatio(window.devicePixelRatio); // Full quality- Reduce
analyzer.fftSizein AudioAnalyzer.js (256 instead of 512) - Disable antialiasing (already off by default)
- Lower particle counts
- Reduce shader complexity
Create preset sequences in src/config/presets.js:
export const MY_SET = {
scenes: [
{ name: 'starfield', duration: 60, transition: 'fade' },
{ name: 'galaxy', duration: 90, transition: 'fade' },
{ name: 'whirlpool', duration: 120, transition: 'cut' }
],
bpm: 128,
intensity: 0.8
};Load preset via keyboard shortcut (add to main.js controls).
No audio response
- Check browser permissions (microphone/system audio)
- Verify audio input in system settings
- Check debug overlay shows "Audio: Active"
Low FPS
- Close other applications
- Reduce particle counts (see Performance section)
- Lower screen resolution
- Disable browser extensions
Scenes look wrong
- Clear browser cache
- Check WebGL support: https://get.webgl.org/
- Update graphics drivers
- Try different browser (Chrome/Edge recommended)
Multi-screen not working
- Use Chrome 100+ for automatic detection
- Manually configure screens in config
- Check display settings (extend, not mirror)
- Create new scene file in
src/scenes/:
import { BaseScene } from './BaseScene.js';
import * as THREE from 'three';
export class MyScene extends BaseScene {
init(width, height) {
super.init(width, height);
// Setup your scene
}
update(time, audio) {
// Animate based on time and audio
// audio.bass, audio.mid, audio.treble, audio.volume, audio.beat
}
}- Register in
src/main.js:
import { MyScene } from './scenes/MyScene.js';
// In setupScenes():
this.sceneManager.addScene('myscene', new MyScene());Minimum:
- CPU: Intel i5 / Ryzen 5
- RAM: 8GB
- GPU: GTX 1050 / equivalent
- Outputs: HDMI/DisplayPort for each screen
Recommended:
- CPU: Intel i7 / Ryzen 7
- RAM: 16GB
- GPU: RTX 2060 / equivalent
- Outputs: Multiple DisplayPort
- SSD for fast load times
Tour Laptop Setup:
- Keep laptop plugged in (disable battery mode)
- Disable sleep/screensaver
- Close all other applications
- Disable notifications
- Use wired network if streaming content
Three.js Documentation: https://threejs.org/docs/ Web Audio API: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Shader Programming: https://thebookofshaders.com/ Audio Visualization: https://github.com/willianjusten/awesome-audio-visualization
MIT - Free to use, modify, and distribute.
Built with:
- Three.js (3D graphics)
- Web Audio API (audio analysis)
- Vite (bundler)
- Shader techniques from Shadertoy community