Skip to content

nevermore23274/AetherTune

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AetherTune

A terminal-based internet radio player with real-time audio visualization, built in Rust.

Rust License Release AUR PPA Homebrew

Overview

AetherTune is a TUI (terminal user interface) application that lets you browse, search, and stream internet radio stations directly from your terminal. It features a real-time spectrum visualizer driven by actual audio analysis, a rolling song log that captures ICY metadata, and live stream health monitoring.

AetherTune

Features

  • Station browsing — browse thousands of stations via the RadioBrowser API, filter by genre, search by name. Results are sorted by popularity with broken streams and spam filtered out automatically
  • Local blending — optionally configure your country code in Settings to blend ~30% local stations into every genre and search result, interleaved naturally with global results
  • Real-time audio visualization — 16-band spectrum analyzer using a sliding-window radix-2 FFT (~94 updates/sec) on captured PCM audio via PulseAudio/PipeWire monitor, with CAVA-inspired gravity fall-off, integral smoothing, and automatic sensitivity
  • Song log — automatically tracks song changes from ICY stream metadata with timestamps
  • Stream health monitor — live bitrate (actual vs advertised), buffer status, codec info, connection uptime
  • Favorites & history — save stations, track listening history, persisted to JSON
  • Customizable keybindings — remap every keyboard shortcut from the in-app settings overlay, persisted to your config
  • Built-in profiler — per-frame timing breakdown for performance tuning
  • Fallback mode — simulated visualizer when PulseAudio capture isn't available

Optional

  • Without parec, the app falls back to a simulated visualizer — everything else works normally.

Installation

Linux — Arch (AUR)
paru -S aethertune-bin

Or with yay: yay -S aethertune-bin

Dependencies (mpv, libpulse) are installed automatically. For real-time audio visualization, you also need pipewire-pulse or pulseaudio (one is likely already installed).

Linux — Ubuntu/Debian (PPA)
sudo add-apt-repository ppa:patchgoblin/aethertune
sudo apt update
sudo apt install aethertune

Currently available for Ubuntu Noble (24.04). Dependencies (mpv, libpulse0) are installed automatically. For real-time audio visualization, you also need pipewire-pulse or pulseaudio.

Linux / macOS — Homebrew

If you don't have Homebrew, install it first from brew.sh.

brew tap nevermore23274/aethertune
brew install aethertune

This will automatically install mpv as a dependency. On Linux, you'll additionally need pulseaudio-utils (or pipewire-pulse) for real-time audio visualization.

macOS note: Audio visualization uses a simulated mode (no real-time audio capture yet). Playback, station browsing, favorites, and all other features work normally.

macOS — Prebuilt binary

Download the latest .tar.gz for your architecture from the Releases page:

# Apple Silicon (M1/M2/M3/M4)
curl -LO https://github.com/nevermore23274/AetherTune/releases/download/VERSION/AetherTune-VERSION-macos-aarch64.tar.gz
tar xzf AetherTune-VERSION-macos-aarch64.tar.gz
./AetherTune-VERSION-macos-aarch64/AetherTune

# Intel
curl -LO https://github.com/nevermore23274/AetherTune/releases/download/VERSION/AetherTune-VERSION-macos-x86_64.tar.gz
tar xzf AetherTune-VERSION-macos-x86_64.tar.gz
./AetherTune-VERSION-macos-x86_64/AetherTune

Replace VERSION with the actual tag (e.g. v0.7.1). You'll need mpv installed — if you have Homebrew: brew install mpv.

macOS note: Audio visualization uses a simulated mode. Playback and all other features work normally.

Linux — Prebuilt binary

Download the latest .tar.gz from the Releases page:

curl -LO https://github.com/nevermore23274/AetherTune/releases/download/VERSION/AetherTune-VERSION-linux-x86_64.tar.gz
tar xzf AetherTune-VERSION-linux-x86_64.tar.gz
./AetherTune-VERSION-linux-x86_64/AetherTune

Replace VERSION with the actual tag (e.g. v0.7.1). You'll need mpv and parec installed on your system.

Nix / Flakes

If you use Nix with flakes enabled, you can run AetherTune directly:

nix run github:nevermore23274/AetherTune

