JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 314
  • Score
    100M100P100Q85346F
  • License MIT

High-performance audio waveform visualization library for the web. Create customizable, interactive waveform renderers with TypeScript support and zero dependencies.

Package Exports

  • waveform-renderer
  • waveform-renderer/package.json

Readme

๐ŸŽต Waveform Renderer

Waveform Renderer

NPM Version npm downloads License: MIT TypeScript Test Coverage

A high-performance, lightweight TypeScript library for rendering audio waveforms on HTML5 Canvas. Create beautiful, interactive audio visualizations with intelligent caching and advanced performance optimizations.

๐Ÿ“ Table of Contents

โœจ Features

  • ๐ŸŽจ Highly customizable appearance - Full control over colors, dimensions, and visual styling
  • โšก High performance - Intelligent caching system with optimized rendering pipeline
  • ๐Ÿ“ฑ Responsive and touch-friendly - Automatic canvas resizing with HiDPI/Retina support
  • ๐Ÿ”„ Real-time progress updates - Smooth animation and instant feedback
  • ๐ŸŽฏ Interactive seeking - Built-in click-to-seek functionality
  • ๐Ÿ’ช TypeScript-first - Complete type safety with comprehensive interfaces
  • ๐Ÿ“ฆ Zero dependencies - Lightweight with no external dependencies
  • ๐Ÿงช Well tested - 231 unit tests ensuring reliability and stability
  • ๐Ÿ”ง Debug system - Built-in performance monitoring and logging
  • ๐Ÿ’พ Smart caching - Automatic render optimization with intelligent cache management
  • ๐Ÿ—๏ธ Modular architecture - Clean separation of concerns for maintainability

๐Ÿš€ Installation

# npm
npm install waveform-renderer

# pnpm
pnpm add waveform-renderer

# yarn
yarn add waveform-renderer

๐Ÿ“– Quick Start

import { WaveformRenderer, getPeaksFromAudioBuffer } from "waveform-renderer";

// Get your audio buffer (from Web Audio API)
const audioContext = new AudioContext();
const response = await fetch("path/to/audio.mp3");
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

// Extract peaks from the audio buffer
const peaks = getPeaksFromAudioBuffer(audioBuffer, 1000); // 1000 samples

// Create the waveform renderer
const canvas = document.getElementById("waveform") as HTMLCanvasElement;
const waveform = new WaveformRenderer(canvas, peaks, {
  color: "#2196F3",
  backgroundColor: "#E3F2FD",
  progressLine: {
    color: "#1565C0",
  },
});

// Listen to events
waveform.on("seek", progress => {
  console.log(`Seeked to ${progress * 100}%`);
});

โš™๏ธ Configuration Options

WaveformOptions

Option Type Default Description
amplitude number 1 Amplitude multiplier for the waveform
backgroundColor string "#CCCCCC" Background color of the waveform
barWidth number 2 Width of each bar in pixels
borderColor string "#000000" Border color of the bars
borderRadius number 0 Border radius of the bars in pixels
borderWidth number 0 Border width of the bars in pixels
color string "#000000" Color of the waveform bars
gap number 1 Gap between bars in pixels
minPixelRatio number 1 Minimum pixel ratio for rendering
position "bottom" | "center" | "top" "center" Vertical positioning of the waveform
progress number 0 Initial progress (0-1)
smoothing boolean true Whether to apply smoothing to the rendering
progressLine ProgressLineOptions | null {...} Progress line configuration (see below)
debug boolean false Enable debug logging and performance stats

ProgressLineOptions

Option Type Default Description
color string "#FF0000" Color of the progress line
heightPercent number 1 Height of the line as percentage of total height
position "bottom" | "center" | "top" "center" Vertical position of the line
style "solid" | "dashed" | "dotted" "solid" Style of the progress line
width number 2 Width of the line in pixels

๐Ÿ“š API Reference

WaveformRenderer

Constructor

new WaveformRenderer(
  canvas: HTMLCanvasElement,
  peaks: number[],
  options?: Partial<WaveformOptions>
)

Instance Methods

  • setOptions(options: Partial<WaveformOptions>): Updates the waveform options
  • setPeaks(peaks: number[]): Updates the waveform peaks data
  • setProgress(progress: number): Updates the current progress (0-1)
  • setProgressLineOptions(options: Partial<ProgressLineOptions> | null): Updates progress line options
  • setDebug(enabled: boolean): Enable/disable debug mode
  • resetDebugCounters(): Reset debug performance counters
  • setCustomRenderer(renderer?: CustomRenderer): Set a custom rendering function
  • setRenderHooks(hooks: RenderHook): Set custom render hooks for advanced customization
  • clearRenderHooks(): Clear all custom render hooks
  • destroy(): Cleans up and removes the instance

๐ŸŽฏ Events

The waveform renderer emits the following events:

Event Payload Description
renderStart void Emitted when rendering begins
renderComplete void Emitted when rendering is complete
seek number Progress value between 0-1 when user seeks
error Error Error object when an error occurs
destroy void Emitted when the instance is destroyed
ready void Emitted when the waveform is ready
resize { width: number; height: number } New dimensions when canvas is resized
progressChange number New progress value between 0-1

๐Ÿ“ฆ Exports

// Main Component
import { WaveformRenderer } from "waveform-renderer";

// Utility Functions
import { getPeaksFromAudioBuffer } from "waveform-renderer";

// TypeScript Types
import type {
  WaveformOptions,
  ProgressLineOptions,
  WaveformEvents,
  RenderMode,
  CustomRenderer,
  RenderHook,
} from "waveform-renderer";

