fireworks-radio
A pragmatic Codex skill for reliable coding-session audio playback.
When ncm-cli fails on source rights and Spotify CLI fails on OAuth or Premium restrictions, this project falls back to yt-dlp + mpv and gets audio playing fast.
中文文档 · License · Legal Notes
Why This Project Exists
This project came from a very unglamorous reality:
ncm-clicould search tracks, but many target songs still had no playable source.- Spotify CLI could authenticate halfway, then fail on callback behavior or return
403because the app owner did not have an active Premium subscription. - Even when playback worked, multiple player processes could stack and create double audio.
The core lesson was simple:
Users do not care which audio stack is ideologically correct. They care about hearing the music now.
So this project codifies a more honest strategy:
- Try the preferred path only briefly.
- Stop pretending auth or rights failures are “just one more retry away.”
- Fall back to
yt-dlp + mpv. - Keep the playlist short, explicit, and stable.
- Clean up duplicate playback processes.
What It Actually Does
fireworks-radio is not trying to be a full streaming client. It is a coding-session audio fallback skill.
Its job is operational:
- recover quickly when common terminal media stacks break
- build small explicit playlists from search queries
- prefer existing public sources for all audio playback instead of generating new spoken content
- support both
streamandcacheplayback modes - remember lightweight listening preferences for future preset selection
- avoid duplicate player processes and overlapping audio
One Hard-Won Lesson Added
One real failure we hit was source switching overlap: killing only the PID saved in the skill was not enough.
The reason is straightforward:
- a foreground
mpvtest may never get written to the PID file - a later source switch may stop only the remembered background process
- the leftover foreground
mpvkeeps playing, so the user hears two streams at once
That lesson is now part of the default behavior:
- source switches do not rely only on the saved PID
- they also clear residual
mpv --no-videoprocesses - the goal is not “usually no overlap”; the goal is no overlap by default
It can be used for:
- music
- podcasts
- interviews
- long-form technical talks
- ambient or focus audio
Playback Modes
stream
Default mode. yt-dlp resolves playable media URLs and mpv streams them directly.
Best for:
- quick listening
- stable networks
- low-friction playback
cache
Downloads audio into a local cache directory first, then plays the local files.
Best for:
- unstable networks
- repeated listening
- reusable mixes
- downstream transcription or editing
Stack
yt-dlpfor resolving playable media URLs from YouTubempvfor stable local playback- shell scripts for playlist generation and lifecycle control
- a lightweight preference memory script for presets, artists, and feedback
SKILL.mdso Codex can use the workflow consistently
Project Structure
fireworks-radio/
├── SKILL.md
├── LICENSE
├── LEGAL.md
├── README.md
├── README.zh-CN.md
├── assets/
│ └── images/
│ ├── fireworks-radio-icon.png
│ └── fireworks-radio-landing.png
└── scripts/
├── build_playlist.sh
├── play_mix.sh
├── radio_memory.py
└── stop_mix.sh
Requirements
- macOS or Linux
yt-dlpmpv- network access to YouTube
Quick Start
1. Build a playlist from queries
./scripts/build_playlist.sh /private/tmp/fireworks-radio.m3u \
"萧亚轩 爱的主打歌 official" \
"Ed Sheeran Shape of You official lyric video" \
"Lady Gaga Bad Romance official"2. Play it
./scripts/play_mix.sh /private/tmp/fireworks-radio.m3u2b. Cache first, then play local files
./scripts/play_mix.sh --mode cache /private/tmp/fireworks-radio.m3u3. Stop it
./scripts/stop_mix.shCommon Workflows
1. Play a hand-built short list
./scripts/build_playlist.sh /private/tmp/fireworks-radio.m3u \
"Tycho Awake official audio" \
"Ed Sheeran Perfect official" \
"Lady Gaga Bad Romance official"
./scripts/play_mix.sh /private/tmp/fireworks-radio.m3u2. Reuse the same list in cache mode
./scripts/play_mix.sh --mode cache /private/tmp/fireworks-radio.m3u3. Use built-in presets
./scripts/play_mix.sh --preset three-artists
./scripts/play_mix.sh --preset focus-ambient
./scripts/play_mix.sh --preset coding-pop4. Let preference memory choose
./scripts/play_mix.sh --autoGeneral Audio Source Policy
This is not only for AI news. It is the default policy for all audio playback inside fireworks-radio.
Hard rules:
- use only public, currently accessible, already-published, directly playable sources
- do not synthesize a local spoken track from web content unless the user explicitly asks
- do not open a webpage just to get playback
- prefer direct playback in the current terminal window
- start with one finished source instead of stitching fake shows or fake episodes
- after one source works, confirm at least one backup source class
Allowed source types:
- public YouTube videos, audio-only playback
- public podcast RSS feeds
- direct MP3
enclosurelinks exposed by a podcast host - free and public music sources where the work is already published and directly accessible
Default disallowed behavior:
- summarizing the web and then reading it back with local TTS
- opening a browser page and offloading playback to the user
- stitching unrelated web pages into a pretend program
- drifting into article reading, newsletter summarization, or other non-playback forms unless the user explicitly asks
Music Source Guidance
For music, this skill may prefer free and public source classes such as:
ccMixterFree Music ArchiveMusopenOpen Music Archive
That still does not mean every track grants every downstream use. Per-track rights and platform rules still matter.
AI News Mode
AI news is only a narrower sub-mode under the global source policy above:
- prefer public YouTube AI news videos through
mpv --no-video - if YouTube is unreliable, prefer public podcast RSS / MP3
enclosure - if both fail, explain the failure instead of silently switching back to local synthesis
Currently verified source classes:
YouTube
good for directmpv --no-videoplayback of public AI news videosPodcast RSS / MP3 enclosure
for example,The AI News Daily Briefexposes a public RSS feed:
https://feeds.podcastai.com/lzSp5oGSGEaLNzHdqUBaTh.xml
That feed already exposes direct enclosure audio URLs, so it works as a non-YouTube backup.
Built-in Preset
./scripts/play_mix.sh --preset three-artists
./scripts/play_mix.sh --autoBuilt-in presets currently include:
three-artists
Elva Hsiao / Ed Sheeran / Lady Gagafocus-ambient
quieter instrumental and ambient listeningcoding-pop
higher-energy pop for active work blocks
The --auto mode uses remembered preference signals to choose a preset.
Preference Memory
fireworks-radio stores lightweight listening preferences so future runs can make better decisions without pretending to be a full recommendation engine.
Examples:
python3 ./scripts/radio_memory.py reinforce --preset three-artists --feedback like
python3 ./scripts/radio_memory.py reinforce --artist "Lady Gaga" --feedback like
python3 ./scripts/radio_memory.py showStored signals include:
- liked or disliked presets
- liked artists
- tags such as
coding-pop,focus, orambient - play counts for presets
Common Codex Usage
Use fireworks-radio to play a coding mix and fall back to YouTube if ncm-cli fails.Play existing public audio directly in the current window. Do not open a webpage.For AI news, do not synthesize anything. Play a real public source.Play a 12-track mix of Elva Hsiao, Ed Sheeran, and Lady Gaga.Choose a preset automatically from my past listening preferences.Stop the current mix and rebuild it with faster songs.Test one track first, then expand to a full playlist if playback works.
Design Principles
- Short feedback loops beat perfect architecture.
- Rights failures are operational facts, not bugs to deny.
- Fallbacks should be explicit and fast.
- Existing public audio is the default. Local synthesis is opt-in only.
- Test tracks must be cleaned up after validation.
Licensing Position
This repository is source-available, not OSI open source.
The default software license is PolyForm Noncommercial 1.0.0. Commercial use is
not allowed without separate written permission.
This repository does not grant any rights to third-party media. If a user
chooses to stream, cache, or play content from third-party platforms, the user
is responsible for copyright and platform-term compliance.
In other words:
streamandcacheare workflow modes, not rights grants- the repository automates playback workflows, not content licensing