To install permanently, add the flake input to your flake.nix:

inputs.AetherTune.url = "github:nevermore23274/AetherTune";

Then add the package to your system or user packages:

# NixOS (configuration.nix)
environment.systemPackages = [ inputs.AetherTune.packages.${system}.aethertune ];

# Home Manager
home.packages = [ inputs.AetherTune.packages.${system}.aethertune ];
Linux / macOS — From source

Requires Rust 1.85+ and mpv. On Linux, you'll also need pulseaudio-utils or pipewire-pulse for real-time audio visualization.

git clone https://github.com/nevermore23274/aethertune.git
cd aethertune
cargo build --release
./target/release/AetherTune
Windows

Download the latest .zip from the Releases page. The zip includes AetherTune.exe and mpv.exe bundled together — no separate installation needed.

  1. Extract the zip to a folder
  2. Open Windows Terminal (recommended) and navigate to the folder
  3. Run AetherTune.exe

Note: For the best experience, use Windows Terminal rather than cmd.exe. The legacy console has limited support for keyboard input and ANSI rendering that TUI apps rely on.

Windows limitations: Audio visualization uses a simulated mode (no real-time audio capture yet). Playback, station browsing, favorites, and all other features work normally.

All platforms — cargo install

If you have Rust installed, you can install directly from GitHub:

cargo install --git https://github.com/nevermore23274/AetherTune

This builds and installs the AetherTune binary to ~/.cargo/bin/. Make sure mpv is available on your system.

Usage

# Run normally (with CRT boot animation)
aethertune

# Skip the launch menu
aethertune --skip-menu

# Adjust boot animation speed (fast, normal, slow, off)
aethertune --boot-speed=fast

On Windows, run AetherTune.exe from Windows Terminal. If installed from source on Linux, use ./target/release/AetherTune.

Keybindings (Defaults)

Below is a list of default keyboard shortcuts. All keybindings can be remapped from the settings overlay (S). Press ? in the app to see your current bindings (Esc closes the overlay).

