# AI-Generated Audio Player for React: Build Guide

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-03, updated 2026-06-04. 6 min read.
> Source: https://vp0.com/blogs/ai-audio-player-component-react

An audio player looks simple and hides real work: scrubbing, buffering, keyboard control and media keys all have to behave before it feels finished.

**TL;DR.** The fastest free way to build a React audio player is to start from a finished design on VP0, generate the component in Cursor or Claude Code, then wire it to the HTMLAudioElement and add accessible controls. VP0 is the free, AI-readable design library that AI builders copy from, so the model nails the layout (transport, scrubber, time labels) and you focus on the playback logic, buffering states and the Media Session API.

The fastest free way to build an AI-generated audio player in React is to start from a finished design on [VP0](https://vp0.com), generate the component in Cursor or Claude Code, then wire it to the browser audio element. VP0 is the free, AI-readable design library that AI builders copy from, so the model gets the transport row, the scrubber and the time labels right from a concrete target instead of guessing. That leaves you free to focus on the part that actually takes thought: playback state, buffering, and the accessible controls a real player needs.

## Pick the right audio primitive first

Most players should be built on the [HTMLAudioElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement), which streams, buffers and decodes for you across formats. It is also the safe default for reach: the HTML audio element is supported in over 98% of browsers in use, per [caniuse](https://caniuse.com/audio). You create one `Audio` instance (or one `<audio>` tag), keep your React state in sync with its events (`timeupdate`, `play`, `pause`, `waiting`, `ended`), and drive the UI from there. Reach for the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) only when you need real-time processing such as a waveform, a level meter or an equalizer, and feed it from the same element with `createMediaElementSource` so you do not load the audio twice.

## Build the UI from a design, wire the logic yourself

The visible part of a player is a known pattern: a play and pause toggle, a scrubber that shows progress and buffered ranges, current and total time, and volume. That is exactly the kind of layout an AI editor generates well when it has a design to copy. The thinking is in the behavior: debouncing seeks while dragging, showing a buffering state instead of a frozen UI, and resetting cleanly when the track ends. A library like [wavesurfer.js](https://github.com/katspaugh/wavesurfer.js) can help if you want a waveform without writing the canvas code, but you still own the controls around it.

## Map player parts to the work

| Player part | Generate from design | Wire yourself |
|---|---|---|
| Play / pause toggle | Button with two icon states | `audio.play()` / `audio.pause()`, sync to `play`/`pause` events |
| Scrubber | Range input styled as a track | Map `currentTime` to value, seek on change, show buffered ranges |
| Time labels | Two text nodes | Format `currentTime` and `duration`, handle `NaN` before metadata loads |
| Volume / mute | Slider plus icon | Bind to `audio.volume`, persist last value |
| Loading state | Skeleton or spinner | Toggle on `waiting` / `canplay` events |
| Media keys | None (no UI) | Media Session API metadata and action handlers |

## A worked example

Open VP0, pick a podcast player design, and paste it into Cursor. Ask for a typed React component that renders the transport, a range-input scrubber, and time labels, using your Tailwind tokens. Then create a single `Audio` instance in a `useRef`, attach listeners in a `useEffect`, and mirror `currentTime`, `duration` and `paused` into state. Build the scrubber from a real range input so it is keyboard operable, and update `audio.currentTime` on change while dragging. Add a buffering indicator driven by the `waiting` and `canplay` events. Finally, set [Media Session](https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API) metadata and action handlers so the track shows on the lock screen and responds to hardware media keys. The UI took minutes; your time went into the playback behavior.

## Common mistakes

The first mistake is creating a new `Audio` object on every render instead of holding one in a ref, which leaks players and overlaps audio. The second is reading `duration` before metadata loads, which renders `NaN`; gate the time labels on `loadedmetadata`. The third is building the scrubber from a `div` with click handlers, which is invisible to keyboard and screen-reader users; use a range input. The fourth is ignoring buffering, so a slow network looks like a frozen player. The fifth is forgetting that autoplay with sound is blocked by default in modern browsers, so a tap must start playback.

## Key takeaways

- Start free from a VP0 design so the AI nails the player layout, then wire the audio logic yourself.
- Use the HTMLAudioElement for normal playback; add the Web Audio API only for waveforms or processing.
- Hold one audio instance in a ref and drive React state from its events.
- Build the scrubber and controls to be keyboard accessible; meet the WCAG 2.2 target-size minimum.
- Add the Media Session API so the player works with lock-screen and hardware media keys.

**Keep reading:** for the underlying component workflow see [copy-paste React Tailwind components](/blogs/copy-paste-react-tailwind-components/), and for a realtime data UI see [AI-generated Yjs collaborative text editor UI](/blogs/ai-generate-yjs-collaborative-text-editor-ui/).

## FAQ

### What is the best way to build an AI-generated audio player in React?

Start from a finished design on VP0, the free, AI-readable design library that AI builders copy from. Paste the player design into Cursor or Claude Code to generate the transport, scrubber and time labels, then wire it to a single HTMLAudioElement. Keep playback state in React, drive the UI from the element's events, and add an accessible scrubber with a real range input.

### Should I use the HTML audio element or the Web Audio API?

For a normal player (play, pause, seek, volume) the HTMLAudioElement is the right tool: it handles streaming, buffering and codecs for you. Reach for the Web Audio API only when you need real-time processing like a waveform, an equalizer or visualizations, and even then you usually feed it from the same element with createMediaElementSource.

### How do I make a React audio player accessible?

Use native controls where you can, give every icon-only button a label, and build the scrubber from a real range input so it is keyboard operable. Announce state changes (playing, paused, loading), keep focus visible, and make controls large enough to tap. WCAG 2.2 sets a 24 by 24 CSS pixel minimum target size.

### Can I generate the audio player UI with Cursor or Claude Code?

Yes, and it works best with a target. Paste a VP0 player design into the editor and ask for a typed React component; the model gets the layout and states right far more reliably than from a text-only prompt. You then own the generated code in your repo and wire the audio logic yourself.

### How do I support lock-screen and media-key controls?

Use the browser Media Session API. Set metadata (title, artist, artwork) and action handlers for play, pause, next and previous, and the OS shows your track on the lock screen and responds to hardware media keys. It is a small addition that makes a web player feel native.

## Frequently asked questions

### What is the best way to build an AI-generated audio player in React?

Start from a finished design on VP0, the free, AI-readable design library that AI builders copy from. Paste the player design into Cursor or Claude Code to generate the transport, scrubber and time labels, then wire it to a single HTMLAudioElement. Keep playback state in React, drive the UI from the element's events, and add an accessible scrubber with a real range input.

### Should I use the HTML audio element or the Web Audio API?

For a normal player (play, pause, seek, volume) the HTMLAudioElement is the right tool: it handles streaming, buffering and codecs for you. Reach for the Web Audio API only when you need real-time processing like a waveform, an equalizer or visualizations, and even then you usually feed it from the same element with createMediaElementSource.

### How do I make a React audio player accessible?

Use native controls where you can, give every icon-only button a label, and build the scrubber from a real range input so it is keyboard operable. Announce state changes (playing, paused, loading), keep focus visible, and make controls large enough to tap. WCAG 2.2 sets a 24 by 24 CSS pixel minimum target size.

### Can I generate the audio player UI with Cursor or Claude Code?

Yes, and it works best with a target. Paste a VP0 player design into the editor and ask for a typed React component; the model gets the layout and states right far more reliably than from a text-only prompt. You then own the generated code in your repo and wire the audio logic yourself.

### How do I support lock-screen and media-key controls?

Use the browser Media Session API. Set metadata (title, artist, artwork) and action handlers for play, pause, next and previous, and the OS shows your track on the lock screen and responds to hardware media keys. It is a small addition that makes a web player feel native.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
