Skip to content

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

License

Notifications You must be signed in to change notification settings

antonl-dev/stream-hopper

Repository files navigation

🐇 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.