Key Action
/ or j / k Navigate station list
Enter Play selected station
s Stop playback
+ / - Volume up / down
/ Search stations
f Toggle favorite
i Station details overlay
n Load more stations
Tab Cycle panel (Stations / Favorites / History)
[ / ] Cycle genre category
Shift+Tab Cycle genre category (backward)
g Genre picker overlay
t Theme picker overlay
v Toggle visualizer on/off
? Help overlay
S Customize keybindings
` Performance profiler
< / > Adjust tick rate (when profiler is open)
{ / } Adjust visualizer smoothing (when profiler is open)
q Quit

Settings

AetherTune has a settings screen accessible from the launch menu, and a keybinding settings overlay accessible during playback. Settings are persisted to ~/.aethertune/config.json.

Country Code

Set a two-letter ISO 3166-1 Alpha-2 country code (e.g. US, DE, GB, JP) to blend local stations into your results. You can find your country code in the full list on Wikipedia. When configured, roughly 30% of stations in each genre and search result will come from your country, interleaved naturally with global results sorted by popularity.

To configure: launch AetherTune → select Settings from the menu → type your two-letter country code → press Enter to save.

Leave the country code empty (backspace to clear) for pure global results — this is the default.

Keybindings

Every keyboard shortcut can be remapped. Press S during normal playback to open the keybinding settings overlay.

Themes

Press t to open the theme picker. AetherTune ships with 8 built-in themes:

  • CRT — the default phosphor terminal aesthetic (cyan/magenta/neon green)
  • Gruvbox — warm retro palette
  • Nord — cool arctic blues
  • Dracula — dark purple
  • Monokai — classic editor colors
  • Catppuccin — pastel dark
  • Hacker — green-on-black matrix style
  • Solarized — precision colors for readability

Themes apply to the player UI only (not the launcher or exit animation). Your selection is persisted to ~/.aethertune/config.json. The theme picker shows live color swatches and previews each theme as you navigate.

In the overlay:

  • ↑/↓ — navigate the action list
  • Enter — rebind the primary key (press any key to assign)
  • a — rebind the alternate key
  • d — clear the alternate key
  • r — reset a single action to its default
  • R — reset all keybindings to defaults
  • Esc or S — close the overlay

Each action supports a primary key and an optional alternate key. Changes are saved immediately to config.json and the help overlay (?) always reflects your current bindings. The header bar hints also update dynamically.

Only non-default keybindings are written to the config file to keep it clean. A fresh config with customized bindings looks like:

{
  "tick_rate_ms": 30,
  "volume": 50,
  "country_code": "US",
  "theme": "CRT",
  "visualizer_enabled": true,
  "keybindings": {
      "quit": ["x"],
      "search": ["Space"]
  }
}

Architecture

src/
├── main.rs                   Entry point, event loop, frame timing
├── app.rs                    App state, business logic, perf stats
├── audio/
│   ├── player.rs             mpv playback, IPC, parec capture, stream info
│   ├── pipe.rs               FIFO creation, PCM reader thread, radix-2 FFT, SeqLock
│   └── visualizer.rs         Bar animation (real + simulated modes)
├── storage/
│   ├── config.rs             User preferences (tick rate, volume, country code, keybindings)
│   ├── favorites.rs          JSON persistence for favorites
│   └── history.rs            JSON persistence for play history
└── ui/
    ├── mod.rs                Layout orchestration
    ├── helpers.rs            Color palette, shared widgets
    ├── launcher.rs           CRT boot animation, start menu, settings screen
    ├── header.rs             Top bar (LIVE indicator, genre, hints)
    ├── station_list.rs       Left panel (stations/favorites/history)
    ├── now_playing.rs        Station info + session timer
    ├── song_log.rs           Rolling ICY metadata log
    ├── visualizer.rs         Spectrum bar rendering
    ├── stream_info.rs        Live stream health panel
    ├── media_browser.rs      Media source switcher (Radio/Subsonic stub)
    ├── overlays.rs           Help + station detail popups
    ├── genre_picker.rs       Genre selection overlay
    ├── theme_picker.rs       Theme selection overlay
    ├── themes.rs             Color theme definitions (8 built-in themes)
    ├── settings.rs           Keybinding settings overlay
    ├── shutdown.rs           CRT power-off animation on quit
    └── perf_overlay.rs       Built-in performance profiler

Audio visualization pipeline

When parec is available, AetherTune captures audio through the PulseAudio/PipeWire monitor source:

  1. mpv plays audio normally through the default audio output
  2. parec captures the monitor source and writes raw s16le stereo 48kHz PCM to a named FIFO
  3. A background thread reads the FIFO using a sliding window — 512 new samples (~10.7ms) at a time, shifted into a 1024-sample buffer — then runs an in-place radix-2 Cooley-Tukey FFT with Hann windowing. This produces ~94 FFT updates/sec (2× the rate of full-chunk reads) without sacrificing frequency resolution. The 512 frequency bins are grouped into 16 logarithmically-spaced bands (50Hz–10kHz). FFT buffers, window coefficients, and band edges are all pre-allocated at thread startup for zero per-frame heap allocation.
  4. Band energies and RMS are published via a lock-free sequence lock (SeqLock<AudioAnalysis>) — the reader thread writes without blocking, and the render thread always reads the latest consistent snapshot with no contention
  5. The visualizer applies CAVA-inspired post-processing: gravity fall-off (accelerating drop), integral smoothing (weighted running average), and automatic sensitivity adjustment

Process isolation is handled carefully: parec runs in its own process group via setsid(), and cleanup uses kill(-pgid, SIGTERM) to ensure no orphaned processes.

Data persistence

Favorites, history, and user preferences (tick rate, volume, country code, keybindings) are stored as JSON in ~/.aethertune/. The serializer/parser is hand-rolled (no serde dependency) to keep the dependency tree minimal. Settings like tick rate and keybindings are saved automatically when adjusted and restored on next launch. The country code is configured via the Settings screen in the launch menu. Only non-default keybindings are persisted to keep the config file clean.

Contributing

See docs/CONTRIBUTING.md for build instructions, project structure, and how to submit PRs.

Performance Tuning

AetherTune has a built-in per-frame profiler. See docs/PROFILING.md for how to read the profiler and tune performance for your system.

License

MIT

About

A terminal-based internet radio player with real-time audio visualization, built in Rust.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages