A terminal-based music player (TUI) for streaming services, currently supporting Subsonic-compatible APIs and YouTube Music. Spotify, Apple Music, and other services are future features.
Note
This project is not supported or endorsed by any streaming music service or major company. It is a hobby project and has no affiliation with Spotify, Apple, Google, or YouTube. The same warnings and disclaimers for the well-known yt-dlp project apply here.
- TUI Interface: Built with Terminal.Gui for a rich console experience.
- Cross-Platform Audio: Powered by SoundFlow.
- YouTube Music Integration: Powered by YouTubeMusicAPI. Search, stream, and manage your library.
- Subsonic API Integration: Streaming client for any Subsonic-compatible server. For instance, Navidrome, Airsonic Advanced, Gonic, or Madsonic.
- Visuals: Displays album art using Sixel graphics (requires a compatible terminal).
While most basic functionality is available and SMoC is totally usable, there's a lot left to do.
Feature Plan (Click to expand)
- UI
- Search Support
- Command Bar
- Song Table
- Now Playing Bar
- Album Art (Sixel)
- Status Bar
- Visualizations
- Now Playing Screen
- Playback
- Play
- Pause
- Stop
- Skip
- Previous
- Start Over
- Repeat Track
- Volume
- Playback Device Selection
- Gapless Playback
- Queue
- Add to End of Queue
- Queue Next (after current song)
- Remove
- Advance to Next at End of Song
- Repeat Queue
- Shuffle
- Search
- Artist
- Track
- Playlist
- URL
- YouTube Music
- Authentication
- POToken
- VisitorData
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Subsonic API-compatible Servers
- Authentication
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Apple Music (gamdl as a reference)
- Authentication
- Play Audio Stream
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Spotify (librespot as a reference)
- Authentication
- Play Audio Stream
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
Once installed some setup is required to use SMoC. See the Configuration and Setup section for more information.
Current release is v0.1.0.
Available for Windows x64, Linux x64, and MacOS ARM64.
SMoC is available via my overlay. To install, add my overlay and emerge it.
eselect repository add razza git https://github.com/mrazza/razza-overlay.git
emerge media-sound/smoc
# Clone the repository
git clone https://github.com/mrazza/smoc.git
cd smoc
# Build and run
dotnet run --project smoc/smoc.csprojSMoC operates with a Vim-style command bar. Press : to enter command mode.
| Command | Description |
|---|---|
:a |
Switch to Artist mode |
:a/<artist> |
Switch to Artist mode and search for <artist> |
:t |
Switch to Track mode |
:t/<track> |
Switch to Track mode and search for <track> |
:p |
Switch to Playlist mode |
:p/<playlist> |
Switch to Playlist mode and search for <playlist> |
:likes |
Load your Liked Songs playlist |
:url |
Switch to Playlist mode from URL |
:url/<url> |
Load songs from a specific YouTube Music URL |
:pq |
View the Playback Queue |
:np |
View Now Playing screen |
:v/<0-100> |
Set volume (e.g., :v/80) |
:q |
Quit application |
| Hotkey | Action |
|---|---|
Space |
Play / Pause |
Ctrl+Space |
Stop |
, (Comma) |
Previous Track (Restart if > 10s played) |
. (Period) |
Next Track |
[ |
Seek Backward 10s |
] |
Seek Forward 10s |
Up/Down/Left/Right |
Navigate Tables |
h/j/k/l |
Navigate Tables (Vim style) |
Tab |
Switch active pane |
Enter |
Open action menu for selected item |
SMoC stores configuration and authentication data in ~/.config/smoc/ (on Linux).
To use a Subsonic-compatible service (like Navidrome, Gonic, or Airsonic):
- Ensure your server has the Subsonic API enabled.
- Configure your server hostname, port, scheme, username, and password in
config.json(see below). - Set
SmocConfiguration.ActiveServicetoSubsonic.
To use YouTube Music:
- Set
SmocConfiguration.ActiveServicetoYouTubeMusic. - Setup required settings for YouTube Music authentication (see below).
Note
You need a YouTube Music Premium subscription to play most content.
To access your YouTube Music account, you need to extract your cookies from YouTube Music (these steps are copied from YouTube.js):
- Open YouTube Music in your browser (Incognito recommended).
- Open Developer Tools (
F12) -> Network tab. - Find a
POSTrequest tomusic.youtube.com. - Copy the value of the
cookierequest header. - Save it to
~/.config/smoc/cookie.txt.
Tip
It is recommended to open an incognito window or separate browser profile when getting your cookie information to avoid other browser sessions from invalidating the tokens. Once cookies are retrieved, close the session without logging out.
More recently, additional tokens beyond just cookies are often needed. POToken and Visitor Data are required in the tokens.json file in the same directory as your cookie.txt.
Tip
Run smoc --gentokens after setting up the cookie to generate necessary PO Tokens and Visitor Data automatically.
Create or edit ~/.config/smoc/config.json to customize settings.
Example Configuration (Click to expand)
{
"SmocConfiguration.LogLevel": "Warning",
"SmocConfiguration.SongCacheSizeBytes": 1073741824,
"SmocConfiguration.AlbumCoverCacheSizeBytes": 1073741824,
"SmocConfiguration.SongCacheMaxElements": 1000,
"SmocConfiguration.AlbumCoverCacheMaxElements": 1000,
"SmocConfiguration.ActiveService": "Subsonic",
"SubsonicConfig.ServerHost": "localhost",
"SubsonicConfig.ServerPort": 8080,
"SubsonicConfig.Username": "username",
"SubsonicConfig.Password": "password",
"Theme": "gruvbox-custom",
"Themes": [
{
"gruvbox-custom": {
"Schemes": [
{
"Accent": {
"Normal": { "Foreground": "#ebdbb2", "Background": "#00000000" },
"Focus": { "Foreground": "#ebdbb2", "Background": "#639494" },
"Active": { "Foreground": "#ebdbb2", "Background": "#394e4e" }
}
}
// ... (other schemes)
]
}
}
]
}| Category | Key | Type | Description |
|---|---|---|---|
| Streaming | SmocConfiguration.ActiveService |
StreamingService |
Active service (YouTubeMusic, Subsonic) |
| Subsonic | SubsonicConfig.ServerScheme |
string |
URI Scheme for the Subsonic API (default: http) |
SubsonicConfig.ServerHost |
string |
Hostname of your Subsonic server | |
SubsonicConfig.ServerPort |
int |
Port of your Subsonic server (default: 80) | |
SubsonicConfig.Username |
string |
Subsonic username | |
SubsonicConfig.Password |
string |
Subsonic password | |
SubsonicConfig.UseToken |
bool |
Whether to use token auth instead of plaintext password (default: true) | |
| Caching | SmocConfiguration.SongCacheSizeBytes |
long |
Max size of song cache in bytes (0 = no limit) |
SmocConfiguration.AlbumCoverCacheSizeBytes |
long |
Max size of album cover cache in bytes (0 = no limit) | |
SmocConfiguration.SongCacheMaxElements |
int |
Max number of songs to cache (0 = no limit) | |
SmocConfiguration.AlbumCoverCacheMaxElements |
int |
Max number of album covers to cache (0 = no limit) | |
| Logging | SmocConfiguration.LogLevel |
LogLevel |
Min log level (Trace, Debug, Information, Warning, Error, Critical) |
| Listen History | ListenHistory.Enabled |
bool |
Whether listen history tracking is enabled |
ListenHistory.MinimumPositionSeconds |
int |
Minimum position (seconds) to consider listened | |
ListenHistory.MinimumFraction |
double |
Minimum fraction of a song to consider listened | |
| UI | Theme |
string |
The name of the theme to use (default: default) |
If specifying a custom theme (as in the example config above), you will need to specify styling for all schemes.
Example Theme (Click to expand)
{
"Theme": "gruvbox-custom",
"Themes": [
{
"gruvbox-custom": {
"Schemes": [
{
"Accent": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#00000000"
},
"Focus": {
"Foreground": "#ebdbb2",
"Background": "#639494"
},
"Active": {
"Foreground": "#ebdbb2",
"Background": "#394e4e"
}
}
},
{
"Base": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#00000000"
}
}
},
{
"TableCurrentTrack": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#394e4e",
"Style": "Bold"
},
"Focus": {
"Foreground": "#ebdbb2",
"Background": "#639494",
"Style": "Bold"
},
"Active": {
"Foreground": "#ebdbb2",
"Background": "#394e4e",
"Style": "Bold"
}
}
},
{
"TableNormalTracks": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#00000000"
},
"Focus": {
"Foreground": "#ebdbb2",
"Background": "#639494"
},
"Active": {
"Foreground": "#ebdbb2",
"Background": "#394e4e"
}
}
},
{
"Menu": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#3a3a3a"
},
"Focus": {
"Foreground": "#ebdbb2",
"Background": "#639494"
},
"Active": {
"Foreground": "#ebdbb2",
"Background": "#394e4e"
}
}
},
{
"StatusBar": {
"Normal": {
"Foreground": "#949494",
"Background": "#3a3a3a"
}
}
},
{
"StatusBar_Mode": {
"Normal": {
"Foreground": "#262626",
"Background": "#949494",
"Style": "Bold"
}
}
},
{
"CommandLine": {
"Normal": {
"Foreground": "#ebdbb2",
"Background": "#00000000"
},
"Editable": {
"Foreground": "#ebdbb2",
"Background": "#00000000"
}
}
},
{
"CommandLineError": {
"Normal": {
"Foreground": "#262626",
"Background": "#d75f5f",
"Style": "Bold"
}
}
}
]
}
}
]
}Contributions are welcome!
- Code Style: We follow the Google C# Style Guide.
- Commits: Please use Conventional Commits.
Distributed under the Apache-2.0 License. See LICENSE for more information.
