Audio API

Provide audio streams for tracks in your Spotube plugin.

The Audio API lets your plugin resolve track metadata into playable audio streams. Include "AUDIO" in plugin.json abilities.

How it works

Spotube calls your API in two stages:

  1. Match: getStreamsByTrack() receives a MetadataTrack and returns a list of possible AudioSource matches, each with a confidence score (0.0–1.0). Spotube picks the best match based on confidence and available quality.

  2. Resolve: If the chosen source is AudioSource.Basic (no stream URL yet), Spotube calls getStreamsOfAudioSource() to fetch the actual stream URLs. The result is AudioSource.Streamed containing AudioStream objects with direct URLs.

AudioFormat

Declare what your provider supports:

data class AudioFormat(
    val codec: String,       // "mp3", "aac", "opus", "flac"
    val container: String,   // "mp3", "mp4", "webm"
    val qualities: List<AudioQuality>,
)

sealed interface AudioQuality {
    data class Lossy(val bitrate: Int) : AudioQuality
    data class Lossless(val sampleRate: Int, val channels: Int) : AudioQuality
}

AudioStream

Each available stream has a URL, codec info, and protocol:

sealed interface AudioStream {
    val url: String
    val codec: String
    val container: String
    val protocol: StreamProtocol    // HLS, DASH, or PROGRESSIVE

    data class Lossy(val bitrate: Int, ...) : AudioStream
    data class Lossless(val sampleRate: Int, val channels: Int, ...) : AudioStream
}

Implementation guide

The key design decision is how you map MetadataTrack to audio sources. Common approaches:

  • Exact ID match: Match the track's ID or ISRC against your audio catalog.
  • Title + artist search: Query your audio provider with title and artist name, rank by confidence.
  • Album + track number: Use album context to narrow matches.

Return multiple AudioSource entries with descending confidence so Spotube can fall back if the first source fails. In getStreamsOfAudioSource(), return the highest-quality stream available for each source.

For a complete working implementation, see the example's RealAudioAPI.

Binding

import dev.krtirtho.plugin_interfaces.plugin_apis.audio.AudioAPI
import dev.krtirtho.plugin_interfaces.plugin_apis.audio.AudioAPI_SERVICE_NAME

zipline.bind<AudioAPI>(AudioAPI_SERVICE_NAME, RealAudioAPI())