Skip to main content

Manage Yoto CYO playlists as folders on disk

Project description

yoto-library

CI PyPI Python 3.10+ License: MIT Platform: macOS Built with Claude Code Conventional Commits Gitmoji

Manage Yoto Player Create-Your-Own (CYO) playlists as folders on disk, with two-way sync to the Yoto API.

Each playlist is a folder. Audio files live in MKA containers that carry metadata and icon attachments. Cover art and track icons are auto-generated via AI when missing. Sync pushes local state to Yoto; pull downloads remote state to a local folder.

Prerequisites

Required:

  • Python 3.10+
  • FFmpeg — audio processing, MKA muxing, silence detection
  • mkvtoolnix — MKA metadata and attachment read/write

Optional:

  • yt-dlp — YouTube audio downloads (for .webloc support)
  • bsdiff — byte-perfect export patches (install via brew install bsdiff; bspatch ships with macOS)

AI services (for icon and cover art generation):

  • Claude CLI — descriptions, icon matching, cover text quality checks (uses your Claude subscription)
  • node (v18+) — required for web scraping lyrics sources. Install via brew install node or from nodejs.org. Also requires jsdom: npm install jsdom (run once in the yoto-library directory).
  • RetroDiffusion — 16x16 pixel art icon generation (RETRODIFFUSION_API_KEY)
  • Together AI — album art recomposition via FLUX Kontext (TOGETHER_API_KEY)
  • Google Gemini — text rendering for cover art repair (GEMINI_API_KEY)
  • OpenAI — text-to-image cover generation when no album art exists (OPENAI_API_KEY)

On macOS with Homebrew:

brew install ffmpeg mkvtoolnix yt-dlp

Installation

pip install yoto-library

This installs the yoto command.

To install from source (requires uv):

git clone https://github.com/steverice/yoto-library.git
cd yoto-library
uv sync

Quick start

Authenticate:

yoto auth

Opens a device code flow — visit the URL shown, enter the code, and your token is saved to macOS Keychain.

Pull an existing playlist:

yoto pull abc12

Downloads the playlist with card ID abc12 into a local folder.

Create a new playlist:

yoto init "Bedtime Songs"

Scaffolds an empty playlist folder. Add .mka audio files, then sync.

Import existing audio files:

yoto import ~/Music/album -o "Road Trip Mix"

Converts a folder of audio files (MP3, FLAC, WAV, etc.) into MKA-wrapped tracks in a new playlist folder.

Sync to Yoto:

yoto sync "Bedtime Songs"

Pushes local state to the Yoto API — uploads audio, generates icons and cover art if missing, and creates or updates the card.

Playlist folder structure

Bedtime Songs/
  playlist.jsonl          # track order (JSON strings, one per line)
  description.txt         # playlist description, ≤500 chars (auto-generated if missing)
  cover.png               # 638x1011 portrait cover art (auto-generated if missing)
  .yoto-card-id           # Yoto card ID (written on first sync or pull)
  lullaby.mka             # audio + metadata + icon attachment
  twinkle-twinkle.mka
  rock-a-bye.mka

playlist.jsonl — bare JSON strings defining track order. Auto-generated alphabetically if absent. Editable with yoto reorder or any text editor.

"lullaby.mka"
"twinkle-twinkle.mka"
"rock-a-bye.mka"

MKA containers — Matroska Audio files that losslessly wrap any audio codec. Each MKA carries the original audio stream, Matroska metadata tags (artist, language, etc.), and a 16x16 icon attachment (PNG or animated GIF).

Commands

yoto auth

Authenticate with Yoto via OAuth device code flow. Tokens are stored in macOS Keychain.

yoto sync [path]

Push local playlist state to Yoto. Uploads new/changed audio, icons, and cover art. Creates or updates the remote card.

yoto sync                     # sync playlist in current directory
yoto sync "Bedtime Songs"     # sync a specific folder
yoto sync --dry-run           # preview changes without executing
yoto sync --no-trim           # skip silence trimming on YouTube downloads
yoto sync --print             # print cover art after sync
yoto sync --no-print          # skip print prompt

yoto pull [path | card-id]

Pull remote playlist state to a local folder. Downloads audio, wraps in MKA, sets icons.

yoto pull abc12               # pull by card ID into a new folder
yoto pull "Bedtime Songs"     # update an existing linked folder from remote
yoto pull --all               # pull all playlists into subdirectories of cwd
yoto pull --dry-run           # preview changes

yoto status [path]

Show the diff between local and remote state for a playlist.

yoto list

Show all MYO cards on the authenticated Yoto account (card ID, title, track count).

yoto init [path]

Scaffold a new empty playlist folder with an empty playlist.jsonl. Defaults to current directory.

yoto import <source>

Bulk import: convert a folder of audio files into a playlist with MKA-wrapped tracks.

