<div align="center">
# ✦ DriftFM ✦
**A cyber-synthwave internet radio player for your terminal.**
*Stream any radio station on Earth. Record tracks automatically. Never leave the command line.*
[](https://opensource.org/licenses/MIT)
[](https://www.rust-lang.org/)
[](#-installation)
[](#)
[](https://www.rust-lang.org/)
</div>
---

---
## What is DriftFM?
DriftFM is a **terminal internet radio player** with a retrowave soul, built in Rust. It works like any radio — tune in, listen, discover — but it lives entirely in your terminal, starts instantly, and uses a few megabytes of RAM.
It ships pre-loaded with handpicked synthwave, chiptune, and cyberpunk stations so it sounds great from the first keypress. But you can search, save, and play **any public internet radio station in the world**.
Think of it as: *VLC for internet radio, but it fits in your terminal and records tracks into named folders automatically.*
---
## What makes it different?
Most TUI radio players just wrap ffplay. DriftFM is purpose-built from scratch in Rust with features you'd otherwise only find in native desktop apps:
- 📡 **Search 30,000+ stations** from the global radio-browser.info catalog — by name, tag, or country
- 📼 **Automatic track recording** — press `r` and it captures tracks as separate files, named `Artist - Title.mp3`, tagged with ID3 metadata, sorted into genre subfolders
- 🧹 **Smart ad filtering** — DJ speech, news breaks, and commercial spots are detected and silently discarded. Only real music is kept.
- 🔊 **Smooth tuning transitions** — switching stations fades out the current stream and fades in the new one, like turning an analog dial
- 🎨 **5 built-in themes** — Retrowave (default), plus all 4 [Catppuccin](https://catppuccin.com/) flavors (Mocha, Macchiato, Frappé, Latte). Switch live in settings.
- 💾 **Favorites & history** — your stations are remembered between sessions, and the last-played station can auto-resume on launch
- 🔔 **Desktop notifications** — a silent system notification shows the current track when a new song starts
- 🎛️ **Resilient streaming** — a circular buffer absorbs network hiccups so your audio doesn't cut out when the connection stutters
---
## Installation
**Prerequisites:** [Rust & Cargo](https://rustup.rs/) (1.75+)
> On Linux, also install ALSA dev headers first:
> ```bash
> sudo apt-get install libasound2-dev # Debian/Ubuntu
> sudo dnf install alsa-lib-devel # Fedora
> ```
### From crates.io (recommended)
```bash
cargo install driftfm
```
### From source
```bash
git clone https://github.com/milgaj84/driftFM.git
cd driftFM
cargo run --release
```
That's it. No config files to write. No API keys. Stations are pre-loaded and the player starts immediately.
---
## How to use it
DriftFM is keyboard-driven. Press **`h`** at any time to see the full control reference.
The most important keys to get started:
| `↑` / `↓` | Move between stations |
| `Enter` | Play selected station |
| `Tab` | Switch genre categories |
| `/` | Search for any station worldwide |
| `Space` | Pause / Resume |
| `r` | Start / stop recording |
| `f` | In search: add to library. In library: remove station |
| `,` | Open settings |
| `q` | Quit |
---
## Workflow
**Finding and adding a new station:**
1. Press `/` to open search, type a genre, city, or station name — results come from the [radio-browser.info](https://www.radio-browser.info/) catalog of 30,000+ stations worldwide
2. Use `↑` / `↓` to browse results
3. Press `Enter` to tune in instantly — this also **automatically adds the station to your library** so it's there next time
4. Alternatively, press `f` on a search result to save it to your library without playing it yet
**Managing your library:**
- Your library is the main station list you see on launch
- To remove a station, highlight it in the main list and press `f`
- Switch between genre categories with `Tab` / `Shift+Tab` to browse the pre-loaded catalog
**Coming back tomorrow:**
- DriftFM remembers your library between sessions
- Enable *Auto-resume last station* in settings (`,`) and it starts playing where you left off automatically
---
## Recording
Press `r` while a station is playing. DriftFM will:
1. Wait for the next song boundary (so you never capture a partial intro)
2. Record each track to its own file in the **native stream format** — `recordings/Synthwave/Perturbator - Venger.mp3` or `.aac` depending on what the station broadcasts. No transcoding, no quality loss.
3. Embed the correct ID3 tags (artist, title, station name as album)
4. Discard anything under 90 seconds — DJ speech, ads, station IDs are swept automatically
5. Stop cleanly when you press `r` again
The minimum song duration and whether to keep short clips are configurable in the settings (`,`).
---
## Settings
Press `,` to open the settings panel. Current options:
- **Desktop notifications** — show track info when a song changes
- **Auto-resume last station on startup** — picks up where you left off
- **Tape capture folder** — cycle between preset recording directories
- **Keep partial snippets & ads** — whether short clips and non-music segments are kept or silently deleted
- **Min song duration** — threshold for auto-discarding short recordings (30s–180s). Only active when snippets filtering is ON.
- **Theme** — cycle between Retrowave, Catppuccin Mocha, Macchiato, Frappé, and Latte
Settings are saved automatically to a JSON file in your config directory.
---
## Platform Support
| Windows | ✅ Full support (native WASAPI audio) |
| Linux | ✅ Full support (ALSA) |
| macOS | ✅ Full support (CoreAudio) |
---
## Built with
*All native Rust — no ffmpeg, no Python, no Electron. A single self-contained binary.*
- [Ratatui](https://ratatui.rs/) — Terminal UI framework
- [Rodio](https://github.com/RustAudio/rodio) + [Symphonia](https://github.com/pdeljanov/Symphonia) — Audio decoding & playback (native, no ffmpeg dependency)
- [Tokio](https://tokio.rs/) — Async runtime for API search
- [reqwest](https://docs.rs/reqwest) — HTTP streaming with ICY metadata support
- [id3](https://docs.rs/id3) — ID3 tag injection into recorded files
---
## License
MIT — see [LICENSE](LICENSE) for details.