Library / SDK
jberg/butterchurn avatar
jberg/butterchurn

Butterchurn: Browser-Based MilkDrop-Style Audio Visualization

Butterchurn is a WebGL implementation of the Milkdrop Visualizer

1,973 stars171 forksJavaScriptMIT

At a glance

What is it?
Butterchurn brings MilkDrop-style preset visualization to modern browser applications through WebGL 2 and the Web Audio API. It fits developers building music players, audio-reactive pages, or custom canvas experiences, but its beta package, WebGL 2 requirement, and separate preset dependency narrow adoption.
Who is it for?
Browser developers needing a programmable MilkDrop-style visualizer should first confirm WebGL 2 support, inspect their preset licensing, and verify that the beta package satisfies their deployment requirements. Teams seeking a stable release history or a non-WebGL visualization path should look elsewhere, because Butterchurn has no GitHub releases and its package version remains a beta.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why Butterchurn Exists for Browser Audio Applications

Butterchurn solves a specific graphics problem: rendering audio-driven visual effects in a web application. It is a JavaScript implementation of the MilkDrop Visualizer, intended for developers who already have an `AudioContext`, an `AudioNode`, and a visible canvas. The project is not a complete music player, audio decoder, or hosting platform. It accepts the existing audio graph and renders the visual response into the supplied canvas.

That boundary makes Butterchurn suitable for a local music interface, an audio-reactive landing page, or a browser-based tool that visualizes microphone input. The README also lists integrations with Webamp, browser extensions, personal music servers, video generators, and other visualizer applications. Those entries demonstrate several possible hosts, although the README does not provide separate integration guides for each one.

The project is especially relevant to developers who want preset-based visualization without treating every effect as a custom WebGL shader. Butterchurn supplies a `createVisualizer` API, preset loading, preset blending, renderer resizing, and a support check. The visual result still depends on WebGL 2 and on presets loaded from `butterchurn-presets`.

MilkDrop is a meaningful comparison rather than another browser package. The README credits Ryan Geiss with creating MilkDrop and describes Butterchurn as its WebGL implementation. The distinction is therefore the execution environment and integration model: MilkDrop is the original visualizer, while Butterchurn exposes the effect through a browser-oriented JavaScript API.

The AudioContext-to-Canvas Data Flow

The documented data flow starts with two application-owned browser resources. `audioContext` supplies the Web Audio context, while `canvas` supplies the drawing target. `butterchurn.createVisualizer(audioContext, canvas, options)` combines them with renderer dimensions. The documented options set `width` and `height`, after which the returned visualizer becomes the application-facing object.

Audio enters separately. `visualizer.connectAudio(audioNode)` receives a node from an audio source or microphone, which means Butterchurn does not require its own file-loading or microphone-permission layer. The host application remains responsible for creating and managing that `AudioNode`. This separation is useful when the same audio graph contains other processing or destinations.

Visuals come from presets. `butterchurnPresets.getPresets()` returns a collection, and the README selects one by its complete preset name. `visualizer.loadPreset(preset, 0.0)` loads that preset, with the second argument documented as the number of seconds used to blend presets. Applications can also call `visualizer.setRendererSize(1600, 1200)` when the available drawing area changes.

Rendering is explicit. The host calls `visualizer.render()` for a frame. The documentation does not describe an internal animation loop, frame scheduler, or exact audio-frequency mapping, so an application should not assume that loading a preset begins continuous rendering on its own.

The repository metadata adds more context. The package identifies WebGL, Web Audio, AssemblyScript, and WebAssembly as relevant technologies, and `package.json` lists `@assemblyscript/loader`, `eel-wasm`, and `ecma-proposal-math-extensions` among runtime dependencies. The package also publishes Rollup-built distribution files. These details indicate a JavaScript package backed by additional runtime components, but the README does not expose the internal rendering pipeline.

Installing Butterchurn and Loading the First Preset

Install both the visualizer and its separately named preset package. The README offers equivalent commands for pnpm, Yarn, and npm. This produces both the rendering library and the preset collection needed by the documented example.

bash
pnpm add butterchurn butterchurn-presets

The same installation can be performed with Yarn:

bash
yarn add butterchurn butterchurn-presets

Or with npm:

bash
npm install butterchurn butterchurn-presets

After the browser already has a usable `AudioContext`, `canvas`, and `AudioNode`, the first visualizer can be created with the dimensions required by the page. The documented flow then connects audio, selects one named preset, resizes the renderer, and starts explicit frame rendering.

js
import butterchurn from 'butterchurn';
import butterchurnPresets from 'butterchurn-presets';

const visualizer = butterchurn.createVisualizer(audioContext, canvas, {
  width: 800,
  height: 600
});

visualizer.connectAudio(audioNode);

The preset collection is obtained separately because preset content is delivered by `butterchurn-presets`. The README's example selects one entry from that collection and passes it to `loadPreset`.

js
const presets = butterchurnPresets.getPresets();
const preset = presets['Flexi, martin + geiss - dedicated to the sherwin maxawow'];

visualizer.loadPreset(preset, 0.0);
visualizer.setRendererSize(1600, 1200);
visualizer.render();

At this point the expected result is one rendered visualizer frame containing the response driven by the connected audio node. Continuous playback still belongs to the host's audio and animation flow. The README does not document teardown methods, automatic frame scheduling, or a fallback for unavailable WebGL 2.

