use-sound

repository·main·Indexed 25 days ago

https://github.com/joshwcomeau/use-sound

A lightweight React hook for playing sound effects, built on top of the Howler.js audio library. It provides a declarative API to trigger sounds, manage volume, pitch, and playback controls, and supports audio sprites for playing multiple samples from a single file.

Tokens
2.1K
Snippets
9
Records
16
Agent score
84%

What's inside use-sound

  1. Use audio sprites with useSound

    main

    An audio sprite is a single audio file containing multiple sound samples. You can load one file and trigger specific sections by defining a sprite map in the HookOptions.

    A SpriteMap is an object where keys are sound IDs and values are tuples [startTime, duration] in milliseconds.

    Note: When using sprites, the playbackRate parameter is not reactive; only the initial value provided will be used.

    const spriteMap = {
      laser: [0, 300],
      explosion: [1000, 300],
      meow: [2000, 75],
    };
    
    const [play] = useSound('/path/to/sprite.mp3', {
      sprite: spriteMap,
    });
    
    // To play a specific sprite:
    <button onClick={() => play({ id: 'laser' })}>Play Laser</button>
  2. Importing audio files in React

    main

    To use audio files with useSound, you must provide a valid path or URL. How you provide this depends on your build system:

    1. Webpack/Create React App: You can import the file directly. Webpack will resolve it to a dynamic path.
      import mySound from './sound.mp3';
      const [play] = useSound(mySound);
    2. Static Assets: In frameworks like Next.js or Gatsby, place audio files in the public or static folder and use a string path.
      const [play] = useSound('/sounds/sound.mp3');

    Warning: If your audio file URL is loaded asynchronously, you may encounter issues. This package is not intended for async sound paths.

  3. Access the Howl instance via the sound object

    main

    For advanced control not exposed by the hook, useSound returns a sound object, which is a direct instance of Howl. This allows you to call any method available in the Howler API, such as .fade().

    const Arcade = () => {
      const [play, { sound }] = useSound('/win-theme.mp3');
    
      return (
        <button
          onClick={() => {
            // Use the Howl instance directly to fade in the victory theme
            sound.fade(0, 1, 1000);
          }}
        >
          Click to win
        </button>
      );
    };
  4. Access Howler options via HookOptions

    main

    Any option passed to useSound that is not explicitly recognized by the hook is automatically delegated to the underlying Howl instance. You can use this to access the full suite of Howler options, such as onend to trigger a callback when a sound finishes.

    const [play] = useSound('/thing.mp3', {
      onend: () => {
        console.info('Sound ended!');
      },
    });
  5. Use the useSound hook

    main

    The useSound hook is a declarative React hook for playing sound effects. It takes a URL to a sound file and an optional configuration object. It returns a tuple containing a play function and an ExposedData object.

    Basic Usage

    import useSound from 'use-sound';
    import boopSfx from '../../sounds/boop.mp3';
    
    const BoopButton = () => {
      const [play] = useSound(boopSfx);
    
      return <button onClick={play}>Boop!</button>;
    };
  6. Configure useSound with HookOptions

    main

    When initializing useSound, you can pass a HookOptions object to configure the sound behavior. Most of these options are reactive; if they change, the sound effect will immediately reflect those changes.

    NameValueDescription
    volumenumberA value from 0 to 1 (1 is full volume, 0 is muted).
    playbackRatenumberA value from 0.5 to 4. Affects both speed and pitch.
    interruptbooleanIf true, calling play again before the sound ends will truncate the current sound instead of overlapping.
    soundEnabledbooleanUsed to globally mute sounds (e.g., via context or Redux).
    spriteSpriteMapAllows using a single hook for multiple sound effects within one file.
    [delegated]Any additional arguments passed to HookOptions are forwarded to the Howl constructor.

    Note: If a sprite is provided, playbackRate will not be reactive and will only use the initial value.

  7. Understand the useSound return value

    main

    The useSound hook returns a tuple in the format [PlayFunction, ExposedData].

    • The first element is the function used to trigger sounds.
    • The second element is an object containing the sound instance and control methods like stop, pause, and duration.
    type ReturnedValue = [PlayFunction, ExposedData];
  8. Access sound state with ExposedData

    main

    The useSound hook returns an array where the second element is an ExposedData object. This object provides access to the underlying sound instance and control methods.

    Properties and methods:

    • sound: The Howl instance (or null if not loaded).
    • stop: A function to stop the sound. Accepts an optional id (string) to specify a sprite.
    • pause: A function to pause the sound. Accepts an optional id (string) to specify a sprite.
    • duration: The duration of the sound in seconds (or null).
    interface ExposedData {
      sound: Howl | null;
      stop: (id?: string) => void;
      pause: (id?: string) => void;
      duration: number | null;
    }
  9. Play sounds with PlayOptions

    main

    The PlayFunction returned by the hook accepts a PlayOptions object to customize specific playback instances.

    Available options:

    • id: (string) The ID of the sprite to play.
    • forceSoundEnabled: (boolean) Forces the sound to play even if soundEnabled is false in HookOptions.
    • playbackRate: (number) Overrides the global playback rate for this specific play call.
    interface PlayOptions {
      id?: string;
      forceSoundEnabled?: boolean;
      playbackRate?: number;
    }