Files
beefy-player/README.md
T

192 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Beefy Player
![beefy-player demo](assets/beefy-player-demo.gif)
A flashy terminal player for **internet radio** — a live spectrum analyser,
song history and album art, with desktop media integration on Linux and macOS.
It draws with your terminal's own ANSI palette on the terminal's default
background, so it fits any theme, including transparent terminals.
Thirteen station catalogues ship today, from SomaFM's curated channels to the
62,000-station Radio Browser directory, loaded as you scroll and searched live
as you type. Press `p` to switch catalogue without restarting.
## Features
- **Live spectrum analyser** — 72 log-spaced bands with peak caps, a palette
gradient and a mirrored spectrum. Six modes (`v`): mirrored bars, plain bars,
oscilloscope, scrolling waterfall, radial spectrum and a high-resolution
braille oscilloscope.
- **Synced to what you hear** — the analyser listens to your actual audio
output by default, so the bars follow the music. If that is unavailable it
falls back to decoding the stream, then to a simulated display.
- **Now playing and history** — artist, title, album, DJ, listeners, bitrate
and "played N minutes ago", plus the full recent history. A clickable
**Bandcamp ↗** link appears when the current track can be found there.
- **Real album art** — native images in Kitty, iTerm2 and WezTerm; an
ANSI-shaded mosaic in every other terminal.
- **Thirteen station catalogues** — SomaFM (≈50 channels), Radio Paradise,
tilderadio, Bassdrive, dublab, Rinse FM, Refuge Worldwide, LYL Radio, The Lot
Radio, Cashmere Radio, Datafruits, aNONradio and the Radio Browser directory
(loaded as you scroll in popularity order, with live search across all
62,000).
- **Favourites, search and schedules** — favourites float to the top and are
remembered between runs, including directory stations outside the loaded
page; search by title, genre or description, with live server-side search
across the Radio Browser directory; single-stream stations show their
broadcast schedule instead of a one-item list.
- **Desktop media integration** — MPRIS on Linux (GNOME/KDE widgets, lock
screens, `playerctl` and the media keys) and Now Playing on macOS (Control
Center and the media keys).
- **Sixteen palettes, theme-aware** — every colour is native ANSI against the
terminal's default background, so transparent terminals stay transparent and
the TUI follows your colour scheme. Press `c` to cycle palettes.
- **Graceful offline** — cached stations and schedules, a bundled fallback
list, automatic mirror failover and `ffplay` when `mpv` is missing.
## Installation
## Usage
```bash
beefy-player
```
The UI wants roughly **84×24**; it also works smaller, just less pretty.
| flag | what it does |
| --- | --- |
| `--provider <slug>` | pick a station catalogue |
| `--station <id>` | pick a station (see `--list`) |
| `--play` | tune the last station right away |
| `--list` | print station ids for the current catalogue |
| `--volume <0-100>` | set the initial volume |
| `--offline` | no network; use cached and bundled stations |
| `--no-audio` | UI demo without `mpv` / `ffmpeg` |
| `--no-mpris` | no MPRIS / Now Playing, no media keys |
| `--spectrum-source monitor\|stream` | force synced output capture or the stream tap |
Environment variables are prefixed `BEEFY_`: `BEEFY_IMAGES` (`tgp`, `iterm2`
or `0`), `BEEFY_MPV_ARGS` and `BEEFY_SPECTRUM_DEVICE`.
### Keys
| key | action |
| --- | --- |
| `↑` / `↓`, `j` / `k` | move through stations |
| `pgup` / `pgdn` | page through stations |
| `enter` | tune in to the selected station |
| `space` | play / pause |
| `s` | stop |
| `]` / `[` | next / previous station (tunes immediately) |
| `+` / `-` | volume |
| `m` | mute |
| `f` | favourite (favourites sort to the top) |
| `/` | filter by title, genre, description |
| `esc` | close the search box; press again to clear the filter |
| `v` | visualiser: mirror → bars → wave → waterfall → radial → braille |
| `c` | colour palette (16 of them, remembered) |
| `r` | refresh stations, schedule and song history |
| `p` | switch station catalogue |
| `g` / `G` | top / bottom |
| `?` | help |
| `q` | quit |
## Station catalogues
| catalogue | slug | stations |
| --- | --- | --- |
| [SomaFM](https://somafm.com) | `somafm` | ≈50 curated channels |
| [Radio Paradise](https://radioparadise.com) | `radioparadise` | 5 mixes |
| [tilderadio](https://tilderadio.org) | `tilderadio` | 1 + schedule |
| [Bassdrive](https://bassdrive.com) | `bassdrive` | 1 + schedule |
| [dublab](https://dublab.com) | `dublab` | 1 + schedule |
| [Rinse FM](https://rinse.fm) | `rinse` | 3 |
| [Refuge Worldwide](https://refugeworldwide.com) | `refuge` | 1 |
| [LYL Radio](https://lyl.live) | `lyl` | 1 |
| [The Lot Radio](https://thelotradio.com) | `lot` | 1 |
| [Cashmere Radio](https://cashmereradio.com) | `cashmere` | 1 |
| [Datafruits](https://datafruits.fm) | `datafruits` | 1 |
| [aNONradio](https://anonradio.net) | `anonradio` | 1 |
| [Radio Browser](https://www.radio-browser.info) | `radiobrowser` | 62k · paged + live search |
Pick one with `p` in the UI, `--provider <slug>` on the command line, or by
setting `"provider"` in the config file.
## Desktop media integration
**Linux** — while playing, the app exposes an
`org.mpris.MediaPlayer2.beefyplayer.instance<pid>` player on the session bus,
so GNOME/KDE widgets, lock screens, `playerctl` and the media keys pick it up:
```bash
playerctl -l
playerctl metadata --format '{{artist}} — {{title}} ({{album}})'
playerctl play-pause
```
If there is no session bus (SSH without `dbus-run-session`, containers, …)
MPRIS is skipped and the status bar shows `mpris off`.
**macOS** — mpv publishes to the system Now Playing session, so Control Center,
the menu bar and the media keys drive the app while it plays. The status bar
shows `nowplaying on`. `--no-mpris` (also spelled `--no-media`) turns the media
keys off.
> macOS shows one Now Playing app at a time. If Music, Safari or another mpv is
> playing, the media keys go there instead.
## Configuration
Settings live in `~/.config/beefy-player/config.json` (favourites, volume,
provider and the last station tuned in each catalogue). Cached stations,
schedules and artwork live in `~/.cache/beefy-player/`.
These stay in the usual XDG locations on every platform, macOS included;
`XDG_CONFIG_HOME` and `XDG_CACHE_HOME` are honoured when set.
## Troubleshooting
- **Artwork shows the mosaic?** Real images are auto-enabled for Kitty, iTerm2
and WezTerm. Force a protocol with `BEEFY_IMAGES=tgp` (Kitty) or
`BEEFY_IMAGES=iterm2` (iTerm2/WezTerm); `BEEFY_IMAGES=0` forces the mosaic.
`--diagnose-images` prints what was detected.
- **No audio?** `mpv` is preferred, `ffplay` works as a fallback. Without
either, the UI still runs and tells you. Extra mpv arguments can be injected
with `BEEFY_MPV_ARGS`, e.g. `BEEFY_MPV_ARGS='--audio-device=...'`.
- **Spectrum says `FFT` instead of `SYNC`?** Output capture is unavailable or
failed, so the analyser is decoding the stream instead; the bars are still
real audio but can drift. Force sync with `--spectrum-source monitor`, or
pick a specific monitor with `BEEFY_SPECTRUM_DEVICE` on Linux. `SIM` means the
bars are synthesized.
- **macOS: spectrum stays `FFT`?** Grant your terminal **System Audio
Recording** permission under *System Settings → Privacy & Security → System
Audio Recording*, then restart the app. Also check that mpv is playing to the
default output device, since that is what the analyser records.
- **macOS: media keys do nothing?** Another app owns the Now Playing session,
the app was started with `--no-mpris`, or audio fell back to `ffplay` (mpv is
required for Now Playing).
- **MPRIS says off?** There is no session bus. Run from your desktop session,
or use `dbus-run-session` for a private bus. macOS does not use MPRIS.
## Development
```bash
uv sync # create the environment
uv run pytest # test suite
uvx ruff check . # lint
```
Each catalogue is a self-contained provider module under
`beefy_player/providers/`; `base.py` documents the interface. `tools/ansi_art.py`
converts a PNG logo into half-block ANSI art. On NixOS, `shell.nix` provides an
FHS shell for the same `uv sync` / `uv run` workflow.
## Licence
WTFPL — Do What The Fuck You Want To Public License, Version 2. See
[LICENSE](LICENSE). SomaFM and its channel names are trademarks of
SomaFM.com, LLC. tilderadio belongs to the tildeverse community.
Terminal image rendering uses [Pillow](https://python-pillow.org/).