On this page

Chapter 5 of 7. Prerequisite: Mapping bass to motion. You already have a bass band driving scale and brightness on a rectangular frame. This chapter takes the same 32-bin array and arranges it around a centre instead of along an edge.

Search "remotion audio visualizer radial circular" and you get bars. Every result is a row of rectangles that grow with the music. The compelling forms, the ones that read as a pulse or a burst rather than an equaliser, are almost entirely absent from tutorials. They are not hard to build. What is missing is the one substitution that turns a bar chart into a circle: stop mapping bin index to an x-position, start mapping it to an angle.

Remotion audio visualizer: radial and circular, not bars

The bar visualiser and the radial visualiser read from the exact same source. In Remotion's audio-visualization model, visualizeAudio() hands you "an audio spectrum for the current frame". That spectrum is an array. A bar layout walks the array left to right and sets each element's height. A radial layout walks the same array and sets each element's angle. Nothing else changes about the analysis.

There are two distinct things people mean by "radial", and this build shipped the second one, not the first.

The first is a circular spectrum: N bins placed on a ring, each drawn as a spoke whose length tracks that bin's amplitude. This is the direct analogue of the bar chart, bent into a circle. It is the thing the target query is usually looking for, and this chapter shows the geometry for it.

The second is a radial field: no discrete spokes, but light and mask geometry that is itself circular. Here a gradient blooms from a centre, a conic fan rotates over the frame, and a disc-shaped alpha mask carves the light into a circle. The visualiser in this course leans on the second, because a photograph-backed music video wants light, not an overlaid graph. Both are radial and they answer to different aesthetics, so know which one you are building before you write a line.

The frequency array you are mapping

Whichever radial form you pick, you start from the array. This build asks Remotion for 32 bins per frame, twice, once smoothed and once raw:

// TrackVisualiser.tsx:53-54
const smooth = visualizeAudio({ fps, frame, audioData, numberOfSamples: 32, smoothing: true });
const raw    = visualizeAudio({ fps, frame, audioData, numberOfSamples: 32, smoothing: false });

numberOfSamples: 32 is the ring resolution. It is the count of spokes you could draw. For a circular spectrum, 32 gives a legible, chunky ring. Push it to 128 for a fine corona, but know that beyond a point the eye stops resolving individual spokes and reads a solid disc anyway.

The values matter as much as the count. visualizeAudio() returns "an array of values describing the amplitude of each frequency range. Each value is between 0 and 1." Pre-normalised. That 0-to-1 guarantee is what makes the radius mapping trivial. Contrast the browser's own analyser, where getByteFrequencyData() returns "integers on a scale from 0 to 255", and you would divide by 255 before you could use it. Remotion has done that division for you.

This build never draws all 32 as spokes. It collapses them into bands with a plain averaging helper over fixed index slices:

// TrackVisualiser.tsx:55-58
sub     = clamp(avg(smooth, 0, 3)   * 3.2);  // bins 0–2   sub-bass envelope
kick    = clamp(avg(raw,    0, 2)   * 3.6);  // bins 0–1   raw transient
hats    = clamp(avg(smooth, 22, 32) * 4.5);  // bins 22–31 highs
hatsRaw = clamp(avg(raw,    22, 32) * 5.0);  // bins 22–31 raw highs

Low bins are bass, high bins are treble. That mapping is linear. There is no log-frequency remapping in this code, because the bins Remotion returns are already the granularity the design needed. If you are building a circular spectrum you will use the whole array. If you are building a radial field, as here, you reduce the array to a handful of scalars and drive gradient geometry with those.

Mapping bins to angle and radius

Here is the geometry the tutorials skip. To place bin i on a ring, convert its index to an angle by sweeping the full circle across the array length, then convert its amplitude to a length with interpolate(), which "map[s] a range of values to another using a concise syntax":

const bins = visualizeAudio({ fps, frame, audioData, numberOfSamples: 32, smoothing: true });
const cx = width / 2;
const cy = height / 2;
const inner = height * 0.22;

