01 / Die Geschichte
Warum ich Vynl gebaut habe
Ich besitze mehr als 500 CDs und rund tausend Schallplatten. Ich habe Jahre damit verbracht, diese Sammlung zu digitalisieren. Das Anhören hätte der einfache Teil sein sollen.
So einfach war es nicht. Probleme mit meinem NAS warfen mich bei der Organisation der Bibliothek immer wieder zurück. Zu Beets kam ich jedes Mal zurück. Es verwaltete die Musik gut, aber ich wollte eine Desktop-Oberfläche zum Anhören meiner eigenen Sammlung.
Spotify hat das für mich nicht gelöst. Die Empfehlungen und die Zufallswiedergabe entsprachen selten dem, was ich hören wollte, und ich wollte nicht mehr für einen Dienst bezahlen, wenn ich bereits so viel Musik besass. Ich wollte meine eigenen Alben auswählen, meine eigenen Playlists erstellen und überall hören, wo ich gerade war.
Das war der Grund, warum ich Vynl gegründet habe. KI hat mir beim Aufbau geholfen, aber der Ausgangspunkt war eine Musiksammlung, die ich geniessen wollte.
02 / Das Problem
Eine Musiksammlung braucht eine Oberfläche zum Anhören
Vynl fügt eine Browseroberfläche über Musik hinzu, die auf Ihrem Computer oder einem angeschlossenen NAS gespeichert ist. Sie können Alben und Künstler durchsuchen, Wiedergabelisten erstellen und Ihre Sammlung abspielen, ohne die Audiodaten auf einen Streaming-Dienst hochzuladen.
Ich verwende es mit meinen Sonos-Systemen zu Hause. Ich höre meine Home-Collection auch unterwegs, auch im Urlaub und im Auto. Das ist der Teil, der mir am wichtigsten ist. Die Musik, die ich im Laufe der Jahre gesammelt habe, ist verfügbar, wenn ich sie möchte.
Die Schnittstelle funktioniert auf Desktop- und mobilen Browsern. Für das Fernhören ist weiterhin eine Verbindung zum Server zu Hause erforderlich.
03 / Wie es funktioniert
Beets bleibt der Kern der Musikbibliothek
Die React-Schnittstelle von Vynl stellt eine Verbindung zu Next.js-API-Routen für Bibliotheksoperationen und Wiedergabe her. Die SQLite-Anwendungsdatenbank ist vom Beets-Katalog getrennt. Der Browser verwaltet seine Wiedergabewarteschlange mit Zustand; Sonos-Lautsprecher beziehen den Ton selbst vom Server.
Musikdateien
Lokale Festplatte oder gemountetes NAS. Audiodateien, eingebettete Tags und Grafiken.
Beets-Bibliothek
Import, Tagging und Organisation. Die Bibliotheksdatenbank verfolgt die Sammlung.
Vynl-Anwendungsserver
Next.js-API-Routen für Bibliotheksdurchsuchung, Wiedergabelisten, Bereinigung und Wiedergabe. SQLite speichert Anwendungsdaten über Drizzle.
Browser-Player
React-Schnittstelle mit Wiedergabe- und Warteschlangenstatus, verwaltet durch Zustand.
Sonos-Lautsprecher
Erkennung und Kontrolle über das lokale Netzwerk. Lautsprecher rufen Audio von einer erreichbaren Server-URL ab; FFmpeg konvertiert Formate bei Bedarf.
Bibliotheksbereinigung und Unterstützung bei Wiedergabelisten
Konfigurierte lokale oder Cloud-Modellanbieter helfen bei der Auswertung von Metadaten und der Erstellung von Playlists. Sie sind vom Audiowiedergabepfad getrennt.
Beets eignete sich gut für die Verwaltung meiner Sammlung, also blieb ich dabei. Vynl baut auf dem vorhandenen Katalog auf. Der Beets-Adapter liest die Bibliotheksdatenbank und übernimmt die Metadaten der Titel in Vynls Oberfläche zum Musikhören.
Dazu gehören Künstler, Albumkünstler, Titel- und Disc-Nummern, Zusammenstellungs-Flags, Genres, Aufnahmekennungen und Audioeigenschaften. Der Adapter prüft, ob jede Datei vorhanden ist. Es liest das Albumcover von Beets und greift bei Bedarf auf das in die Audiodatei eingebettete Cover zurück.
Das löst auch ein praktisches Problem beim eigenen Hosting. Ein Musikordner kann auf dem Mac einen anderen Pfad haben als im Container. Die Einstellung BEETS_PATH_REMAP übersetzt diese Pfade, wenn Vynl den Katalog liest. Ein geänderter Einhängepunkt erfordert keine neuen Tags für die Sammlung.
Der Adapter erhält beispielsweise die Compilation-Markierung von Beets, wenn er ein Album für die Anzeige vorbereitet. Dieser Ausschnitt stammt aus der Beets-Adapter. Er ist kein separat ausführbares Skript:
const albumArtist = row.comp
? "Various Artists"
: (row.albumartist || undefined);
const isCompilation = Boolean(row.comp);Housekeeping für eine über Jahre gewachsene Sammlung
Die Housekeeping-Werkzeuge lösen Probleme, die mir in einer grossen Bibliothek begegnen. Manche nutzen Beets direkt. Andere reparieren den Vynl-Katalog oder bearbeiten die Musikdateien. Ihre Auswirkungen unterscheiden sich:
- Metadaten aktualisieren liest Tags und Audioeigenschaften aus den Dateien erneut in Vynl ein, einschliesslich Titelnummern, Dauer, Bitrate und Samplerate.
- Die Funktion zum Laden von Covern ruft den Beets-Befehl
fetchartauf. Die erneute Cover-Suche extrahiert eingebettete Bilder und aktualisiert die Cover-Verweise in Vynl. - "Fehlende Einträge bereinigen" entfernt Vynl-Datensätze, deren Dateien nicht erreicht werden können. Bei einem getrennten NAS kann es so aussehen, als würde Musik fehlen. Überprüfen Sie daher die Bereitstellung, bevor Sie es ausführen.
- Die Split-Album-Reparatur bringt Titel unter einen ausgewählten Albumkünstler. Der Zusammenführungsvorgang kann Dateien in ein Verzeichnis verschieben, Pfade in beiden Katalogen aktualisieren und Beets-Albendatensätze konsolidieren.
- Die Erkennung doppelter Formate findet MP3/M4A-Paare mit übereinstimmendem Album, Titelnummer und Titel. Die Bereinigung behält das ausgewählte Format bei und löscht die andere Datei. Hierbei handelt es sich um einen Metadatenabgleich, nicht um einen Audio-Fingerabdruck-Vergleich oder eine Beurteilung, welche Aufnahme besser klingt.
Wie direkt Beets eingebunden bleibt, zeigt Wartungsprozess. Die Cover-Suche führt dessen bestehenden Befehl aus:
const { stdout } = await execFileAsync("beet", ["fetchart", "-q"], {
timeout: 300000,
});BeetsAI Doctor schlägt Reparaturen vor, dann führt Beets sie durch
Der Doctor ergänzt eine modellgestützte Prüfung für Probleme wie falsch gruppierte Compilations, aufgeteilte Veröffentlichungen und Genre-Metadaten. Die Option für einen reinen Plan überspringt die Schreibzugriffe von Beets. So können Sie die vorgeschlagenen Änderungen zuerst prüfen. Im Ausführungsmodus können manche Entscheidungen automatisch angewendet werden. Nicht jede Änderung wartet dort auf eine manuelle Freigabe.
Der Code zum Anwenden einer Änderung protokolliert den Albumzustand davor und danach. Er führt zuerst beet modify und dann beet write aus, um die Datei-Tags zu aktualisieren. Erkannte Änderungen übernimmt er in Vynls Titeltabelle. Ohne das Schreiben der Tags könnte eine spätere Metadatenaktualisierung die alten Werte aus den Audiodateien zurückholen.
Die Pipeline anwenden protokolliert Fehler beim Schreiben der Tags und die Zahl aktualisierter Vynl-Einträge. Diese Schritte können unabhängig voneinander scheitern. Sichern Sie die Audiodateien und beide Datenbanken, prüfen Sie den Plan und kontrollieren Sie die Ergebnisse. Erst dann ist die Reparatur abgeschlossen. Der reine Planungsmodus gehört zum Doctor. Die übrigen Wartungsfunktionen können weiterhin Dateien verändern oder löschen.
Sonos zu Hause, lauschend
Vynl steuert Sonos im Serverprozess über die Bibliothek @svrooij/sonos. Sie findet Lautsprecher im lokalen Netzwerk per SSDP. Findet die Multicast-Suche nichts, kann SONOS_SEED_IP einen bekannten Lautsprecher als Einstiegspunkt vorgeben. Das hilft bei Containern oder Netzwerken, in denen die Suchpakete die Lautsprecher nicht erreichen.
Die Schnittstelle funktioniert mit benannten Räumen. Wählen Sie einen Raum aus, um die Wiedergabe zu starten oder anzuhalten, Titel zu überspringen oder die Lautstärke anzupassen. In separaten Räumen kann unterschiedliche Musik gespielt werden. Schliessen Sie Räume zu einer Gruppe zusammen, wenn Sie möchten, dass sie zusammen spielen, und verlassen Sie dann die Gruppe oder lösen Sie sie auf, um sie wieder separat zu steuern.
Diese Funktionen stammen direkt aus Vynls Sonos-Integration. Jeder Befehl ermittelt den gewählten Lautsprecher anhand seines Namens. Die Lautstärke bleibt im unterstützten Bereich von 0 bis 100:
export async function setVolume(speaker: string, volume: number): Promise<void> {
const device = await getDeviceByName(speaker);
const clamped = Math.max(0, Math.min(100, Math.round(volume)));
await device.SetVolume(clamped);
}
export async function groupJoin(speaker: string, target: string): Promise<void> {
const device = await getDeviceByName(speaker);
await device.JoinGroup(target);
}Durch die Gruppierung wird die individuelle Lautstärkeregelung nicht aufgehoben. Vynl liest den Wiedergabetitel und den Transportstatus vom Gruppenkoordinator, liest jedoch die Lautstärke vom ausgewählten Lautsprecher. Stereopaare und Heimkino-Satelliten erscheinen als ein einziger adressierbarer Raum, anstatt so zu tun, als wäre jeder physische Lautsprecher ein unabhängiger Player.
Wie ein Titel den ausgewählten Lautsprecher erreicht
Der Browser sendet den Lautsprechernamen und die Dateiauswahl an Vynls Steuerungsroute. Diese erzeugt eine Audio-URL, die der Lautsprecher direkt vom Server abruft. Bei einer verlustfreien Datei, die zur Sonos-Transkodierung markiert ist, fordert die Route einen MP3-Stream über Vynls Audio-Endpunkt an:
const sonosEncoded = isLossless
? encoded.replace(/\.(flac|wav|aiff|alac)$/i, ".mp3")
: encoded;
const sonosParam = isLossless ? "?sonos=1" : "";
const builtUri = `${base}/api/audio${sonosEncoded}${sonosParam}`;
await sonos.playUri(speaker, builtUri, false);Der Ausschnitt stammt aus der Sonos-Steuerungsroute. Vor dem Start übergibt der Wiedergabehelfer die Sonos-Metadaten. Er vermeidet ausserdem, Leerzeichen in Dateipfaden doppelt zu kodieren. Eine falsch kodierte URL kann eine vorhandene Musikdatei unerreichbar erscheinen lassen.
Setzen Sie VYNL_HOST oder den unterstützten Ersatzwert NEXT_PUBLIC_VYNL_HOST auf eine Adresse, die die Lautsprecher erreichen können. Eine URL, die auf dem Telefon über eine Fernverbindung funktioniert, muss vom Lautsprecher im Heimnetz aus nicht erreichbar sein. Vynl steuert gefundene, erreichbare Sonos-Räume. Die Netzwerkverbindung zwischen ihnen muss funktionieren.
Zum Musikhören unterwegs braucht es eine separat eingerichtete und abgesicherte Verbindung zum Server. Die Musik liegt weiterhin zu Hause. Server und Internetverbindung müssen deshalb erreichbar sein. Daran ändert eigenes Hosting nichts.
Wo KI hilft
Die Bereinigung von Bibliotheken ist eine konkrete Verwendung. Anstatt jeden Tag-Vorschlag anzunehmen, kann ich die Änderungen überprüfen, bevor sie in die Dateien gelangen.
Vynl unterstützt lokale Modellverbindungen über Ollama oder LM Studio sowie Cloud-Anbieter wie Anthropic und OpenRouter. Der Anbieter, den Sie auswählen, ist wichtig. Eine cloudgestützte Funktion sendet ihre Modellanfragen ausserhalb Ihres Computers. Die Audiodateien zu Hause zu behalten ist nicht dasselbe wie jede KI-Anfrage lokal zu halten.
Der KI-DJ- und Party-Workflow befindet sich noch in der Entwicklung. Sie sind Teil dessen, wo ich Vynl hinbringen möchte, und nicht ein fertiger Satz von Funktionen.
Playlists mitbringen
Die Spotify-Integration importiert Playlist- und Like-Informationen und gleicht sie dann mit der Musik ab, die Sie bereits haben. Es verwendet Aufnahmekennungen und den Abgleich von Künstler und Titel. Passende Titel werden zu Vynl-Wiedergabelisten. Fehlende Titel kommen auf eine Wunschliste.
Dadurch wird die Organisation einer Playlist übertragen, nicht die Audiodateien von Spotify. Sie benötigen weiterhin eine eigene Kopie der Musik.
04 / Installation
Betreiben Sie Ihre eigene Musikbibliothek
Vynl verwendet Next.js und SQLite, Beets zur Musikverwaltung und FFmpeg zur Audioverarbeitung. Im Projekt-Repository finden Sie die Installationsanleitung und den aktuellen Funktionsstand.
Überprüfen Sie vor dem Importieren einer grossen Sammlung, ob der Server die Musikordner lesen kann, dass der Speicher über Neustarts hinweg erhalten bleibt und dass Ihre Wiedergabegeräte darauf zugreifen können. Sichern Sie die Audiodateien, die Beets-Datenbank und die Vynl-Datenbank. Das Neuerstellen eines Index ist nicht dasselbe wie das Wiederherstellen Ihrer Sammlung.
Vynl begann als eine Möglichkeit, wieder meine eigene Musik zu hören. Das bleibt der Test für das, was ich als nächstes hinzufüge. Hilft es mir, ein Album zu finden, die Sammlung zu organisieren oder zu hören, wo ich möchte?