// Default Configuration
import { DEFAULT_OPTIONS } from "waveform-renderer";

๐Ÿ’ก Examples

Basic Usage

import { WaveformRenderer } from "waveform-renderer";

const canvas = document.getElementById("waveform") as HTMLCanvasElement;
const peaks = [0.1, 0.3, 0.8, 0.4, 0.6, 0.2, 0.9, 0.1]; // Your audio peaks
const waveform = new WaveformRenderer(canvas, peaks);

Custom Styling

const waveform = new WaveformRenderer(canvas, peaks, {
  color: "#2196F3",
  backgroundColor: "#E3F2FD",
  barWidth: 3,
  gap: 2,
  borderRadius: 2,
  progressLine: {
    color: "#1565C0",
    style: "dashed",
    width: 2,
  },
  debug: false,
});

Event Handling with Audio Element

const audio = new Audio("path/to/audio.mp3");
const waveform = new WaveformRenderer(canvas, peaks);

// Sync progress with audio playback
audio.addEventListener("timeupdate", () => {
  const progress = audio.currentTime / audio.duration;
  waveform.setProgress(progress);
});

// Handle seek events
waveform.on("seek", progress => {
  audio.currentTime = progress * audio.duration;
  audio.play();
});

// Listen to other events
waveform.on("ready", () => {
  console.log("Waveform is ready!");
});

waveform.on("resize", ({ width, height }) => {
  console.log(`Canvas resized to ${width}x${height}`);
});

Debug Mode and Performance Monitoring

const waveform = new WaveformRenderer(canvas, peaks, {
  debug: true, // Enable debug mode
});

// Enable/disable debug mode dynamically
waveform.setDebug(true);

// Reset performance counters
waveform.resetDebugCounters();

// Debug information is logged to console when debug mode is enabled

Advanced Customization

Custom Renderer

import type { CustomRenderer } from "waveform-renderer";

const customRenderer: CustomRenderer = {
  render(ctx, cache, options, staticPath) {
    // Your custom rendering logic here
    // Return true if you handled the rendering, false to use default
    return false;
  },
};

waveform.setCustomRenderer(customRenderer);

Render Hooks

import type { RenderHook } from "waveform-renderer";

const hooks: RenderHook = {
  beforeRender: (ctx, cache, options) => {
    // Called before any rendering starts
  },
  afterBackground: (ctx, cache, options) => {
    // Called after background is drawn
  },
  afterProgress: (ctx, cache, options, progress) => {
    // Called after progress line is drawn
  },
  afterComplete: (ctx, cache, options) => {
    // Called when rendering is complete
  },
};

waveform.setRenderHooks(hooks);

Working with Audio Buffers

// Get an AudioBuffer from your audio source
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

// Calculate peaks with custom sample count
const peaks = getPeaksFromAudioBuffer(audioBuffer, 2000);

// Create waveform with calculated peaks
const waveform = new WaveformRenderer(canvas, peaks, {
  color: "#10b981",
  backgroundColor: "#1f2937",
  debug: false,
});

๐Ÿ—๏ธ Architecture

The library follows a modular architecture with clean separation of concerns:

  • Renderer: Main rendering logic and canvas management
  • RenderingEngine: Core drawing operations and optimizations
  • CacheManager: Intelligent caching system for performance
  • DebugSystem: Performance monitoring and logging
  • EventHandler: Event management and user interactions

This architecture ensures:

  • Maintainability: Clear separation of responsibilities
  • Performance: Optimized rendering with intelligent caching
  • Extensibility: Easy to add new features and customizations
  • Testability: Comprehensive unit test coverage (231 tests)

โšก Performance

The library is designed for high performance with several optimizations:

  • Intelligent Caching: Automatic render optimization that prevents unnecessary redraws
  • Efficient Peak Processing: Optimized algorithms for handling large audio datasets
  • Canvas Optimization: Smart canvas management with pixel ratio handling
  • Memory Management: Proper cleanup and resource management
  • Event Debouncing: Optimized event handling to prevent performance bottlenecks

Performance monitoring is available in debug mode to help optimize your implementation.

๐ŸŒ Browser Support

  • Chrome 88+
  • Firefox 78+
  • Safari 14+
  • Edge 88+

The library works in all modern browsers that support Canvas and ES6.

๐Ÿ”ง Development

# Install dependencies
pnpm install

# Run development server with demo
pnpm dev

# Build the library
pnpm build

# Build demo page
pnpm build:webpage

# Run tests
pnpm test

# Run tests with coverage
pnpm test:coverage

# Lint code
pnpm lint

# Type check
pnpm type-check

๐Ÿ’ก Motivation

While wavesurfer.js is an excellent library, we needed a more focused solution. Waveform Renderer was created to be a lightweight alternative that concentrates solely on waveform visualization, eliminating additional features like playback, regions, or spectrograms. This results in:

  • ๐ŸŽฏ Focused scope: Just waveform rendering and interaction
  • ๐Ÿ“ฆ Smaller bundle size: No unnecessary features or dependencies
  • ๐Ÿ’ช TypeScript-first development: Built from the ground up with TypeScript
  • โšก Optimized performance: Intelligent caching and rendering optimizations
  • ๐Ÿ—๏ธ Modern architecture: Clean, testable, and maintainable codebase

Choose Waveform Renderer when you need efficient waveform visualization without the overhead of a full-featured audio library.

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ“„ License

MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgements


Made with โค๏ธ by Andres Alarcon