WebGL 2 Checks and the Remaining Browser Constraints

WebGL 2 is a hard requirement in the README. A host can check support through the published `isSupported.min` entry before loading the full visualizer. The package manifest includes `dist/isSupported.min.js` among its published files, and the README imports it as `butterchurn/lib/isSupported.min`.

js
import isButterchurnSupported from "butterchurn/lib/isSupported.min";

if (isButterchurnSupported()) {
  // Load and use butterchurn
}

The block shows the intended decision point: only proceed when the support helper returns true. It does not explain a fallback visualizer, an error message, or behavior under disabled hardware acceleration. Those remain application responsibilities.

Canvas sizing is another concrete constraint. The visualizer is initialized with a width and height, then resized through a separate method. Butterchurn cannot create the canvas from this example because the caller supplies it. Clear sizing, pixel density rules, layout behavior, and cleanup are therefore controlled by the host application rather than documented as Butterchurn features.

The audio side has a similar boundary. The source or microphone must produce an `AudioNode` before `connectAudio` is called. The README does not cover audio-context suspension, browser autoplay policy, microphone permission handling, or disconnected-node cleanup. A developer should not infer support for those concerns from the short example.

This browser dependency also makes Butterchurn a poor fit for software that must run in environments without WebGL 2, such as a rendering target that only offers canvas 2D. In that case, use a visualizer built for the available renderer or a native graphics path rather than treating the support check as an automatic compatibility solution.

Preset Packaging, Release State, and Upgrade Work

Butterchurn separates execution code from preset content. The install command always adds both `butterchurn` and `butterchurn-presets`, and the example imports `getPresets` from the latter. An upgrade therefore involves reviewing both packages, even though the runtime API lives in `butterchurn`.

The repository version in `package.json` is `3.0.0-beta.5`. The project also has no GitHub releases. These are direct maintenance and adoption signals. The README does not publish a stable migration guide, release schedule, compatibility matrix for presets, or policy for breaking changes between beta builds. A consumer should therefore treat the selected package version as part of its own compatibility decision.

The repository is not archived. Its last push was on 2026-04-20, so its recent source changes do not by themselves imply a stable release cadence. The absence of GitHub releases remains relevant when a team needs an auditable package history or a predictable upgrade path.

The package manifest uses `type: module` and points `main`, `module`, and `unpkg` at `dist/butterchurn.js`. Published files are limited in the manifest to the main bundle, a minified bundle, and the support script. Build and test commands are defined through Rollup and Jest, including visual regression scripts. Those repository commands are useful to contributors, but the README does not document a consumer-side migration procedure.

The MIT license permits use under its terms, but preset licensing is a separate question. The README credits MilkDrop, Winamp, and multiple preset creators, while `butterchurn-presets` is installed separately. A product owner should inspect the license files and attribution notices for the exact preset collection being shipped rather than assuming that the core package license settles every visual asset question.

MilkDrop Compatibility Versus Native Visualizer Workflows

MilkDrop is the clearest alternative because Butterchurn explicitly identifies itself as a WebGL implementation of it. The original MilkDrop is associated in the README with Ryan Geiss, while Butterchurn packages a browser-facing JavaScript API and a separate preset collection.

The practical distinction is integration rather than a claim about identical output. Butterchurn's documented surface includes ES module imports, an `AudioNode`, a canvas, preset blending duration, renderer resizing, and an explicit `render` call. The README does not state that every MilkDrop preset or plugin will behave identically, so compatibility should not be inferred solely from the project description.

Another choice is using a manually written WebGL visualizer. That approach can give an application direct control over its shaders and buffers, but it requires the developer to build the audio analysis, shader logic, render loop, resizing, and preset system. Butterchurn instead centers its public workflow on preset loading and MilkDrop-style effects. The trade-off is a specialized preset renderer versus a lower-level custom graphics pipeline.

For a quick browser music page, Butterchurn reduces the amount of effect code the host must own. For a product requiring custom effects outside that preset model, the documented library may be the wrong abstraction. The README provides no plugin API, effect authoring guide, or compatibility guarantee for extending its preset format.

Editorial conclusion

Browser developers needing a programmable MilkDrop-style visualizer should first confirm WebGL 2 support, inspect their preset licensing, and verify that the beta package satisfies their deployment requirements. Teams seeking a stable release history or a non-WebGL visualization path should look elsewhere, because Butterchurn has no GitHub releases and its package version remains a beta.

Frequently asked questions

What is Butterchurn used for?

Butterchurn renders audio-reactive, preset-based visualizations in a browser canvas. It is intended for web applications that already have an `AudioContext`, a canvas, and an `AudioNode`.

Does Butterchurn require WebGL 2?

Yes. The README states that Butterchurn requires browser support for WebGL 2 and documents `isButterchurnSupported` as a support check.

How do I install and start Butterchurn?

Install both `butterchurn` and `butterchurn-presets`, create a visualizer with an `AudioContext` and canvas, call `connectAudio`, load a preset, and call `render` for each frame.

Official sources

  1. Issues
  2. jberg/butterchurn on GitHub
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jberg-butterchurn.svg)](https://hysenlabs.com/projects/jberg-butterchurn)

Was this useful?