Attribute Source
An AttributeSource is the plugin component that enriches tracks, artists, and albums with metadata. It is called after a track is indexed and whenever an attribute task is run.
Registration
ctx.registerAttributeSource({
id: "my-source",
enable(apiCtx) {
/* register attribute definitions */
},
getName() {
return "My Attribute Source";
},
async getTrackAttributeValues(helper) {
/* return metadata */
},
async getArtistAttributeValues(helper) {
/* return metadata */
},
async getAlbumAttributeValues(helper) {
/* return metadata */
},
});
Interface
enable(apiCtx)
Called once when the source is registered. Use the AttributeSourceApiContext to declare the attributes your source will produce:
enable(apiCtx) {
apiCtx.registerTrackAttributes([
{ key: "title", type: "string", supportsMultiple: false },
{ key: "genre", type: "string", supportsMultiple: true },
{ key: "front", type: "buffer", supportsMultiple: false },
]);
apiCtx.registerArtistAttributes([
{ key: "name", type: "string", supportsMultiple: false },
]);
apiCtx.registerAlbumAttributes([
{ key: "title", type: "string", supportsMultiple: false },
{ key: "front", type: "buffer", supportsMultiple: false },
]);
}
Declaring attributes here makes them available as filter targets in users/Playlists and users/Search if the currently configured search source supports it. an attribute source cannot return any attributes that it hasn't registered.
getTrackAttributeValues(helper)
Called for each track during attribution. Returns a TrackMetadata object:
async getTrackAttributeValues(helper) {
const identity = await helper.getIdentity("my-identifier", null);
if (!identity) {
return { attributes: null, artists: null };
}
const data = await fetchFromMyApi(identity.identity);
return {
attributes: [
{ key: "title", value: data.title },
{ key: "genre", value: data.genre },
],
artists: [
{
pluginId: null,
identityId: "my-artist-identifier",
identity: data.artistId,
attributes: [{ key: "name", value: data.artistName }],
},
],
};
}
The TrackAttributionHelper gives you:
| Method | Purpose |
|---|---|
getIdentity(id, pluginId) |
Get an identity produced by a named users/Identifiers |
getCompletedAttributeKeys() |
Keys already filled by earlier sources - lets you skip redundant lookups |
getTrackUuid() |
The server's internal UUID for this track |
getPluginId() / getLibraryId() / getTrackId() |
The track's library coordinates |
getAudioProducer() |
Access the raw audio (for reading embedded tags, etc.) |
getArtistAttributeValues(helper) / getAlbumAttributeValues(helper)
Same pattern. The ArtistInformationHelper and AlbumInformationHelper provide getIdentity() and their respective UUID getter.
Attribute types
See users/Attributes for the full type list. Buffer attributes (type: "buffer") carry binary data:
{ key: "front", value: { extension: "jpg", buffer: imageBuffer } }
// or lazy:
{ key: "front", value: { extension: "jpg", buffer: async () => fetchImage() } }
Source ordering
All registered attribute sources run in registration order for each entity. Later sources see which keys are already filled via getCompletedAttributeKeys() but cannot read the values set by earlier sources. Attribute values are preserved per-plugin and per-attribute source, so two attribute sources can safely register and populate attributes with the same key.
In the event that there are multiple definitions for the same attribute key, you can select which source should take priority in Settings → Attribute Sources.
Related pages
- users/Attributes — user-facing explanation and type reference
- users/Identifiers — producing the identities that attribute sources rely on
- development/Plugin-Development — plugin entry point and SDK overview