Project Awesome project awesome

JavaScript: Audio > Waveform Playlist

Multitrack web audio editor and player with canvas waveform preview.

Package 1.6k stars GitHub

Waveform Playlist

A multi-track audio editor and player built with React, Tone.js, and the Web Audio API. Features canvas-based waveform visualization, drag-and-drop clip editing, and professional audio effects.

Waveform Playlist Screenshot

Features

  • Multi-track editing - Multiple clips per track with drag-to-move and trim
  • Waveform visualization - Canvas-based rendering with zoom controls
  • 20+ audio effects - Reverb, delay, filters, distortion, and more via Tone.js
  • Recording - AudioWorklet-based recording with live waveform preview
  • Export - WAV export with effects, individual tracks or full mix
  • Annotations - Time-synced text annotations with keyboard navigation
  • Theming - Full theme customization with dark/light mode support
  • MIDI playback - MIDI file parsing with piano roll visualization and SoundFont sample playback
  • TypeScript - Full type definitions included

Quick Start

npm install @waveform-playlist/browser tone @dnd-kit/react

Note: tone and @dnd-kit/react are peer dependencies and must be installed separately. @dnd-kit/dom and @dnd-kit/abstract are transitive dependencies of @dnd-kit/react.

import { WaveformPlaylistProvider, Waveform, PlayButton, PauseButton, StopButton } from '@waveform-playlist/browser';
import { createTrack, createClipFromSeconds } from '@waveform-playlist/core';

function App() {
  const [tracks, setTracks] = useState([]);

  // Load audio and create tracks
  useEffect(() => {
    async function loadAudio() {
      const response = await fetch('/audio/song.mp3');
      const arrayBuffer = await response.arrayBuffer();
      const audioContext = new AudioContext();
      const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

      const track = createTrack({
        name: 'My Track',
        clips: [createClipFromSeconds({ audioBuffer, startTime: 0 })],
      });

      setTracks([track]);
    }
    loadAudio();
  }, []);

  return (
    <WaveformPlaylistProvider tracks={tracks}>
      <div>
        <PlayButton />
        <PauseButton />
        <StopButton />
      </div>
      <Waveform />
    </WaveformPlaylistProvider>
  );
}

Documentation

Examples

Example Description
Stem Tracks Multi-track playback with mute/solo/volume controls
Effects 20 Tone.js effects with real-time parameter control
Recording Live recording with VU meter and waveform preview
Multi-Clip Drag-and-drop clip editing with trim handles
Annotations Time-synced text with keyboard navigation
Waveform Data Pre-computed peaks for fast loading
MIDI MIDI file playback with piano roll and SoundFont samples
Beats & Bars Tempo-synced timescale with beats and bars ruler
Fades Fade in/out with configurable curves
Stereo Stereo waveform rendering and pan controls
Spectrogram FFT-based spectrogram visualization
Media Element HTMLMediaElement playout with playback rate
Styling Bar width, gaps, gradients, and theme colors
Flexible API Custom playheads, timestamps, and full UI customization

Packages

Package Description
@waveform-playlist/browser Main React components, hooks, and context
@waveform-playlist/core Types, utilities, and clip/track creation
@waveform-playlist/engine Framework-agnostic timeline engine with pure operations
@waveform-playlist/ui-components Styled UI components (buttons, sliders, etc.)
@waveform-playlist/playout Tone.js audio engine
@waveform-playlist/webaudio-peaks Peak extraction from AudioBuffer or sample arrays
@waveform-playlist/loaders Audio loaders

Optional packages:

Package Description
@waveform-playlist/midi MIDI file parsing, piano roll visualization, and SoundFont playback
@waveform-playlist/annotations Time-synced text annotations with drag editing
@waveform-playlist/recording AudioWorklet recording with live waveform preview (requires setup)
@waveform-playlist/worklets Shared AudioWorklet processors for metering and recording (auto-installed with recording)
@waveform-playlist/spectrogram Spectrogram visualization with FFT worker
@waveform-playlist/media-element-playout HTMLMediaElement-based playout with pitch-preserving playback rate

Key Hooks

// Load audio files into tracks
const { tracks, loading, error } = useAudioTracks([
  { src: '/audio/vocals.mp3', name: 'Vocals' },
  { src: '/audio/drums.mp3', name: 'Drums' },
]);

// Playback controls
const { play, pause, stop, seekTo } = usePlaylistControls();

// Playback animation (60fps updates)
const { currentTime, isPlaying } = usePlaybackAnimation();

// Zoom controls
const { zoomIn, zoomOut, samplesPerPixel } = useZoomControls();

// Master effects chain
const { masterEffects, toggleBypass, updateParameter } = useDynamicEffects();

