DJ and chat read listener preferences from settings.json on every request. Co-authored-by: Cursor <cursoragent@cursor.com>
4.2 KiB
Live Ozan Radio
Personal AI radio — no catalog music, ever. DeepSeek is the DJ. Google Lyria 3 composes every track. Spotify is read-only taste input.
Inspired by Magenta RealTime 2 (live, ~200ms) and Lyria 3 (full songs via Gemini API). On Mac you can layer MRT2 for true live improvisation; this repo ships the cross-platform Lyria + DeepSeek stack first.
Stack
| Layer | Product | Role |
|---|---|---|
| DJ brain | DeepSeek (via Tinqs inference or BYOK) | Mood, prompts, variety |
| Music engine | Google Lyria 3 Pro / Clip | Generate MP3 tracks |
| Taste | Spotify Web API (optional) | Top artists, genres — never plays Spotify |
| Player | FastAPI + gateway/player.html |
Stream generated queue |
| Live (optional) | Magenta RealTime 2 | Apple Silicon only — see below |
Taste (settings.json)
Edit settings.json at the repo root — the DJ reads it on every generate and chat. Default profile: ethnic world dubtronica (global roots + dub space + electronic groove).
Saved songs
Every track is written to ./songs/ and committed via Git LFS (audio) + plain git (metadata):
| File | Storage | Contents |
|---|---|---|
{id}_{title}.mp3 |
LFS | Audio |
{id}.meta.json |
git | Title, mood, DJ line, prompt, lyrics, timestamp |
Browse in the player under Saved songs, or GET /api/songs. After clone: git lfs install then git lfs pull.
Quick start (Forge / Windows)
cd live-ozan-radio
python -m venv .venv
.venv\Scripts\activate
pip install -e .
copy .env.example .env
# Fill GEMINI_API_KEY + DEEPSEEK_API_KEY (and Spotify if you have them)
python -m ozan_radio serve
# Open http://127.0.0.1:8787/player
One-shot track (no server):
python -m ozan_radio generate
Environment
| Variable | Required | Notes |
|---|---|---|
GEMINI_API_KEY |
Yes | Google AI Studio — Lyria 3 |
DEEPSEEK_API_KEY |
Yes | Tinqs proxy or DeepSeek direct |
DEEPSEEK_BASE_URL |
No | Default https://tinqs.com/api/v1/inference |
SPOTIFY_* |
No | Refresh token flow — taste only |
LYRIA_MODEL |
No | lyria-3-pro-preview (default) or lyria-3-clip-preview |
Spotify setup (taste profile)
- Create an app at Spotify Developer Dashboard.
- Add redirect URI
http://127.0.0.1:8888/callback. - Complete OAuth once to obtain a refresh token (scope:
user-top-read). - Paste
SPOTIFY_CLIENT_ID,SPOTIFY_CLIENT_SECRET,SPOTIFY_REFRESH_TOKENinto.env.
The Spotify MCP / tool you wired to DeepSeek can call the same endpoints — this repo exposes them natively for the DJ loop.
API
| Method | Path | Description |
|---|---|---|
| GET | /api/now |
Current track metadata |
| GET | /api/queue |
Full queue |
| POST | /api/generate |
DJ plans + Lyria renders next track |
| POST | /api/skip |
Advance queue |
| GET | /stream/{file} |
MP3 stream |
| GET | /player |
Web UI |
Magenta RealTime 2 (optional live layer)
On Apple Silicon (Kraken), install magenta-rt for sub-second live generation:
uv pip install "magenta-rt[mlx]"
mrt models init && mrt models download
mrt mlx generate --prompt "disco funk" --duration 4.0 --model=mrt2_small
Wire MRT2 as a bridge between tracks or as a live “bed” under the Lyria queue — PRs welcome.
Publish on tinqs.com (public repo)
- On Git Studio: + → New Repository
- Owner:
tinqs - Name:
live-radio - Visibility: Public
- Owner:
- Push (with LFS for song MP3s):
git lfs install
git init
git remote add origin git@ssh.tinqs.com:tinqs/live-radio.git
git add .
git commit -m "Live Ozan Radio — DeepSeek DJ + Lyria 3"
git push -u origin main
- Preview the player:
https://tinqs.com/tinqs/live-radio/src/branch/main/gateway/player.html(static shell; audio streams from your running server).
Agent usage
DeepSeek (Pi, Cursor, Claude Code) can operate the station via HTTP or the skill in .cursor/skills/ozan-radio/SKILL.md.
License
Apache 2.0 — same spirit as Magenta RealTime 2 open weights.