Getting Started

DancingPluginSdk provides type definitions, lifecycle contracts, and audio data interfaces for building visualizer plugins that run inside the DancingMusic host application.

Install

npm install @musicdance/plugin-sdk

Basic usage

import type { DancePlugin, AudioData } from '@musicdance/plugin-sdk';

const myPlugin: DancePlugin = {
  config: {
    id: 'my-visualizer',
    name: 'My Visualizer',
    description: 'A custom visualizer plugin',
    author: 'Your Name',
    version: '1.0.0',
    category: 'abstract',
    price: 0,
  },
  init(canvas) { /* set up rendering context */ },
  render(audioData, deltaTime, isPlaying) { /* draw frame */ },
  dispose() { /* release resources */ },
};

Plugin Lifecycle

Every plugin follows a strict lifecycle managed by the host:

  1. init(canvas)Called once when the plugin is activated. Store a reference to the canvas and set up your rendering context (Canvas 2D, WebGL, Three.js).
  2. resize(width, height)Called when the canvas dimensions change. Optional.
  3. render(audioData, deltaTime, isPlaying)Called every animation frame (~60 fps). Draw your visualization using the real-time audio data.
  4. dispose()Called when the plugin is switched out. Release all resources.

Optional hooks:

  • updateSettings(settings)Called when the user changes plugin settings via the UI.
  • setAudioSource(audioContext, sourceNode)Called when the Web Audio graph becomes available.

Example Plugin

A minimal spectrum bar visualizer:

import type { DancePlugin } from '@musicdance/plugin-sdk';
let ctx: CanvasRenderingContext2D | null = null;

export const spectrumBars: DancePlugin = {
  config: {
    id: 'spectrum-bars', name: 'Spectrum Bars',
    description: 'Simple frequency bar chart',
    author: 'Demo', version: '1.0.0',
    category: 'abstract', price: 0,
  },
  init(canvas) { ctx = canvas.getContext('2d'); },
  render(audio, dt, playing) {
    if (!ctx) return;
    const { width: w, height: h } = ctx.canvas;
    ctx.clearRect(0, 0, w, h);
    const bars = audio.frequencyData.length;
    const barW = w / bars;
    for (let i = 0; i < bars; i++) {
      const barH = (audio.frequencyData[i] / 255) * h;
      ctx.fillStyle = `hsl(${i / bars * 240}, 80%, 55%)`;
      ctx.fillRect(i * barW, h - barH, barW - 1, barH);
    }
  },
  dispose() { ctx = null; },
};

DancePlugin

The core plugin interface. Every plugin must implement this.

MethodSignatureDescription
init(canvas: HTMLCanvasElement) => voidSet up rendering context
render(audioData, deltaTime, isPlaying) => voidDraw one frame (~60 fps)
dispose() => voidRelease all resources
resize(width, height) => voidHandle canvas resize optional
updateSettings(settings) => voidReact to user config changes optional
setAudioSource(ctx, node) => voidAccess Web Audio graph optional

DancePluginConfig

Static metadata and configurable settings for a plugin.

FieldTypeDescription
idstringUnique identifier (kebab-case)
namestringDisplay name
descriptionstringShort description
authorstringAuthor name
versionstringSemVer version string
category'abstract' | 'particle' | 'geometric' | 'nature' | 'other'Plugin category
pricenumberPrice (0 = free)
thumbnailstringPreview image URL optional
settingsRecord<string, Setting>User-configurable parameters optional

Settings types

Each setting supports type: 'number' | 'boolean' | 'color' | 'select' with label, default, and optional min/max/options.

AudioData

Real-time audio analysis data passed to render() every frame.

FieldTypeDescription
frequencyDataUint8ArrayFull frequency spectrum (0–255 per bin)
timeDomainDataUint8ArrayTime-domain waveform
bassLevelnumberLow-frequency energy (0–1)
midLevelnumberMid-frequency energy (0–1)
trebleLevelnumberHigh-frequency energy (0–1)
volumenumberOverall volume (0–1)
energynumberNon-linear energy curve (0–1)
beatDetectedbooleanTrue when a beat is detected
bpmnumberEstimated BPM (0 if not computed)
bassChangenumberBass change rate (-1 to 1)
volumeChangenumberVolume change rate (-1 to 1)

PluginRegistry

Types for the remote plugin registry endpoint.

PluginRegistryEntry

FieldTypeDescription
idstringPlugin identifier
bundleUrlstringURL of the ESM plugin bundle
sdkVersionstringSDK version range (semver)
checksumSha256stringBundle integrity hash optional
tagsstring[]Searchable tags optional
publishedAtstringISO date string optional

PluginRegistry wraps an array of entries with version and updatedAt.

createEmptyAudioData()

Returns a zeroed-out AudioData object. Useful for rendering in paused/idle state, or for unit tests.

import { createEmptyAudioData } from '@musicdance/plugin-sdk';

const idle = createEmptyAudioData();
plugin.render(idle, 0.016, false);