npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-visual-audio

v1.1.0

Published

<div align="center"> <img src="./docs/logo.gif"> </div>

Downloads

17

Readme

Introduction

Audio Visualizers are graphics representation of audio frequency data, creating beautiful and whimsical variations 🧙‍♂️

This library provides a beautiful, lightweight and extremely customizable AudioVisualizer component, used to represent any html audio source you wish.

Installation

If you just want to edit the code and / or play around with storybook:

git clone https://github.com/saverioscagnoli/react-visual-audio

cd react-visual-audio

This package uses the yarn package manager:

yarn install

To start storybook:

yarn storybook

Installation using popular package managers:

npm i react-visual-audio

yarn add react-visual-audio

pnpm add react-visual-audio

bun install react-visual audio

Usage

import { useState, useMemo } from "react";
import { AudioVisualizer, AudioState } from "react-visual-audio";

const AudioPreview = () => {
  const [src, setSrc] = useState<string | null>(null);
  const [audioState, setAudioState] = useState<AudioState>("unset");

  const playOrResume = () => {
    setAudioState("playing");
  };

  const pause = () => {
    setAudioState("pause");
  };

  const disabled = useMemo(
    () => ["unset", "loading"].includes(audioState),
    [audioState]
  );

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
      <div style={{ display: "flex", flexDirection: "column", gap: "0.5" }}>
        <button disabled={disabled} onClick={playOrResume}>
          play
        </button>
        <button disabled={disabled} onClick={pause}>
          pause
        </button>
      </div>

      <AudioVisualizer
        src={src}
        audioState={audioState}
        onAudioStateChange={setAudioState}
        barHeight={defaultHeight => defaultHeight / 2}
        barWidth={(canvasWidth, bufferLength) => canvasWidth / bufferLength}
        barColor={(barHeight, bufferLength, index) =>
          `rgb(${barHeight}, ${bufferLength}, ${index})`
        }
      />
    </div>
  );
};

This is a setup for a simple usage. You can tweak the values and play around with it.

Documentation

The types of this packages only come from the src/types.ts file.

/**
 * The possible states of the audio source
 *
 * unset: The audio src is not set
 * loading: The audio src is being loaded
 * pending: The audio src is loaded and ready to play
 * paused: The audio src is paused
 * playing: The audio src is playing
 * ended: The audio src has ended
 */
type AudioState = "unset" | "loading" | "pending" | "paused" | "playing" | "ended";

/**
 * The possible arguments for the width of the bars
 * This could be a fixed number, or a function can be passed with the canvasWidth and
 * the buffer length, so it can be setted programmatically.
 */
type CustomBarWidthArg =
  | ((canvasWidth: number, bufferLength: number) => number)
  | number;

/**
 * The possible arguments for the height of the bars
 * This is a function that must return the actual number.
 * Note: this function gets called for each bar in the visualizer.
 */
type CustomBarHeightArg = (
  defaultHeight: number,
  bufferLength: number,
  index: number
) => number;

/**
 * The possible arguments for the color of the bars
 * This could be a CanvasGradient, CanvasPattern or a string.
 * Or it could be function that must return a CanvasGradient, CanvasPattern or a string.
 */
type CustomBarColorArg =
  | ((
      barHeight: number,
      bufferLength: number,
      index: number
    ) => string | CanvasGradient | CanvasPattern)
  | (string | CanvasGradient | CanvasPattern);

type CustomDrawFunctionArgs = {
  /**
   * The width of the canvas where the visualizer is drawn
   */
  canvasWidth: number;

  /**
   * The height of the canvas where the visualizer is drawn
   */
  canvasHeight: number;

  /**
   * The width of each bar of the visualizer
   */
  barWidth: number;

  /**
   * The height of each bar of the visualizer
   */
  barHeight: number;

  /**
   * The length of the buffer
   */
  bufferLength: number;

  /**
   * The default x of the canvas
   */
  x: number;

  /**
   * The index of the currently drawn bar
   */
  index: number;
};

/**
 * A custom function that defines how each bar is drawn.
 * Note: this function gets called for each bar in the visualizer.
 * @param ctx The canvas context
 * @param args The necessary args to customize the drawing process
 * @see CustomDrawFunctionArgs
 */
type CustomDrawFunction = (
  ctx: CanvasRenderingContext2D,
  args: CustomDrawFunctionArgs
) => void;