yoto import ~/Music/album                       # in-place
yoto import ~/Music/album -o "Road Trip Mix"    # into a new folder

yoto download [path]

Resolve .webloc URLs in a playlist folder — downloads audio (via yt-dlp), trims silence, and wraps in MKA. Does not sync to Yoto.

yoto download                 # process .webloc files in current directory
yoto download --no-trim       # skip silence trimming

yoto export <playlist>

Export MKA tracks back to their original audio format. If a source.patch attachment exists, the export is byte-perfect via bspatch.

yoto export "Bedtime Songs"                    # export to Bedtime Songs-exported/
yoto export "Bedtime Songs" -o ~/Music/out     # export to a specific folder

yoto lyrics <playlist>

Fetch and store lyrics for tracks in a playlist. Checks source tags first, then falls back to the LRCLIB API.

yoto lyrics "Bedtime Songs"           # fetch missing lyrics
yoto lyrics "Bedtime Songs" --force   # re-fetch all lyrics
yoto lyrics "Bedtime Songs" --show    # display stored lyrics in a pager
yoto lyrics "Bedtime Songs" --clear   # remove stored lyrics from tracks

yoto cover [path]

Generate cover art for a playlist folder without syncing.

yoto cover                          # generate cover in current directory
yoto cover --style cartoon          # generate with a specific art style
yoto cover --force                  # regenerate even if cover.png exists
yoto cover --backup                 # rename existing cover.png before generating
yoto cover --ignore-album-art       # skip album art reuse, generate from prompt

Available styles: cartoon, cel, chalk, crayon, gouache, papercraft, storybook (default), watercolor. The chosen style is saved to .yoto-style in the playlist folder and reused on future regenerations.

yoto reorder [playlist]

Open playlist.jsonl in $EDITOR to reorder tracks. Validates JSON on save. Defaults to playlist.jsonl in the current directory.

yoto select-icon <track>

Interactive icon selection for a single track (or multiple tracks in sequence). Generates three pixel art icon options, finds the best match from Yoto's icon catalog, scores all candidates with an LLM, and displays them in bordered panels for selection. Pick one or press r to regenerate.

yoto reset-icon <tracks...>

Remove icon attachments from one or more MKA files. The next yoto sync will regenerate icons for those tracks.

yoto print [path]

Print cover art to a photo printer via macOS CUPS. Optionally applies an ICC color profile for accurate color reproduction.

yoto print                                  # print cover in current directory
yoto print "Bedtime Songs"                  # print a specific playlist's cover
yoto print --yes                             # skip confirmation prompt
yoto print --profile /path/to/profile.icc   # use ICC color profile

If no cover.png exists, offers to generate one first. If a profile is specified but not found, warns and offers to continue without color management.

yoto lyrics [path]

Fetch and embed lyrics for tracks in a playlist folder. Tries embedded tags, then user-configured web scraping sources, then the LRCLIB public API.

yoto lyrics                          # fetch lyrics for current directory
yoto lyrics "Bedtime Songs"          # fetch lyrics for a specific folder
yoto lyrics --clear                  # remove stored lyrics from tracks
yoto lyrics --add-source <url>       # analyze a website and add it as a lyrics source

yoto billing

Show provider balances, subscription usage, and lifetime cost tracking.

yoto billing                    # show all billing info
yoto billing --reset            # reset all lifetime cost data
yoto billing --reset openai     # reset costs for a specific provider group

yoto completions [shell]

Print the shell completion setup command for zsh, bash, or fish. Auto-detects your shell if not specified.

Configuration

Authentication is handled via macOS Keychain — no config file needed. Run yoto auth to log in.

AI services require API keys set as environment variables (e.g., in .env at the project root):

RETRODIFFUSION_API_KEY=...   # retrodiffusion.ai — icon generation
TOGETHER_API_KEY=...         # together.ai — album art recomposition (FLUX Kontext)
GEMINI_API_KEY=...           # aistudio.google.com — text layer rendering
OPENAI_API_KEY=...           # platform.openai.com — text-to-image cover generation

Each service handles a specific part of the pipeline — see AI providers below.

