Files
toni-sync/README.md
T
arnefandCopilot eb77c0ecbd Support m3u playlist files to define chapter order
The chapter order on the tonie is already fully API-controlled via
SortChaptersOfTonie/PATCH. This adds an explicit way to define that
order via an .m3u/.m3u8 file placed in the tonie folder, instead of
relying on alphabetical filenames:

- internal/syncer/playlist.go: finds a single playlist file in the
  tonie folder, parses its entries (ignoring blanks/#-comments), and
  reorders local tracks accordingly. Tracks not referenced by the
  playlist are appended afterwards so nothing is silently dropped;
  playlist entries without a matching local file are ignored.
  Multiple playlist files in the same folder is an error (ambiguous
  order).
- ListLocalTracks now prefers this playlist-defined order, falling
  back to alphabetical filename order when no playlist is present.
- Tests covering playlist ordering, unreferenced-track handling,
  missing entries, and the multiple-playlists error case.
- README documents the .m3u/.m3u8 convention.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-14 13:26:09 +02:00

5.0 KiB

toni-sync

Ein CLI-Tool zur Verwaltung von Kreativ-Tonies: Es synchronisiert lokale Audio-Ordner (z. B. exportierte Deezer-Playlists) automatisch zu den passenden Kreativ-Tonies über die inoffizielle TonieCloud-API. Geschrieben in Go, kompiliert zu einer einzigen statischen Binary - keine Laufzeit- Abhängigkeiten (kein Python/pip nötig).

Hinweis: toni-sync lädt selbst keine Musik von Deezer herunter. Das Herunterladen/Umgehen von DRM-geschützten Streams verstößt gegen die Nutzungsbedingungen von Deezer und ggf. gegen Urheberrecht. Lege deine bereits legal exportierten Audiodateien einfach in die passenden lokalen Ordner - toni-sync kümmert sich nur um den Abgleich mit der TonieCloud.

Keine Config-Datei - die Ordnerstruktur ist die Konfiguration

Statt einer separaten Config-Datei wird das Mapping Playlist ↔ Kreativ-Tonie direkt über die Ordnerstruktur abgebildet:

<root>/
  <household_id>/
    <freier_name> [id=<tonie_id>]/
      01 - Track.mp3
      02 - Track.mp3
  • <household_id>: die Household-ID deines TonieCloud-Accounts
  • <freier_name> [id=<tonie_id>]: frei wählbarer Name + Tonie-ID in eckigen Klammern - der Name dient nur der Lesbarkeit, für das Mapping zählt allein die ID
  • Die alphabetische Dateireihenfolge innerhalb eines Tonie-Ordners bestimmt die Kapitelreihenfolge auf dem Tonie

Installation

Benötigt wird nur eine Go-Toolchain (>= 1.21) zum Bauen - danach ist das Ergebnis eine einzelne Binary ohne weitere Abhängigkeiten:

go build -o toni-sync ./cmd/toni-sync
./toni-sync --help

Oder direkt installieren (landet in $(go env GOPATH)/bin):

go install ./cmd/toni-sync

Anmeldedaten

toni-sync benötigt deine TonieCloud-Zugangsdaten (dieselben wie in der Tonies-App). Sie werden nicht gespeichert, sondern bei jedem Aufruf über Umgebungsvariablen oder interaktiven Prompt abgefragt:

export TONI_SYNC_USERNAME="you@example.com"
export TONI_SYNC_PASSWORD="********"

Alternativ: --username/--password Flags bei tonies list, init und sync.

Nutzung

1. Library-Ordner automatisch anlegen

toni-sync init --root ~/Musik/tonies

Legt für jede Household und jeden Kreativ-Tonie deines Accounts den passenden Ordner an, z. B.:

[created] /home/you/Musik/tonies/abcd-1234/Peppa Wutz [id=ef01-5678]
[created] /home/you/Musik/tonies/abcd-1234/Gute-Nacht-Geschichten [id=9876-4321]
Library ready at /home/you/Musik/tonies

Bereits vorhandene Ordner (anhand der Tonie-ID erkannt, auch bei geändertem Namen) werden nicht angefasst - deine Audiodateien bleiben unberührt.

Alternativ manuell: einfach die Ordner nach obigem Schema selbst anlegen.

2. Root-Ordner festlegen

Der Library-Root wird wie folgt bestimmt (erste zutreffende Option):

  1. --root PATH Flag
  2. Umgebungsvariable TONI_SYNC_ROOT
  3. aktuelles Arbeitsverzeichnis

3. Audiodateien einsortieren & synchronisieren

Lege deine (legal exportierten) Audiodateien in den passenden Tonie-Ordner. Die Kapitelreihenfolge wird wie folgt bestimmt:

  • Mit Playlist: Liegt genau eine .m3u/.m3u8-Datei im Tonie-Ordner, bestimmt deren Zeilenreihenfolge die Kapitelreihenfolge (Kommentare/#-Zeilen und Leerzeilen werden ignoriert, Pfade relativ zum Ordner). Dateien, die lokal existieren aber nicht in der Playlist stehen, werden trotzdem synchronisiert und ans Ende angehängt (nichts geht verloren). Einträge in der Playlist ohne passende Datei werden ignoriert. Liegen mehrere Playlist- Dateien im selben Ordner, bricht sync mit einem Fehler ab (Reihenfolge wäre sonst mehrdeutig).
  • Ohne Playlist: alphabetische Dateireihenfolge, z. B. 01 - Track.mp3, 02 - Track.mp3, ...

Beispiel playlist.m3u:

#EXTM3U
02 - Second Track.mp3
01 - First Track.mp3
03 - Third Track.mp3
# alle gefundenen Tonies synchronisieren
toni-sync sync --root ~/Musik/tonies

# nur Tonies syncen, deren Household-ID/Tonie-ID/Name den Filter enthalten
toni-sync sync peppa --root ~/Musik/tonies

# nur anzeigen, was sich ändern würde
toni-sync sync --root ~/Musik/tonies --dry-run

sync lädt neue Dateien hoch, entfernt Kapitel, die lokal nicht mehr existieren (abschaltbar via --no-prune), und sortiert die Kapitel passend zur lokalen Reihenfolge (Playlist-Datei falls vorhanden, sonst alphabetisch).

Household-/Tonie-IDs nachschlagen

Falls du die Struktur lieber manuell pflegen willst:

toni-sync tonies list
Household: Familie Müller  [id=abcd-1234]
  - Peppa Wutz  [id=ef01-5678]  (12 chapters, 3600s)
  - Gute-Nacht-Geschichten  [id=9876-4321]  (0 chapters, 0s)

Unterstützte Audioformate

.mp3, .m4a, .aac, .ogg, .flac, .wav

Projektstruktur

cmd/toni-sync/         CLI-Einstiegspunkt (Cobra-Kommandos: tonies, init, sync)
internal/tonieapi/      Eigener, minimaler TonieCloud-API-Client
internal/library/       Erkennung & Scaffolding der Ordnerstruktur (Household/Tonie)
internal/syncer/        Diff-/Apply-Logik zwischen lokalem Ordner und Tonie

Entwicklung / Tests

go build ./...
go vet ./...
go test ./...