bins.map((v, i) => {
  const angle = (i / bins.length) * Math.PI * 2;   // index → radians around the circle
  const len   = interpolate(v, [0, 1], [0, height * 0.18]); // amplitude → spoke length
  const x1 = cx + Math.cos(angle) * inner;
  const y1 = cy + Math.sin(angle) * inner;
  const x2 = cx + Math.cos(angle) * (inner + len);
  const y2 = cy + Math.sin(angle) * (inner + len);
  return { x1, y1, x2, y2 };
});

Three lines carry the whole idea. (i / bins.length) * Math.PI * 2 distributes the bins evenly around a full turn. inner is the radius of the hole in the middle, the ring the spokes stand on. interpolate(v, [0, 1], [0, height * 0.18]) turns each 0-to-1 amplitude into a pixel length. Draw a line, a rounded rect, or an SVG path from the inner point to the outer point and you have a spoke. Repeat for 32 spokes and you have a circular spectrum.

That is the answer to the query stated plainly. A bar visualiser is x = i * spacing. A radial visualiser is x = cos(angle) * radius, y = sin(angle) * radius. The signal is identical. Only the placement function changed.

The radial gradient is the workhorse

The radial field this build ships starts with a CSS radial gradient positioned at the light source of the photograph, its opacity driven by the bass band. Screen-blended, so it adds light without flattening the shadows:

// TrackVisualiser.tsx:115-118
background: `radial-gradient(58% 42% at ${raySource[0]*100}% ${raySource[1]*100}%,
             rgba(232,196,106,${0.22 * glow}), transparent 62%)`,
mixBlendMode: 'screen',

This is a radial visualiser with zero spokes. The at X% Y% places the bloom's centre where the sun already sits in the still, so when the sub-bass swells the light appears to come from the scene rather than from an overlay. transparent 62% is the falloff, the point where the gradient reaches full transparency, which is what gives it a soft circular edge instead of a hard disc. The glow scalar in the alpha is the audio. Bass up, bloom up.

The same primitive builds the vignettes on the video-backed compositions, a dark radial gradient that fades in at the frame edge:

// ReactiveFinish.tsx:102
radial-gradient(ellipse at center, rgba(0,0,0,0) 55%, rgba(0,0,0,0.5) 100%)

Transparent through the centre 55%, then darkening to 50% black at the corners. A circular form again, doing structural work, keeping the eye on the middle of the frame. Radial geometry earns its place well beyond the reactive layer, where it is the cheapest way to shape attention in a rectangular video.

The rotating conic fan and its radial alpha mask

The most explicitly circular element in the build is a fan of volumetric light rays. A conic-gradient div rotates slowly with the frame:

// TrackVisualiser.tsx:80
const rayRot = frame * 0.02;

A raw conic gradient fills the whole rectangle, which looks like a pinwheel painted onto the frame. Wrong read. To turn it into a burst of light emanating from a point, you fade its edges to transparent with a radial alpha mask. This build sets both the prefixed and unprefixed mask-image property, which "hides sections of the element on which the masking image is set based on the alpha channel of the mask image":

// TrackVisualiser.tsx:127-128
WebkitMaskImage: 'radial-gradient(closest-side, black 0%, rgba(0,0,0,0.5) 28%, transparent 66%)',
maskImage:       'radial-gradient(closest-side, black 0%, rgba(0,0,0,0.5) 28%, transparent 66%)',

The mask is opaque black at the centre, so the conic shows through fully there. It falls to half alpha at 28% and to full transparency at 66%, so the fan dissolves before it reaches the frame edge. The rectangle full of rotating conic becomes a soft circular burst of light. This is the whole radial technique in one property: a full-frame layer, shaped into a circle by a radial-gradient mask rather than by clipping.

Why a radial reveal reads differently

Not every radial element is a graph. The most interesting one in the wider project was a mask. Cj's design notes record an earlier build, codenamed tasogare, that ran a radial alpha-mask portal over a photograph. The celestial bloom in this chapter is that same primitive re-aimed at light rather than at a reveal.

The shape of a mask carries meaning before its content does, and this is worth stating as a rule of thumb rather than a law. A circle from a fixed centre reads as an aperture, a window opening in place. A rectangle reads as a wipe, a transition sliding across. A circle from a moving centre reads as something chasing the frame. If you want the reveal to feel like a portal, hold the centre still and drive only the radius. Pick the shape for the read you want, then wire the audio to it.

