Audio Visualization with JavaScript
There is something deeply satisfying about seeing sound. Audio visualizers turn music into motion, mapping frequencies and amplitudes to colors, shapes, and movement. The Web Audio API makes this surprisingly accessible in the browser, and once you understand the core concepts, you can build everything from simple bar charts to complex reactive art pieces.
The Web Audio API: How It Works
The Web Audio API lets you process and analyze audio in real time. Think of it as a chain of connected nodes. Audio comes in from a source (a file, a microphone, a stream), passes through processing nodes, and goes out to your speakers. For visualization, the key node is the AnalyserNode - it gives you access to frequency and waveform data without modifying the audio.
const audioContext = new AudioContext();
const analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
// Connect audio source to analyser
const source = audioContext.createMediaElementSource(audioElement);
source.connect(analyser);
analyser.connect(audioContext.destination);That is the entire setup. You now have an analyser node sitting between your audio source and the output. It listens to everything passing through and makes the data available for you to read.
Getting Frequency Data
The AnalyserNode gives you two types of data: frequency data and time-domain (waveform) data. Frequency data tells you how loud each frequency band is at any given moment. Time-domain data gives you the raw waveform shape.
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
// Call this in your animation loop
analyser.getByteFrequencyData(dataArray);
// dataArray now contains 0-255 values for each frequency binThe fftSize property controls resolution. A higher value gives you more frequency bins (more detail) but costs more processing time. 2048 is a solid default. You get 1024 frequency bins, which is more than enough for most visualizations.
Building a Basic Bar Visualizer
The simplest visualization maps frequency data to vertical bars on a canvas. Each bar represents a frequency range, and its height represents the volume of that range.
const canvas = document.getElementById("visualizer");
const ctx = canvas.getContext("2d");
function draw() {
requestAnimationFrame(draw);
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "rgb(10, 10, 15)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
const barWidth = (canvas.width / bufferLength) * 2.5;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const barHeight = dataArray[i];
const r = barHeight + 25;
const g = 250;
const b = 50;
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
}
draw();This gives you a functional visualizer in about 20 lines. The bars jump up and down with the music. It works. But it looks like something from 2005.
Making It Look Good
The difference between a basic visualizer and something that looks polished comes down to a few techniques:
Use Fewer Bars with Smoothing
You do not need 1024 bars. Sample every 4th or 8th bin, or average groups of bins together. Fewer, wider bars with rounded caps look much cleaner. Set analyser.smoothingTimeConstant to something between 0.8 and 0.9 to make the bars move smoothly instead of jittering.
Add Color Gradients
Map the frequency position to a color gradient. Low frequencies get warm colors (reds, oranges), highs get cool colors (blues, cyans). Use HSL color space so you can just sweep the hue value from 0 to 360 across the frequency spectrum.
const hue = (i / bufferLength) * 360;
ctx.fillStyle = `hsl(${hue}, 100%, ${50 + barHeight / 5}%)`;Draw Circles Instead of Bars
Arrange your frequency data in a circle. Each data point controls the radius of a point on the circle. This creates those iconic circular visualizer patterns. Use Math.cos and Math.sin to place points around the circumference and scale their distance from center based on the frequency amplitude.
Add Glow Effects
Set ctx.shadowBlur and ctx.shadowColor to add bloom/glow to your shapes. A cyan glow on a dark background immediately makes everything look more polished. Layer multiple draws at decreasing opacity for a more natural bloom effect.
Working with Waveform Data
Frequency data is great for bar charts and radial visualizers, but waveform data gives you the actual audio wave shape. Use getByteTimeDomainData() instead of getByteFrequencyData(). Draw it as a line across the canvas and you get an oscilloscope view. Style it with thick strokes and glow effects and it becomes a centerpiece.
analyser.getByteTimeDomainData(dataArray);
ctx.beginPath();
const sliceWidth = canvas.width / bufferLength;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const v = dataArray[i] / 128.0;
const y = (v * canvas.height) / 2;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
x += sliceWidth;
}
ctx.strokeStyle = "#00f0ff";
ctx.lineWidth = 2;
ctx.stroke();Performance Tips
- Always use requestAnimationFrame instead of setInterval for your render loop
- Reuse your Uint8Array instead of creating a new one each frame
- Clear the canvas with a semi-transparent fill instead of clearRect to create trail effects
- If you need more performance, consider OffscreenCanvas or WebGL rendering
- Keep your fftSize at 2048 or lower unless you genuinely need more resolution
Microphone Input
Want to visualize live audio? Use getUserMedia to access the microphone:
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
// Don't connect to destination - that would cause feedbackNote: do not connect microphone input to audioContext.destination unless you want ear-splitting feedback. The analyser reads the data without needing output.
Next Steps
Once you have the basics down, explore combining multiple data sources. Layer frequency bars with waveform lines. Add particle systems that respond to bass frequencies. Use Three.js for 3D visualizations where geometry deforms to the beat. Check out our advanced audio visualizer tutorial for more complex techniques, or dive into generative art for broader creative coding concepts.
The Web Audio API gives you everything you need to turn sound into something you can see. Start with the bar visualizer, get comfortable reading frequency data, then experiment. The best audio visualizations come from playing with the code until something unexpected happens - and then figuring out how to make it happen on purpose.