Rooks
HooksUI & Layout

useAudio

Controls an audio element while exposing playback, loading, timing, volume, rate, loop, and error state.

About

useAudio connects a callback ref to an <audio> element and mirrors its media events into React state. Use it when an application needs custom audio controls or media-event callbacks in addition to the element's native controls.

Example

import { useAudio } from "rooks";

export default function AudioPlayer() {
  const [audioRef, audio, controls] = useAudio(
    { preload: "metadata" },
    { onError: (message) => console.error(message) }
  );

  return (
    <section>
      <audio ref={audioRef} src="/example-audio.mp3" controls />
      <p aria-live="polite">
        {audio.hasError
          ? audio.error
          : `${audio.isPlaying ? "Playing" : "Paused"} at ${Math.round(audio.currentTime)} seconds`}
      </p>
      <button type="button" onClick={controls.togglePlay}>
        {audio.isPlaying ? "Pause" : "Play"}
      </button>
      <button type="button" onClick={controls.toggleMute}>
        {audio.isMuted ? "Unmute" : "Mute"}
      </button>
      <label>
        Volume
        <input
          type="range"
          min="0"
          max="1"
          step="0.1"
          value={audio.volume}
          onChange={(event) =>
            controls.setVolume(event.currentTarget.valueAsNumber)
          }
        />
      </label>
    </section>
  );
}

The /example-audio.mp3 path represents an audio asset supplied by the application.

Parameters

Both arguments are optional objects.

OptionTypeDefaultBehavior
autoPlaybooleanfalseSets the element's autoplay property after the ref attaches.
isMutedbooleanfalseInitial muted state and element property.
volumenumber1Initial element volume; supply 0..1 because this assignment is not clamped. Later controls clamp to that range.
playbackRatenumber1Initial browser playback rate; this assignment is not clamped. Later controls clamp to 0.25..4.
loopbooleanfalseInitial loop state.
preload"none" | "metadata" | "auto""metadata"Sets the element's preload hint.

The callbacks object accepts onPlay, onPause, onEnded, onMute, onUnmute, onLoadedMetadata, onLoadStart, onCanPlay, and onWaiting. It also accepts onTimeUpdate(currentTime), onDurationChange(duration), onVolumeChange(volume), onRateChange(rate), and onError(message). Callback identities stay fresh without requiring media listeners to be recreated.

Return value

The hook returns [audioRef, state, controls].

  • audioRef is a callback ref for an HTMLAudioElement.
  • state contains isPlaying, isMuted, volume, currentTime, duration, playbackRate, isLoading, isBuffering, loop, hasError, and optional error.
  • controls contains play, pause, togglePlay, mute, unmute, toggleMute, setVolume, setCurrentTime, setPlaybackRate, seek, fastForward, rewind, and setLoop.

All controls return void. fastForward() and rewind() default to ten seconds. Seeking is clamped between zero and the known duration, so seeking before metadata supplies a duration remains at zero.

Behavior and lifecycle

After the ref attaches, the hook applies the initial element properties and subscribes to the relevant media events. It removes every listener when the element changes or the component unmounts. Native media events are the source of truth for playing, timing, buffering, volume, rate, and error state.

Controls do nothing until an element has attached. play() handles a rejected HTMLMediaElement.play() promise by setting hasError, clearing isPlaying, and calling onError. Media-element error events use the browser error code and message. Other control assignments rely on normal platform behavior; they do not throw errors through the hook.

Compatibility and accessibility

The initial render is server-safe because DOM work begins only after the ref attaches. Autoplay and scripted playback may still be rejected by browser user-activation policies. The hook does not load an audio source or request media permissions.

Keep native controls when possible, give custom controls accessible names, expose failures with an appropriate live region, and provide a transcript for spoken content. See SSR and browser APIs.

  • useVideo provides the smaller video-specific state and control tuple.
  • useMediaRecorder records a supplied media stream.

On this page