Audio Player

PreviousNext

A customizable audio player with progress controls and playback management for music, podcasts, and voice content.

Installation

pnpm dlx @elevenlabs/cli@latest components add audio-player

Usage

import {
  AudioPlayerButton,
  AudioPlayerDuration,
  AudioPlayerProgress,
  AudioPlayerProvider,
  AudioPlayerSpeed,
  AudioPlayerSpeedButtonGroup,
  AudioPlayerTime,
  useAudioPlayer,
  useAudioPlayerTime,
} from "@/components/ui/audio-player"

Basic Player

<AudioPlayerProvider>
  <div className="flex items-center gap-4">
    <AudioPlayerButton />
    <AudioPlayerProgress className="flex-1" />
    <AudioPlayerTime />
    <span>/</span>
    <AudioPlayerDuration />
  </div>
</AudioPlayerProvider>

Playing a Specific Track

const track = {
  id: "track-1",
  src: "/audio/song.mp3",
  data: { title: "My Song", artist: "Artist Name" }
}
 
<AudioPlayerProvider>
  <AudioPlayerButton item={track} />
  <AudioPlayerProgress />
</AudioPlayerProvider>

Multiple Tracks

const tracks = [
  { id: "1", src: "/audio/track1.mp3", data: { title: "Track 1" } },
  { id: "2", src: "/audio/track2.mp3", data: { title: "Track 2" } },
  { id: "3", src: "/audio/track3.mp3", data: { title: "Track 3" } },
]
 
<AudioPlayerProvider>
  <div className="space-y-4">
    {tracks.map((track) => (
      <div key={track.id} className="flex items-center gap-4">
        <AudioPlayerButton item={track} />
        <span className="text-sm">{track.data.title}</span>
      </div>
    ))}
    <AudioPlayerProgress className="w-full" />
    <div className="flex gap-2 text-sm">
      <AudioPlayerTime />
      <span>/</span>
      <AudioPlayerDuration />
    </div>
  </div>
</AudioPlayerProvider>

API Reference

AudioPlayerProvider

The provider component that manages audio state and playback. Must wrap all audio player components.

<AudioPlayerProvider>{children}</AudioPlayerProvider>

AudioPlayerButton

A play/pause button that controls playback. Shows a loading spinner when buffering.

Props

PropTypeDescription
itemAudioPlayerItem<TData>Optional. The audio item to play. If not provided, controls the current track
...propsButtonPropsAll standard Button component props

AudioPlayerItem Type

interface AudioPlayerItem<TData = unknown> {
  id: string | number
  src: string
  data?: TData
}

AudioPlayerProgress

A slider that shows playback progress and allows seeking. Pauses during seeking and resumes after.

Props

PropTypeDescription
...propsSliderPropsAll Radix UI Slider props except min, max, and value

AudioPlayerTime

Displays the current playback time in formatted time (e.g., "1:30").

Props

PropTypeDescription
classNamestringOptional CSS classes
...propsHTMLSpanElementAll standard span element props

AudioPlayerDuration

Displays the total duration of the current track or "--:--" when unavailable.

Props

PropTypeDescription
classNamestringOptional CSS classes
...propsHTMLSpanElementAll standard span element props

AudioPlayerSpeed

A dropdown menu button (with settings icon) for controlling playback speed. Displays "Normal" for 1x speed and shows other speeds with "x" suffix (e.g., "0.5x", "1.5x").

Props

PropTypeDefaultDescription
speedsreadonly number[][0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]Available playback speeds
variantButtonVariant"ghost"Button variant
sizeButtonSize"icon"Button size
...propsButtonProps-All standard Button component props

Example

<AudioPlayerSpeed variant="ghost" size="icon" />

AudioPlayerSpeedButtonGroup

A button group component for quick playback speed selection.

Props

PropTypeDefaultDescription
speedsreadonly number[][0.5, 1, 1.5, 2]Available playback speeds
classNamestring-Optional CSS classes
...propsHTMLDivElement-All standard div element props

Example

<AudioPlayerSpeedButtonGroup speeds={[0.5, 0.75, 1, 1.5, 2]} />

useAudioPlayer Hook

Access the audio player context to control playback programmatically.

const {
  ref, // RefObject<HTMLAudioElement>
  activeItem, // Current playing item
  duration, // Track duration in seconds
  error, // MediaError if any
  isPlaying, // Playing state
  isBuffering, // Buffering state
  playbackRate, // Current playback speed
  isItemActive, // Check if an item is active
  setActiveItem, // Set the active item
  play, // Play audio
  pause, // Pause audio
  seek, // Seek to time
  setPlaybackRate, // Change playback speed
} = useAudioPlayer<TData>()

Example Usage

function PlaylistController() {
  const { play, pause, isPlaying, activeItem } = useAudioPlayer()
 
  const handlePlayNext = () => {
    const nextTrack = getNextTrack(activeItem?.id)
    if (nextTrack) {
      play(nextTrack)
    }
  }
 
  return <button onClick={handlePlayNext}>Next Track</button>
}

useAudioPlayerTime Hook

Get the current playback time (updates every frame using requestAnimationFrame).

const time = useAudioPlayerTime() // Current time in seconds

Example Usage

function CustomTimeDisplay() {
  const time = useAudioPlayerTime()
  const { duration } = useAudioPlayer()
 
  const percentage = duration ? (time / duration) * 100 : 0
 
  return <div>Progress: {percentage.toFixed(1)}%</div>
}

Advanced Examples

Player with Speed Control

function AudioPlayerWithSpeed() {
  return (
    <AudioPlayerProvider>
      <div className="flex items-center gap-4">
        <AudioPlayerButton />
        <AudioPlayerTime />
        <AudioPlayerProgress className="flex-1" />
        <AudioPlayerDuration />
        <AudioPlayerSpeed />
      </div>
    </AudioPlayerProvider>
  )
}

Custom Controls

function CustomAudioPlayer() {
  const { play, pause, isPlaying, seek, duration, setPlaybackRate } =
    useAudioPlayer()
 
  return (
    <div className="space-y-4">
      <button onClick={() => (isPlaying ? pause() : play())}>
        {isPlaying ? "Pause" : "Play"}
      </button>
 
      <button onClick={() => seek(0)}>Restart</button>
 
      <button onClick={() => duration && seek(duration * 0.5)}>
        Jump to 50%
      </button>
 
      <button onClick={() => setPlaybackRate(1.5)}>Speed 1.5x</button>
    </div>
  )
}

Error Handling

function AudioPlayerWithError() {
  const { error, activeItem } = useAudioPlayer()
 
  if (error) {
    return (
      <div className="text-red-500">
        Failed to load: {activeItem?.src}
        <br />
        Error: {error.message}
      </div>
    )
  }
 
  return <AudioPlayerButton />
}

Notes

  • The audio player uses the HTML5 audio element under the hood
  • Progress updates are synchronized using requestAnimationFrame for smooth UI updates
  • The player handles buffering states and network errors automatically
  • Space bar triggers play/pause when the progress slider is focused
  • The component includes TypeScript support with generic data types
  • Audio state is managed globally within the provider context
  • Playback speed displays "Normal" for 1x speed and numerical values (e.g., "0.5x", "1.5x") for other speeds
  • Playback speed is preserved when switching between tracks