YurbaAP

YurbaAudioPlayer

Minimal, zero-dependency audio player supporting dynamic playlists with auto-advance, smart playback persistence via LocalStorage, flexible speed cycling, and custom action buttons.

Usage
<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

Events will appear here…

API

All public methods available on the <yurba-ap> element instance.

create
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 keyTypeDefaultDescription
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),
        },
    ],
})
The returned element is already in the DOM. You can call .setTrack() / .play() on it immediately.
setTrack
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 fieldTypeDescription
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.
Any extra fields on the track object are preserved and accessible via 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
})
play
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.

pause
player.pause()

Pauses the current audio. Updates the play button icon to play. Fires yurba-ap.pause. No-op if no track is loaded.

togglePlay
const isPlaying = player.togglePlay()

Toggles between play and pause. Returns true if now playing. No-op if no track is loaded.

isPaused
const paused = player.isPaused()

Returns true if the audio is paused or no track has been loaded yet.

Playlist

The playlist is an object keyed by numeric index. When a track ends, the player automatically advances to the next index and calls play().

MethodDescription
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.

Overview
EventDescription
yurba-ap.set_trackA new track was loaded via setTrack().
yurba-ap.playPlayback started.
yurba-ap.pausePlayback paused.
yurba-ap.endedCurrent track ended. Playlist advances automatically if available.
yurba-ap.playlist_endReached the end of the playlist.
yurba-ap.progressPlayback position updated (fires on timeupdate).
yurba-ap.volumeVolume changed by the user.
yurba-ap.speedPlayback speed changed.
yurba-ap.set_track

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)
})
yurba-ap.play

Fired when playback starts — via the play button, play(), or togglePlay().

player.addEventListener('yurba-ap.play', (e) => {
    console.log('playing:', e.track.title)
})
yurba-ap.pause

Fired when playback is paused — via the play button, pause(), or togglePlay().

player.addEventListener('yurba-ap.pause', (e) => {
    console.log('paused:', e.track.title)
})
yurba-ap.ended

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)
})
yurba-ap.playlist_end

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

Hiding controls

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,
    }
})
KeyDefaultDescription
volume true Toggle the volume icon and its slider popup.
speed true Toggle the playback speed label and its slider popup.
CSS variables

The player defines its own CSS variables on the yurba-ap element with sensible defaults. Override them on the element or any parent.

VariableDefaultDescription
--y-ap-bg#ffffffPlayer background color.
--y-ap-text#1c1c1eText and icon color.
--y-ap-mutedrgba(0,0,0,0.4)Secondary text and icon color.
--y-ap-accent#4e7cffAccent color: slider fill and active state.
--y-ap-trackrgba(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);
}