Provider

@braccato/provider-blyrics fetches lyrics from several sources in priority order and returns the first usable result. It includes ready-made providers for each endpoint of this API, parses each response with @braccato/parsers, and hands back Lyric[] that you can give straight to the renderer.

Use it when you want fallback across providers (for example, TTML first, then QQ, then Kugou) without writing the fetch, parse and retry logic yourself.

Install

npm i @braccato/provider-blyrics

Quickstart

Create a ProviderChain, register providers, and call fetchLyrics. Each registration has a key, a display name, a sync type and the fetch function.

import {
  ProviderChain,
  createBLyricsProvider,
  createPortatoProvider,
  createLegatoProvider,
} from "@braccato/provider-blyrics";

const chain = new ProviderChain();
chain.register({ key: "ttml", displayName: "TTML", syncType: "syllable", fetch: createBLyricsProvider() });
chain.register({ key: "qq", displayName: "QQ", syncType: "word", fetch: createPortatoProvider() });
chain.register({ key: "kugou", displayName: "Kugou", syncType: "line", fetch: createLegatoProvider() });

const controller = new AbortController();
const result = await chain.fetchLyrics({
  song: "Wanderlust",
  artist: "The Weeknd",
  album: "Kiss Land (Deluxe)",
  duration: 307,
  signal: controller.signal,
});

if (result) {
  view.lyrics = result.lyrics;
}

duration is in seconds, like the API's d parameter. The signal is required and goes in the same object. Aborting it stops the chain.

Built-in providers

Each factory returns a fetch function. Every one accepts apiUrl and timeout options (the timeout defaults to 10 seconds).

Factory Source Format
createBLyricsProvider This API, /getLyrics TTML, syllable-synced
createPortatoProvider This API, /qq/getLyrics QRC, word-level. Passes song and artist to parseQRC to drop title lines
createLegatoProvider This API, /kugou/getLyrics LRC, line-synced
createLRCLibSyncedProvider LRCLib Synced LRC
createLRCLibPlainProvider LRCLib Plain text, unsynced
createBinimumProvider BiniLyrics TTML
createUnisonProvider Unison TTML, LRC or plain text. Matches on videoId when you pass one

You can register your own provider too. A fetch function takes the context object and returns a result, or null when it has nothing.

Order

Without a priority option, the chain tries providers by sync type: syllable, then word, then line, then unsynced. Pass priority to set the order yourself, and disabled to skip some:

const result = await chain.fetchLyrics(context, {
  priority: ["ttml", "kugou", "qq"],
  disabled: new Set(["kugou"]),
});

The chain returns the first result with at least one line. A provider that throws is skipped, and the chain moves on. If no provider has lyrics, fetchLyrics returns null.

Options

Option Description
priority Provider keys in the order to try them
disabled A Set of provider keys to skip
validate Called with each result. Return false to reject it and try the next provider
onProviderResult Called with the key and result (or null) of each provider tried
onProviderError Called with the key and error when a provider throws

Result

Field Description
lyrics The parsed Lyric[]
source, sourceHref A display name and link for the source, for attribution
language The lyrics language, when the source reports one
cacheAllowed Whether the source allows you to cache the result

Validation

To avoid a wrong match, compare the result against text you already have. createSimilarityValidator rejects results whose text is less similar to the reference than the threshold (0 to 1, default 0.5):

import { createSimilarityValidator } from "@braccato/provider-blyrics";

const validate = createSimilarityValidator(referenceText, 0.5);
const result = await chain.fetchLyrics(context, { validate });

One chain per song

The chain caches each provider's result by provider key, not by song. Call chain.clearCache() before you fetch the next song, or create a new chain for each song. Otherwise the chain returns the previous song's lyrics.