type AudioVisualizerProps = ComponentPropsWithoutRef<"canvas"> & {
  /**
   * The source of the audio to visualize
   */
  src: string;

  /**
   * The current state of the audio source
   * @default "unset"
   * @see AudioState
   */
  audioState?: AudioState;

  /**
   * A callback that is called when the audio source changes state
   *
   * @param audioState The new state of the audio source
   * @example
   * ```tsx
   * const [audioState, setAudioState] = useState<AudioState>("unset");
   *
   * <AudioVisualizer
   *  src={src}
   *  audioState={audioState}
   *  onAudioStateChange={setAudioState}
   * />
   * ```
   */
  onAudioStateChange?: (audioState: AudioState) => void;

  /**
   * The interval in milliseconds at which the time elapesed is updated
   *
   * @default 1000
   * @example
   * ```tsx
   * <AudioVisualizer
   *  src={src}
   *  timeFactor={100}
   *  onTimeChange={time => console.log(time)} // This will log every 0.1 seconds
   * />
   * ```
   */
  timeFactor?: number;

  /**
   * Callback that is called when the time elapsed changes.
   *
   * @param time The current time elapsed in seconds
   */
  onTimeChange?: (time: number) => void;

  /**
   * Whether the audio should start playing as soon as it is loaded
   */
  autoStart?: boolean;

  /**
   * Whether the audio should loop
   */
  loop?: boolean;

  /**
   * The volume of the audio source
   * It should be a number between 0 and 1, error will be thrown otherwise
   *
   * @default 1
   * @example
   * ```tsx
   * const [volume, setVolume] = useState(1);
   *
   * <AudioVisualizer
   *  src={src}
   *  volume={volume}
   * />
   */
  volume?: number;

  /**
   * The number of frames to skip before updating the visualizer
   * This is used to save performance.
   * The higher the number, the less frequent the visualizer updates
   */
  stagger?: number;

  /**
   * The size of the Fast Fourier Transform (FFT) to use.
   * It should be a power of 2 between 32 and 32768
   * @see https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/fftSize
   *
   * @default 2048
   */
  fftSize?: number;

  /**
   * The speed at which the audio should play
   *
   * @default 1
   */
  playbackRate?: number;

  /**
   * The width of the bars. This could be a fixed number, or a function can be passed with the canvasWidth and
   * the buffer length, so it can be setted programmatically.
   *
   * @see CustomBarWidthArg
   * @default (canvasWidth, freqLength) => canvasWidth / freqLength
   */
  barWidth?: CustomBarWidthArg;

  /**
   * The height of each bar. This is a function that must return the actual number.
   * Note: this function gets called for each bar in the visualizer.
   *
   * @param defaultHeight The default height of the bar.
   * @param bufferLength The length of the audio buffer
   * @param index The index of the currently drawn bar
   * @returns The new bar height
   */
  barHeight?: CustomBarHeightArg;

  /**
   * The color of each bar.
   * This could be a CanvasGradient, CanvasPattern or a string.
   * Or it could be function that must return a CanvasGradient, CanvasPattern or a string.
   * Note: this function gets called for each bar in the visualizer.
   * @param barHeight The height of the bar.
   * @param bufferLength The length of the audio buffer
   * @param index The index of the currently drawn bar.
   * @returns The new bar color
   */
  barColor?: CustomBarColorArg;

  /**
   * The padding between each bar
   */
  spaceBetweenBars?: number;

  /**
   * This is a custom function that defines how each bar is drawn.
   * Note: this function gets called for each bar in the visualizer.
   *
   *
   * @param ctx The canvas context
   * @param args The necessary args to customize the drawing process
   * @see CustomDrawFunctionArgs
   *
   * @default (ctx, { x, canvasHeight, barWidth, barHeight }) => ctx.fillRect(x, canvasHeight - barHeight, barWidth, barHeight);
   */
  customDrawFunction?: CustomDrawFunction;

  /**
   * Callback that is called when the audio source is loaded
   *
   * @param audio The audio element
   */
  onSourceLoaded?: (audio: HTMLAudioElement) => void;

  /**
   * Callback that is called when the audio source is paused
   *
   * @param audio The audio element
   */

  onSourceEnded?: (audio: HTMLAudioElement) => void;

  /**
   * Callback that is called when the audio source is paused
   *
   * @param audio The audio element
   */
  onSourcePaused?: (audio: HTMLAudioElement) => void;

  /**
   * Callback that is called when the audio source is playing
   *
   * @param audio The audio element
   */
  onSourcePlaying?: (audio: HTMLAudioElement) => void;

  /**
   * A ref to the canvas element
   */
  canvasRef?: RefObject<HTMLCanvasElement | null>;
};

License

MIT License © Saverio Scagnoli 2024.