This also generalises past audio. Because the mechanism is only a radius and a centre driven by a signal, the same approach works for any two same-size layers. The audio is just the switch. Swap the bass envelope for a scroll position or a time ramp and the technique is unchanged.

The transferable rule

A radial visualiser is a bar visualiser with one function swapped. Where the bar layout writes a bin's amplitude into a height and its index into an x-position, the radial layout writes the amplitude into a radius and the index into an angle. The visualizeAudio() call, the 32 bins, the 0-to-1 normalisation, the band maths: all identical.

Then decide which radial you are actually building. Discrete spokes on a ring, drawn from the full array, for an abstract piece. Or radial fields, gradients and conic fans and alpha masks, driven by a few reduced bands, when the visualiser sits over an image and wants to add light rather than draw a chart. This build chose the second, and the whole of its circular character comes from three CSS primitives: a radial-gradient background, a rotating conic-gradient, and a radial-gradient used as mask-image. No canvas, no SVG spokes, no per-bin loop.

Next chapter takes the alpha mask from this one and makes it the whole subject: compositing layers so the mask reads as a portal into different content instead of as a light switched on.

// EXERCISE

Bend your spectrum into a ring, then trade it for light

Build both radial forms over one of your own tracks. First a circular spectrum: place all 32 bins on a ring by converting index to angle and amplitude to spoke length with interpolate, standing the spokes on an inner radius. Then a radial field over one of your own images: a screen-blended radial gradient whose alpha is driven by a reduced band, positioned at a light source that already exists in the picture. Decide deliberately which band feeds each form, and note how differently a smoothed and a raw driver read.

Expected behaviour
  • 32 spokes are distributed evenly around a full circle and each spoke's length tracks its bin's amplitude per frame
  • An inner radius keeps a hole in the middle so the form reads as a ring rather than a starburst from a point
  • The radial-field version adds light to the image on bass swells without drawing any spokes
  • Swapping the field's driver between the smoothed and the raw band produces a visibly different temperament on the same passage

PROVE IT Show the two versions side by side on the same passage and say which one you would ship over a photograph, and why.

// CHECKPOINT — RADIAL FORMS
multiple choice · auto-checked

What is the single substitution that turns a bar visualiser into a circular spectrum?

exact answer · auto-checked

In the ray-fan mask gradient, the mask reaches full transparency at which percentage stop?

open · self-checked

The chapter names two different things people mean by radial. What are they, and which did this build ship?

Show answer

A circular spectrum is N bins on a ring, each drawn as a spoke whose length tracks that bin's amplitude, the bar chart bent into a circle. A radial field has no discrete spokes: gradients, a rotating conic fan and a disc-shaped alpha mask make the light and mask geometry itself circular. This build shipped the field, because a photograph-backed music video wants light rather than an overlaid graph.

↺ re-read: “Remotion audio visualizer: radial and circular, not bars

Sources

  • Audio Visualization
    remotion.dev
    Anchors the premise that Remotion gives you a per-frame audio spectrum via visualizeAudio(), which is the raw material a radial form is built from
    remotion.dev
  • visualizeAudio()
    remotion.dev
    Source-of-truth for the shape of the returned array: one normalised amplitude per frequency range, each value between 0 and 1, which is what gets mapped to a radius
    remotion.dev
  • interpolate()
    remotion.dev
    Reference for mapping a 0-1 bin value into a pixel radius range for the circular layout
    remotion.dev
  • mask-image CSS property - CSS | MDN
    developer.mozilla.org
    Backs the radial alpha mask: a radial-gradient used as mask-image fades a full-frame layer to a soft-edged circular burst by its alpha channel
    developer.mozilla.org
  • AnalyserNode: getByteFrequencyData() method - Web APIs | MDN
    developer.mozilla.org
    Explains that raw FFT frequency bins are 0-255 integers, the reason Remotion hands you a pre-normalised 0-1 array instead
    developer.mozilla.org
Back to guide overview