本文へ移動
cccskills
無料GitHub で公開

lyrion-api

Query the Lyrion Music Server over its JSON-RPC API from the Flask app. Use this whenever a task needs live data from Lyrion — the now-playing track, player list, transport state, album art, or any `slim.request` command — or when adding a feature that reads from the music server. Covers the request format, the tag system, the shared cache, and the self-signed-TLS rules, so new calls match how `services/lyrion.py` already talks to the server.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md4.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Talking to Lyrion (JSON-RPC)

All server communication goes through services/lyrion.py. Add new server calls there and expose them as functions the routes import — routes never build JSON-RPC payloads themselves.

Request shape

Lyrion speaks JSON-RPC over POST {LYRION_HOST}/jsonrpc.js. Every call goes through lyrion_request(payload), which posts the payload, tolerates the empty non-JSON body Lyrion returns for unknown player ids, and returns {} instead of raising. Read results defensively: data.get("result", {}).get(...).

The payload is always a slim.request with a player id (or "" for server-wide commands) and a command array:

payload = {
    "id": 1,
    "method": "slim.request",
    "params": [player_id, ["status", "-", 1, "tags:aAldcKy"]],
}
data = lyrion_request(payload)
  • params[0] — player id (a MAC address), or "" for server-wide queries like players.
  • params[1] — the command and its arguments. "-" as the playlist index means "current track"; the trailing count (1) limits returned items.

Examples already in the file — read them before writing a new call:

  • get_players() — ["", ["players", "0", "100"]], returns players_loop.
  • get_now_playing(player_id) — ["status", "-", 1, "tags:aAldcKy"], returns the current track from playlist_loop.

The tag system

status returns only the fields you ask for via a tags: string, one letter per field. The ones this app uses:

tagfieldnotes
aartist
Arole-keyed artist listsmultiple artists joined by ", " under a role key (trackartist, artist)
lalbum
yyear0 when unknown, normalized to None
dduration
ccoveridabsent for remote/streamed tracks
Kartwork_urlremote streams (Deezer/Spotify/radio); may be relative to the host

Title and track id come back by default, and so do the player-level fields such as mixer volume (negated while the player is muted; _volume maps it to volume/muted). That track id is the key into the SQLite tracks table for lyrics (see services/database.py). When reading artists, prefer trackartist (full "feat." line) then fall back to artist then albumartist, matching get_now_playing.

Need a field the app doesn't fetch yet? Add its tag letter to the tags: string and map it in the returned dict — don't make a second call.

Covers and same-origin proxying

Covers are proxied through this app rather than pointed straight at LYRION_HOST, so the page can read image pixels on a canvas to derive the accent tint (a cross-origin image would taint the canvas). fetch_cover gets local artwork by coverid (optionally an NxN thumbnail, falling back to full art on 404); fetch_remote_cover gets a stream's artwork_url. Both funnel through _read_image, which caps size at COVER_MAX_BYTES and aborts 502 on oversized or non-image payloads.

Caching and shared state

get_active_now_playing() is the entry point routes should call for now-playing state. It caches the snapshot of all playing players for NOW_PLAYING_TTL (2s) behind _now_lock, so Lyrion sees one enumeration per TTL regardless of how many clients poll. It also ages the cached playback position by wall-clock time so the progress bar and karaoke highlight stay accurate across shared reads. If you add server calls that clients poll, follow this pattern rather than hitting Lyrion per request.

_last_player keeps the auto-selected player stable across polls; only mutate it under _now_lock (see _auto_select).

TLS: verify=False only for the local host

The local Lyrion server is self-signed, so calls to LYRION_HOST pass verify=False — this is documented accepted risk "audit S1" (PR #15). Keep the inline comment referencing it whenever you add such a call, so bandit's # nosec justification trail stays intact. Calls to public CDN URLs (fetch_remote_cover) keep verification on — never blanket-disable it.

Checklist for a new server call

  1. Add the function to services/lyrion.py, building a slim.request payload.
  2. Route it through lyrion_request and read result defensively.
  3. Request exactly the tags you need; map them into a plain dict.
  4. If clients will poll it, cache behind a lock with a short TTL.
  5. Add a test that patches lyrion_request (see tests/test_lyrion_request.py and tests/test_now_playing_cache.py) — never hit a real server in tests.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

add-route

無料

Add or modify a Flask endpoint in the Lyrion Dashboard. Use this whenever a task adds a new URL/route, a JSON API endpoint, or a page — anything that registers a handler in `routes/`. Covers the repo's route → service → test layering, input validation, caching headers, security headers, i18n wiring, and the exact test pattern, so a new endpoint matches how `routes/` already works instead of reinventing the structure.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

android

無料

Work on the Android app — the thin WebView wrapper in `android/`. Use this whenever a task touches the Kotlin sources, the Gradle build, the WebView shell, the native settings screen, LMS server auto-discovery, the JS↔native bridge, app strings/i18n, or the Android CI/lint. Covers the "shell only, UI lives on the web" principle, the debug/release signing split, the static versioning F-Droid needs, and the min/target SDKs, so changes fit the wrapper.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

covers

無料

Work on album artwork — reading an image's dimensions, and embedding a folder's cover file into the tags of its tracks. Use this whenever a task touches `services/artwork.py`, the cover half of `services/tags.py`, or `scripts/embed_covers.py` / `embed_covers_cron.sh`. Covers why Lyrion shows the embedded artwork and never the folder file, how covers are compared, why images are never re-encoded, and what embedding costs in rewritten files.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

database

無料

Read data from Lyrion's SQLite databases — library stats, stored lyrics, album covers, recent plays. Use this whenever a task queries `library.db` or `persist.db`, adds or changes a statistic, or touches `services/database.py`. Covers the read-only connection model (RO open + `ATTACH persist.db`), the key tables, the `play_counts` view over the Alternative Play Count plugin, the single-flight stats cache, and why the app must never write to these DBs. Reach for it before writing any SQL against the Lyrion databases.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

frontend

無料

Work on the dashboard's frontend — the vanilla JS/CSS page with no framework or bundler. Use this whenever a task touches `static/nowplaying.js`, `static/style.css`, the Jinja templates (`templates/nowplaying.html`, `_icons.html`), the accent-color tinting, the karaoke lyrics sync, the now-playing poll, or the empty-state mosaic / recent-plays pile. Covers how the page is wired, how it reads i18n and data from the server, the ESLint gate, and the Android bridge, so changes match the existing patterns.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

i18n

無料

Add, change, or translate user-facing text in the Lyrion Dashboard, which ships bilingual FR/EN. Use this whenever a task introduces a new visible string (a label, tooltip, aria-label, empty state, stat name), changes wording, or touches the README or a `docs/` page — so every string lands in both languages and the EN/FR documentation pairs stay in sync. Covers `i18n.py`, how templates and JS consume translations, and the parity rule.

日本語の概要は準備中です。原文の説明を表示しています。

werdeil/lyrion-dashboard32026年10月15日 更新

werdeil のスキルをすべて見る

このスキルの問題を報告する