/stream-hopper

escape the algorithmic echo chamber. discover music curated by real radio DJs and use those gems to seed better playlists.

Primary LanguageC++Mozilla Public License 2.0MPL-2.0

🐇 stream hopper

stream hopper ui

a terminal-based radio player for discovering new music through human-curated live streams. hop between stations, automatically log every song, and break the algorithm's hold on your musical taste.

✨ features

  • 🎶 instant station switching: seamlessly hop between stations with smooth audio crossfades
  • 📝 interactive curation: review stations with rich metadata and save only the best
  • 🎛️ first-run wizard: guided setup fetches fresh stations based on your favorite genres
  • 📊 rich metadata display: see bitrate, country, tags, and ratings during curation
  • 🔍 advanced discovery: fetch stations by genre and curate them interactively
  • 📋 multi-panel UI: stations, now playing, and history in a clean ncurses interface
  • ⚡ performance modes: Balanced, Performance, and Focus modes for different usage scenarios
  • 🤖 auto-hop discovery: let the app cycle through stations for passive discovery
  • 💾 persistent favorites: mark favorite stations saved between sessions
  • 🔄 multi-url fallbacks: cycle between backup streams with +
  • 🖥️ responsive TUI: adapts to terminal size with compact and full layouts

⚙️ installation

you'll need a C++17 compiler, make, pkg-config, and the development libraries for libmpv and ncurses.

distribution installation command
Debian/Ubuntu sudo apt install build-essential libmpv-dev libncursesw5-dev pkg-config
Fedora/RHEL sudo dnf install gcc-c++ mpv-devel ncurses-devel pkg-config make
Arch Linux sudo pacman -S gcc make pkg-config mpv ncurses

🚀 build & run

  1. compile the project
    make
  2. run the application
    ./build/stream-hopper

New users will be guided through first-run setup to create a personalized station list.

🎛️ controls

main player

key action
/ navigate stations / scroll history
mute/unmute current station
a toggle auto-hop mode
p cycle performance profiles
f toggle favorite for current station
d toggle audio ducking (lower volume)
+ cycle to next stream url for station
switch focus between panels
c enter copy mode (pause ui for selection)
q quit

🗂️ curation mode

key action
k keep station in final list
d discard station
p play/pause current station
q save and exit curation

🛠️ configuration

station management

  • stations.jsonc: Your main station list (generated by first-run wizard)
  • [genre].jsonc: Curated station lists (e.g., techno.jsonc)
  • radio_history.json: Timestamped listening history
  • radio_favorites.json: Your favorited stations
  • radio_session.json: Remembers last played station

editing Stations

example stations.jsonc with rich metadata:

// stations.jsonc
[
    {
        "name": "Sunshine Live - EDM",
        "urls": [
            "http://stream.sunshine-live.de/edm/mp3-192/stream.sunshine-live.de/",
            "http://stream.sunshine-live.de/edm/mp3-128/stream.sunshine-live.de/"
        ]
    },
    {
        "name": "Energy - Dance",
        "urls": ["https://edge01.streamonkey.net/energy-dance/stream/mp3"]
    }
]

🏗️ technical highlights

  • modern architecture: actor model with unidirectional data flow
  • audio engine: libmpv with optimized streaming configuration
  • ui framework: ncursesw with full unicode/emoji support
  • concurrency: std::atomic, mutexes, and condition variables
  • error handling: comprehensive exception safety
  • static analysis: clean reports from cppcheck and flawfinder

🙏 acknowledgements

  • radio browser api - for comprehensive station data
  • libmpv - robust media playback engine
  • ncurses - terminal UI foundation
  • nlohmann/json - JSON persistence
  • AI collaboration: the architecture, code, and documentation were heavily shaped through conversation with large language models, primarily Gemini 2.5 Pro and Claude 4 Sonnet.
  • all the radio stations - for keeping real, human-curated music alive.

📜 license

this project is licensed under the Mozilla Public License 2.0 (MPL-2.0).


the algorithm knows what you liked yesterday. radio knows what you'll love tomorrow.