YurbaAudioPlayer
Minimal, zero-dependency audio player supporting dynamic playlists with auto-advance, smart playback persistence via LocalStorage, flexible speed cycling, and custom action buttons.
<link rel="stylesheet" href="/dist/yurba-ap.min.css">
<script src="/dist/yurba-ap.min.js"></script>
The player is created entirely from JavaScript via the static YurbaAP.create() factory — no HTML markup needed. It appends itself to document.body and returns the element.
const player = YurbaAP.create()
player.setTrack({
title: 'His Theme',
author: 'Toby Fox',
cover: 'https://cdn.yurba.one/photos/4225.jpg',
url: 'https://cdn.yurba.one/musebase/1.mp3',
})
player.play()
Live demo
API
All public methods available on the <yurba-ap> element instance.
const player = YurbaAP.create(config)
Factory method — the only way to create a player. Creates the <yurba-ap> element, appends it to document.body, and returns it.
| Config key | Type | Default | Description |
|---|---|---|---|
icons optional |
object | built-in | Override button icons. Keys: play, volume. Each value is an HTML string. |
controls optional |
object | all visible | Hide built-in controls. Keys: volume, speed. Set to false to hide. |
buttons optional |
array | [] |
Custom buttons appended after the speed label. Each entry: { html, onClick? }. onClick(player, event) is called on click. |
persist optional |
boolean | true |
Save and restore volume, speed, and the last loaded track via localStorage. |
speedSteps optional |
number[] | [0.5, 0.75, 1, 1.25, 1.5, 2] |
Playback speed cycle steps. Clicking the speed label cycles through them in order. |
Minimal — all controls visible, default speed steps, persistence on:
const player = YurbaAP.create()
Full config:
const player = YurbaAP.create({
persist: true,
speedSteps: [0.5, 0.75, 1, 1.25, 1.5, 2],
icons: {
play: '<span class="material-symbols-rounded">play_arrow</span>',
volume: '<span class="material-symbols-rounded">volume_up</span>',
},
buttons: [
{
html: '<span class="material-symbols-rounded">favorite</span>',
onClick: (player, event) => console.log('liked:', player.currentTrack),
},
],
})
.setTrack() / .play() on it immediately.player.setTrack(track)
Loads a new track. Pauses the current audio if any, updates the cover, title, and author display, then creates a new Audio object. Does nothing if the same track reference is passed twice.
| Track field | Type | Description |
|---|---|---|
title required |
string | Track name shown in the player. |
author required |
string | Artist name shown in the player. |
url required |
string | Audio file URL. |
cover optional |
string | Cover image URL. The cover element is hidden when omitted or falsy. |
event.track in event handlers — useful for passing an ID or other metadata.player.setTrack({
title: 'Song title',
author: 'Artist',
cover: 'https://cdn.example.com/cover.jpg',
url: 'https://cdn.example.com/audio.mp3',
id: 42, // extra field, accessible via event.track.id
})
player.play()
Starts playback of the current audio. Updates the play button icon to pause. Fires yurba-ap.play. No-op if no track is loaded.
player.pause()
Pauses the current audio. Updates the play button icon to play. Fires yurba-ap.pause. No-op if no track is loaded.
const isPlaying = player.togglePlay()
Toggles between play and pause. Returns true if now playing. No-op if no track is loaded.
const paused = player.isPaused()
Returns true if the audio is paused or no track has been loaded yet.
The playlist is an object keyed by numeric index. When a track ends, the player automatically advances to the next index and calls play().
| Method | Description |
|---|---|
setPlaylist(playlist) | Replace the playlist with an object { 0: track, 1: track, … }. |
getPlaylist() | Returns the current playlist object. |
pushPlaylist(tracks) | Append an array of track objects to the existing playlist. |
playFirst() | Load and play the track at index 0. |
prevTrack() | Load and play the previous track, if any. |
nextTrack() | Load and play the next track. Fires yurba-ap.playlist_end if already at the last track. |
getPlayingIndex() | Returns the current playlist index. |
setPlayingIndex(i) | Override the current playlist index. |
const tracks = [
{ title: 'First', author: 'Artist', url: '...mp3' },
{ title: 'Second', author: 'Artist', url: '...mp3' },
]
player.pushPlaylist(tracks)
player.playFirst()
player.addEventListener('yurba-ap.playlist_end', () => {
console.log('playlist finished')
})
Events
All events are dispatched as bubbling CustomEvents on the <yurba-ap> element, namespaced under yurba-ap.*. Each event carries an event.track property with the current track object.
| Event | Description |
|---|---|
yurba-ap.set_track | A new track was loaded via setTrack(). |
yurba-ap.play | Playback started. |
yurba-ap.pause | Playback paused. |
yurba-ap.ended | Current track ended. Playlist advances automatically if available. |
yurba-ap.playlist_end | Reached the end of the playlist. |
yurba-ap.progress | Playback position updated (fires on timeupdate). |
yurba-ap.volume | Volume changed by the user. |
yurba-ap.speed | Playback speed changed. |
Fired on the player element when a new track is loaded via setTrack(). The event.track property holds the track object that was passed in.
player.addEventListener('yurba-ap.set_track', (e) => {
console.log('now playing:', e.track.title)
})
Fired when playback starts — via the play button, play(), or togglePlay().
player.addEventListener('yurba-ap.play', (e) => {
console.log('playing:', e.track.title)
})
Fired when playback is paused — via the play button, pause(), or togglePlay().
player.addEventListener('yurba-ap.pause', (e) => {
console.log('paused:', e.track.title)
})
Fired when the current track finishes. After this event, if there is a next track in the playlist, the player automatically loads and plays it. If there is no next track, yurba-ap.playlist_end fires instead.
player.addEventListener('yurba-ap.ended', (e) => {
console.log('track ended:', e.track.title)
})
Fired when playback reaches the end of the playlist — either the last track finishes, or nextTrack() is called while already on the last track. Use this to load more tracks, loop, or show a UI state.
player.addEventListener('yurba-ap.playlist_end', () => {
console.log('playlist finished')
})
Customization
Pass a controls object to YurbaAP.create(). Each key corresponds to a built-in control — set it to false to hide it. Omitted keys default to visible.
const player = YurbaAP.create({
controls: {
volume: false,
speed: false,
}
})
| Key | Default | Description |
|---|---|---|
volume |
true | Toggle the volume icon and its slider popup. |
speed |
true | Toggle the playback speed label and its slider popup. |
The player defines its own CSS variables on the yurba-ap element with sensible defaults. Override them on the element or any parent.
| Variable | Default | Description |
|---|---|---|
--y-ap-bg | #ffffff | Player background color. |
--y-ap-text | #1c1c1e | Text and icon color. |
--y-ap-muted | rgba(0,0,0,0.4) | Secondary text and icon color. |
--y-ap-accent | #4e7cff | Accent color: slider fill and active state. |
--y-ap-track | rgba(0,0,0,0.08) | Unfilled slider track color. |
/* Dark theme example */
yurba-ap {
--y-ap-bg: #1c1c1e;
--y-ap-text: #ffffff;
--y-ap-muted: rgba(255, 255, 255, 0.45);
--y-ap-track: rgba(255, 255, 255, 0.12);
}