Lyrics sources — web scraping configs live in ~/.yoto/lyrics/*.json. Each file defines one source. Use yoto lyrics --add-source <url> to add a new source interactively — Claude analyzes the site's HTML and generates the JS snippets automatically.

Printing — requires a photo printer configured in macOS System Settings:

  • YOTO_PRINTER — CUPS printer name (default: Canon_SELPHY_CP1300)
  • YOTO_ICC_PROFILE — path to ICC color profile (optional; skips color management if unset)

How it works

Sync flow — loads local playlist state (tracks, metadata, cover, description), fetches remote state, diffs them, then uploads changed audio through Yoto's transcode pipeline, uploads icons and cover art, and POSTs the assembled content JSON.

Pull flow — fetches the remote card with signed audio URLs, downloads tracks in parallel, wraps each in MKA with metadata and icon attachments, and writes playlist.jsonl and cover.png.

Icon pipeline — if a track already has an icon attachment in its MKA, that icon is used. Otherwise, the track title is matched against Yoto's public icon catalog via LLM. High-confidence matches are used directly; lower-confidence matches are compared against 3 AI-generated alternatives (via RetroDiffusion pixel art). The LLM picks the winner.

Cover art — if cover.png is missing, the tool first checks whether all tracks share identical embedded album art (e.g., from a ripped CD or tagged album). If so, FLUX Kontext recomposes the square art into a 638x1011 portrait layout. Claude checks the result for text quality — if text is mangled after 3 attempts, a repair pipeline kicks in: Claude OCRs the original text, Gemini renders a styled text layer, Claude picks placement coordinates, and PIL composites the text onto the artwork. If no shared album art exists, OpenAI generates a cover from scratch using track metadata. Delete cover.png to regenerate.

Text-to-image covers accept a --style flag to control the visual art direction (e.g., cartoon, watercolor, gouache). The choice is persisted in .yoto-style so future regenerations reuse it.

Use yoto cover --force to regenerate an existing cover. Set YOTO_RECOMPOSE_ATTEMPTS (default 3) to control how many FLUX attempts before falling back to the text repair pipeline.

  • YOTO_WORKERS — max parallel workers for downloads, uploads, imports, exports (default: 4)

YouTube downloads — drop a .webloc file (Safari bookmark) into a playlist folder. On yoto sync or yoto download, the URL is resolved via yt-dlp, silence is trimmed from pre/post-roll, and the audio is wrapped in MKA. The .webloc is deleted after successful download.

AI providers

Each AI task uses a specific provider chosen for best results at that task:

Task Provider Key Pricing
Icon generation (16x16 pixel art) RetroDiffusion RETRODIFFUSION_API_KEY ~$0.003/image
Album art recomposition FLUX Kontext Pro via Together AI TOGETHER_API_KEY ~$0.04/image
Text layer rendering (cover repair) Gemini 2.5 Flash GEMINI_API_KEY ~$0.07/image
Text-to-image cover generation OpenAI gpt-image-1.5 OPENAI_API_KEY ~$0.013/image
Descriptions, icon matching, cover evaluation (Sonnet) Claude CLI Subscription Included with Claude subscription

Getting API keys:

Important: If ANTHROPIC_API_KEY is set in your environment, the Claude CLI will use it for API-key billing instead of your subscription. This can result in significant per-token charges. Make sure ANTHROPIC_API_KEY is not set (or excluded from your .env) to use your Claude subscription.

iTerm2 icon display

If you use iTerm2, the select-icon command can improve pixel art rendering by fixing a color space issue in some iTerm2 color presets (notably "Dark Background"). To enable this:

  1. Enable iTerm2's Python API: Preferences > General > Magic > "Enable Python API"

The iterm2 Python package will be installed automatically on first use. Without the API enabled, icons display normally but may show faint horizontal banding.

Development

See CONTRIBUTING.md for development setup, commit conventions, and release process.

Architecture

Two-layer design: yoto_lib (standalone library) and yoto_cli (thin Click wrapper). See ARCHITECTURE.md for details.

Disclaimer

This project is not affiliated with, endorsed by, or associated with Yoto Limited. "Yoto" is a trademark of Yoto Limited.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yoto_library-0.3.1.tar.gz (297.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yoto_library-0.3.1-py3-none-any.whl (124.8 kB view details)

Uploaded Python 3

File details

Details for the file yoto_library-0.3.1.tar.gz.

File metadata

  • Download URL: yoto_library-0.3.1.tar.gz
  • Upload date:
  • Size: 297.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yoto_library-0.3.1.tar.gz
Algorithm Hash digest
SHA256 f5d59a956428e815bfe27227c7a74d0803ba54269c03ab3c0d446b7b63bbff7e
MD5 9f8f8db31c4bb092fba4d50551e31488
BLAKE2b-256 36a1d9e9de303e5971f5bf47b032e7e8e4a9b04d303376e9d1782ec5273a2423

See more details on using hashes here.

Provenance

The following attestation bundles were made for yoto_library-0.3.1.tar.gz:

Publisher: pypi.yml on steverice/yoto-library

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yoto_library-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: yoto_library-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 124.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yoto_library-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 57b1353acedfd89f893e71013c4417d9f68c337d7b11a0ac40b0b01f82a7b123
MD5 1b963ec3d57d319e86dab6687c51b8d0
BLAKE2b-256 58f86908da3ef63a689291b47db4d27c8d43d2381ee26a66111b8ffe16b7d565

See more details on using hashes here.

Provenance

The following attestation bundles were made for yoto_library-0.3.1-py3-none-any.whl:

Publisher: pypi.yml on steverice/yoto-library

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page