music on console terminal — player · CD ripper · radio & podcasts
A keyboard-driven terminal music player, CD ripper, internet-radio and podcast client for Windows and Linux, inspired by MOC. Two-pane layout, no mouse, no stutter. All heavy I/O stays off the main thread, every shared state is explicitly protected, and no volatile CD or hardware path ever leaks into persistent config.
Windows (MSYS2 UCRT64) · Linux (Debian Trixie) · MIT-style build from source
44.1 kHz -> 48.
The answer is often not the one you would guess: on the Windows machine this was developed on
every output runs at 48 kHz, so every CD rip had been quietly converted for years while a 48 kHz
Opus file went through untouched. On the Linux machine the same library gives the opposite
answer. It is a fact about your output device, not your collection.
?, one per
character; they now render as written, and accented Latin keeps its accents. A CD that matches
several releases, or a set where two discs share a track count, is no longer decided silently
— RE-MOCT asks, and says so when it had to guess. The rip screen shows the cover art before
it writes anything.
Ctrl+R names it from MusicBrainz.
Classic mode is a faithful MOC homage. Ctrl+T is the remix. That toggle is the whole thesis.
Minimal, monochrome, exactly the console player you remember. Toggle to Awesome with Ctrl+T. Nothing moves that doesn't have to.
A comet progress bar, a sub-cell block visualizer, breathing animations, and 18 named truecolor palettes cycled with F7 / F8. The 256-color visuals shine on a Linux terminal.
Your output device has a rate of its own, and if it differs from the track something converts the audio on the way out. The status line now says so: 44.1 kHz -> 48. Nothing about the sound changed — what changed is that you can see it. It shows whether or not you turn anything on, because it is true either way. A blank means the rates match, not that nothing was touched.
bit_perfect=1 in remoct.conf, off by default, lossless files only. RE-MOCT takes exclusive control of the output and hands it your samples untouched — and checks rather than assumes. An audio system will grant exclusive access and then convert anyway, so RE-MOCT compares what the device is actually running against what it asked for and hands it back if they differ. = appears only when the output really is untouched.
The rip screen renders the cover art it is about to use, before anything is written. P opens everything the Cover Art Archive holds for that release — often dozens of images on a box set, including each disc’s own artwork and booklet pages — with a preview beside the list. F5 changes the release without leaving the screen, for when the cover tells you the release itself is wrong.
A stream that lost its connection used to show [BUFFERING] forever, whether it was about to recover or had given up ten minutes earlier. Now one that cannot recover stops and says why. Short drops go the other way: buffered audio plays out while the connection returns, so a brief outage is often inaudible. Recovery no longer replays seconds you already heard, and a recording running when a stream dies is finalized rather than left open.
水田直志 is 水田直志, not ????. Japanese, Chinese, Korean, Greek and Cyrillic render as written, and accented Latin keeps its accents — Müller, not Muller. Double-width characters get the two columns they need, so rows still line up. The same text goes out to Last.fm and ListenBrainz, and the tag editor no longer flattens it on save.
A CD can match several releases, and a set can have two discs with the same number of tracks. Ctrl+R asks instead of choosing silently, showing what disc number each release would give you before you pick. When two discs of a set tie, it lists the first track of each so you can tell them apart. F5 reopens the list if you change your mind.
A disc RE-MOCT could not identify confidently is marked on screen, recorded in the rip log and in disc.json, and is not scrobbled at all. A guess can be shown; it should not become a permanent record. Ripped files now carry a disc number in their tags too, rather than only in the folder name.
The rip screen renders the cover art it is about to use, so you see it before anything is written. P opens everything the Cover Art Archive holds for that release — often dozens of images on a box set, including each disc’s own artwork and booklet. F5 changes the release without leaving the screen.
A disc with audio hidden in the pregap gets a row above track 1 and an +1 HTOA marker in the playlist header — the disc’s own track count stays what the disc says. Enter plays it like any CD track, and it scrobbles and counts as a play. Mark it with u to rip it as its own file; a whole-disc rip never sweeps it up. Ctrl+R reads its title from MusicBrainz, Ctrl+F from Discogs. Detection is from the table of contents, so it is instant on insert with no read required.
A [Library] section listing every artist in your music folder, however the folders are arranged — artists, albums, tracks. The directory browser is unchanged and still where everything starts; this sits beside it for when you know the artist and not the folder. First open reads your tags and shows its progress; after that it opens instantly and only re-reads files that changed. F12 rescans, Esc cancels a scan without touching the index you already had.
Press | and the list narrows as you type — across every track you have, not the folder in front of you. Matches title, artist, album, album artist, genre and filename, so an untagged rip is still findable by name. Accents work the way you would want: bjork finds BJÖRK, dvorak finds Dvořák.
Mark tracks with u and RE-MOCT rips just those; U clears the marks. Mark nothing and ripping behaves exactly as it always has. A partial rip leaves out what cannot honestly be written for part of a disc — no cue sheet, no album volume level — and says which and why in its log.
g lists your genres, folding Post Punk and Post-Punk into one row without splitting Hip-Hop into two. % shows most-played with counts, again for everything you have never played, again to go back.
Next track pre-decodes into a second buffer while the current one plays. Seamless transitions, configurable crossfade, and the queue overrides crossfade correctly.
Rips to any mix of FLAC, MP3, WAV, Opus, WavPack, and M4A from a single verified disc read, with per-track AccurateRip v1/v2 verification, drive offset correction, and a CUETools DB cross-check.
Eject from the keyboard with Shift+E, refresh the drive list for hot-plugged drives with F12, and stop a CD without unloading the disc.
Press x to convert a file, a folder, a marked set, or a whole playlist (the current pane or the tracks a playlist file references) to FLAC, MP3, WAV, Opus, WavPack, or M4A. Tags and embedded cover art carry over; conversion runs in the background and never overwrites the source.
Record a radio stream with Ctrl+E, cut and tagged per track from the station's own metadata. Record to Opus, MP3, M4A, or Copy mode (the exact broadcast bytes, no re-encode), with ad-aware routing and cover art on each cut.
RE-MOCT appears in the system media surface — SMTC on Windows, MPRIS on Linux — so the media keys, lock screen, and desktop widgets drive playback and show the now-playing card.
Press \ to search a long playlist by artist or title and jump straight to a match, or pick from a list when several match. Same key shifted, | searches your whole collection instead of the list in front of you.
ICY, HLS, and iHeart with live now-playing metadata. Station search via radio-browser.info. Shipped as a loadable plugin.
A [Podcasts] section alongside radio and books. Subscribe by pasting a feed URL or searching the Podcast Index, browse episodes with per-episode state, stream or download for offline, and resume where you left off. Episode chapters — embedded or published by the feed — show with ;.
Multi-band EQ with presets, adjusted live from the right pane. Press e.
Real-FFT spectrum analyzer rendered as sub-cell blocks straight into the terminal grid — accurate across the full range, reflecting each track's actual mastering. Press v.
Synced .lrc lyrics scroll with playback. Built-in tag editor writes through TagLib, and reports honestly when a file can't be written.
Embedded art or fetched from Cover Art Archive, iTunes, and Deezer. Rendered in-terminal as truecolor half-blocks.
Last.fm and ListenBrainz scrobbling, plus Discord Rich Presence over named-pipe IPC. Sensitive credentials are protected at rest — DPAPI on Windows, machine-keyed obfuscation on Linux.
Reads ReplayGain tags and normalizes volume. Toggle with f.
Tape-style speed from 50% to 200% — pitch moves with it, the way a turntable does. Stereo balance with < / >.
Background BPM analysis on track load, surfaced in the track info pane.
15 / 30 / 45 / 60 / 90 minute auto-stop, cycled with Z, shown in the title bar.
Plays:
Rips & converts to:
Records radio to: .opus .mp3 .m4a copy · Playlists: .m3u .m3u8 .pls .xspf
Every ripped track is checksummed and matched against the AccurateRip database. The 150-sector preamble is honoured as a fixed physical property of the disc — a constant stripped from every absolute LBA, never normalized relative to the first track — so pressings with non-standard pregaps verify correctly instead of silently missing.
Track Status Conf CRC (v2) ───── ──────────── ──── ───────── 01 AccurateRip 200 8b4a1c7e 02 AccurateRip 200 d3f09a12 03 AccurateRip 200 6e21bb4f ... 12/12 verified
Every platform-specific capability sits behind a seam with a Windows and a Linux implementation — HTTP, IPC, notifications, CD access, plugin loading. The core is portable; the platform difference is resolved by CMake at build time, never by branching in the code.
The streaming source is a real loadable plugin (remoct_stream.so / remoct_stream.dll) driven through a frozen C ABI, with HTTP injected across a host-services table. A radio fix ships as a rebuilt plugin with no host rebuild. A deterministic test asserts the loaded plugin produces byte-identical audio to the compiled-in reference — so "swap the plugin" never means "hope it still matches."
Grab a build from GitHub Releases, or build from source. Single-header dependencies (miniaudio, nlohmann/json) and the vendored MD5 are checked in — no separate download step.
git clone https://github.com/RadMageIRL/re-moct cd re-moct cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release cmake --build build ctest --test-dir build --output-on-failure
Output lands in build/bin/remoct (or remoct.exe), with the streaming plugin beside it in build/bin/plugins/. Full per-platform instructions — including the Debian non-free enablement for FDK-AAC — are in BUILD.md.
Everything else is in the documentation.