Search Deezer and MusicBrainz together; add preview clips
Search
- Albums and songs search Deezer and MusicBrainz at once and merge the
results: duplicates keep the Deezer copy, best word matches first.
Deezer's search misses albums it carries (Death Magnetic) and most game
soundtracks; MusicBrainz finds them
- MusicBrainz secondary types are shown ("Soundtrack", "Live")
- Settings: Deezer + MusicBrainz (default), Deezer only, MusicBrainz only
- Search results show which service they came from
Previews
- Songs and albums get a play button (cards, rows, detail view, editor,
and Deezer search results) for a 30-second Deezer clip; albums play
their most popular track
- Clips are looked up fresh (Deezer URLs expire), cached 10 minutes, and
streamed through Canon with Range support; hidden lists stay private
- Entries from MusicBrainz or added by hand are matched to Deezer on save
so they can preview too
- "Play previews" toggle in Settings → Profile
Tests cover merging and title/artist matching; `-tags live` runs checks
against the real services.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6d92b46130
commit
b09533cc00
20 files changed
+736
-19
No files matched your search
@@ -77,6 +77,7 @@ function profileSection() {
|
||||
const tagline = h("input", { maxlength: 300, value: settings.tagline, placeholder: "A line about you or your taste" });
|
||||
const preview = h("input", { type: "number", min: 0, max: 50, value: settings.previewCount, style: { maxWidth: "120px" } });
|
||||
const notes = h("input", { type: "checkbox", checked: settings.showNotes });
|
||||
const previews = h("input", { type: "checkbox", checked: settings.showPreviews });
|
||||
const save = h("button", { type: "submit", class: "btn btn--primary" }, "Save profile");
|
||||
|
||||
const form = h("form", { class: "stack" },
|
||||
@@ -85,13 +86,14 @@ function profileSection() {
|
||||
field("Tagline", tagline),
|
||||
field("Entries per list on the home page", preview, "Visitors see the full list on each list's page. 0 shows only the heading."),
|
||||
h("label", { class: "check" }, notes, "Show why each entry is ranked where it is"),
|
||||
h("label", { class: "check" }, previews, "Play 30-second previews for songs and albums (from Deezer)"),
|
||||
h("div", { class: "settings-actions" }, save),
|
||||
);
|
||||
form.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const ok = await saveSettings({
|
||||
ownerName: ownerName.value, siteTitle: siteTitle.value, tagline: tagline.value,
|
||||
previewCount: Number(preview.value), showNotes: notes.checked,
|
||||
previewCount: Number(preview.value), showNotes: notes.checked, showPreviews: previews.checked,
|
||||
}, save, "Profile saved");
|
||||
if (ok) {
|
||||
renderAvatar();
|
||||
@@ -304,8 +306,8 @@ function integrationsSection() {
|
||||
}),
|
||||
integration({
|
||||
title: "Music · Songs & Albums", iconName: "disc", category: "album",
|
||||
desc: "No key needed. Deezer has the best cover art and fast search; MusicBrainz is fully open data but slower (1 request/second).",
|
||||
extra: [providerChoice("musicProvider", [["deezer", "Deezer (recommended)"], ["musicbrainz", "MusicBrainz + Cover Art Archive"]])],
|
||||
desc: "No key needed. Searching both finds the most: Deezer has the best art and preview clips, and MusicBrainz covers albums Deezer's search misses plus game and film soundtracks.",
|
||||
extra: [providerChoice("musicProvider", [["both", "Deezer + MusicBrainz (recommended)"], ["deezer", "Deezer only"], ["musicbrainz", "MusicBrainz only"]])],
|
||||
ready: () => true,
|
||||
}),
|
||||
integration({
|
||||
|
||||
Reference in new issue
Block a user