// WAV export
const { exportWav, isExporting, progress } = useExportWav();

// Recording
const { startRecording, stopRecording, isRecording } = useIntegratedRecording();

Web Components (Experimental)

@dawcore/components provides framework-agnostic Web Components for multi-track audio editing — no React required. Built with Lit, adapter-pluggable: choose between @dawcore/transport (native Web Audio) or @waveform-playlist/playout (Tone.js).

npm install @dawcore/components @waveform-playlist/core @waveform-playlist/engine

Audio backend (choose one):

npm install @dawcore/transport          # Native Web Audio (multi-tempo, multi-meter, metronome)
# or
npm install @waveform-playlist/playout tone  # Tone.js (effects, MIDI synths)
<script type="module">
  import '@dawcore/components';
  import { NativePlayoutAdapter } from '@dawcore/transport';

  const editor = document.querySelector('daw-editor');
  const adapter = new NativePlayoutAdapter(new AudioContext());
  editor.adapter = adapter;
</script>

<daw-editor id="editor" clip-headers interactive-clips timescale>
  <daw-track name="Vocals">
    <daw-clip src="/audio/vocals.mp3" start="0" duration="10"></daw-clip>
  </daw-track>
  <daw-keyboard-shortcuts playback splitting undo></daw-keyboard-shortcuts>
</daw-editor>

<daw-transport for="editor">
  <daw-play-button></daw-play-button>
  <daw-pause-button></daw-pause-button>
  <daw-stop-button></daw-stop-button>
  <daw-record-button></daw-record-button>
</daw-transport>

Features:

  • Declarative <daw-track> and <daw-clip> elements with auto-loading
  • Imperative API for programmatic mutation — editor.addTrack/removeTrack/updateTrack/addClip/removeClip/updateClip and editor.ready() for engine bootstrap before any track loads
  • Adapter-pluggable — choose Native Web Audio or Tone.js backend
  • Clip move, trim, and split with collision detection
  • Undo/redo with transaction-based grouping
  • Keyboard shortcuts (Space=play/pause, S=split, Cmd/Ctrl+Z=undo)
  • File drop for adding tracks
  • Recording with overdub and latency compensation
  • Metronome with mixed meters and tempo changes
  • Tempo automation — linear ramps and Möbius-Ease curves with exact integration
  • Pre-computed peaks for fast initial render
  • indefinite-playback attribute fills the viewport when no audio is loaded — ruler renders before any track

Packages:

Package Description
@dawcore/components Lit Web Components for multi-track editing
@dawcore/transport Native Web Audio transport — scheduling, looping, tempo automation, time signatures, metronome

Run the examples locally:

pnpm example:dawcore-native  # Native Web Audio — localhost:5173
pnpm example:dawcore-tone    # Tone.js backend — localhost:5174

dawcore-native example pages:

  • basic.html — Basic playback with timescale and file drop
  • multiclip.html — Multi-clip editing with move, trim, and split
  • programmatic.html — Imperative editor.addTrack / addClip / updateClip / removeClip plus declarative DOM mutation, side-by-side
  • beats-grid.html — Beats & bars grid mode with snap-to-grid
  • beat-map-grid.html — Variable tempo from beat maps with metronome
  • record.html — Recording with overdub
  • metronome.html — Metronome with mixed meters, tempo presets, and looping sequences
  • automation.html — Tempo automation with step, linear, and curve presets
  • analyser.html — Spectrum analyser connected to master output

dawcore-tone example pages:

  • basic.html — Basic playback with Tone.js adapter
  • multiclip.html — Multi-clip editing with Tone.js
  • programmatic.html — Imperative editor.addTrack / addClip / updateClip / removeClip plus declarative DOM mutation, with the Tone.js adapter
  • beats-grid.html — Beats & bars grid with Tone.js
  • record.html — Mic recording with overdub
  • analyser.html — Spectrum analyser connected to master output

Spec & roadmap: docs/specs/web-components-migration.md — full element catalogue, attribute/property/event tables, programmatic API contracts, theming tokens, and migration phases.

Browser Support

Requires Web Audio API support: Chrome, Firefox, Safari, Edge (modern versions).

See Can I Use: Web Audio API

Development

# Install dependencies
pnpm install

# Start dev server
pnpm website

# Run tests
pnpm test

# Build all packages
pnpm build

Visit http://localhost:3000/waveform-playlist to see the examples.

Books

Currently writing: Mastering Tone.js

Mastering Tone.js

Credits

Originally created for the Airtime project at Sourcefabric.

License

MIT License

Sponsors

Moises.ai

Become a sponsor

Partners

Télécom Paris

Back to Game Engine Development