Tracks & Resolution
Work with resolved and unresolved tracks, and narrow them with type guards.
A Track is playable: it carries the base64 encoded string Lavalink needs. An
UnresolvedTrack only carries search hints — a title, maybe an author, a URI or an ISRC — and turns
into a Track when the player resolves it against a node.
Queue either kind: resolution happens when the track is about to play.
Type guards
TrackResolution groups the guards. The first two narrow the library's own classes; the rest recognise
plain objects coming from Lavalink or from storage.
import { } from 'hoshimi';
import type { , } from 'hoshimi';
declare const : | ;
if (.()) {
.(., ..);
}
if (.()) {
.(..);
}| Guard | True for |
|---|---|
isResolved | a Track instance |
isUnresolved | an UnresolvedTrack instance |
isLavalinkResolved | a plain Lavalink track object with encoded and a requester |
isLavalinkUnresolved | a plain object with info.title and no resolve |
isStoredTrack | a TrackJSON read back from a storage adapter |
Queueing a mix
import type { , , } from 'hoshimi';
declare const : ;
declare const : < | >;
await ..();
if (!.()) {
await .();
}Building an unresolved track
Useful when importing a playlist from somewhere that is not Lavalink: keep the metadata now and pay for the search later, only for the tracks that actually get played.
import { } from 'hoshimi';
import type { } from 'hoshimi';
declare const : ;
const = .(
{
: {
: 'Harder Better Faster Stronger',
: 'Daft Punk',
: 'GBDUW0000059',
},
},
{ : '123', : 'demo-user' },
);
await ..();How resolution picks a track
UnresolvedTrack.resolve() tries, in order:
encoded— decoded directly through the node, no search.info.uri— searched as a URL, first result wins.- A query built from
titleandauthor, then narrowed by author name, then by duration (±1.5s), then by ISRC.
It throws a ResolveError when nothing matches, so a bad import surfaces as a failed play() instead of
a silent skip.
Key Concepts
- Requester travels with the track:
requesteranduserDatasurvive resolution, so whatever you attached at search time is still there when the track plays. queue.utils.build()normalises any of the five shapes above into aTrack; the player calls it for you.- Storage round-trip: tracks saved through a queue adapter come back as
TrackJSON, whichisStoredTrackrecognises andStructures.Trackrehydrates.