naviterm is a terminal user interface client for Navidrome written in Rust. It is an online client, meaning that it does not download music files for offline playing. It does maintain an offline database for faster operation. Navidrome uses the Subsonic API, so naviterm should be compatible with other music server programs using it, at least in theory. It uses the fantastic mpv as backend for the music playback. For the tui, ratatui has been chosen.
I was a happy user of the classic Linux music combo: ncmpcpp and mpd. But then I discovered the benefits of using a dedicated server tool to manage my music collection with Navidrome. There are many different clients for several platforms, and I used Feishin. I liked the "home" tab UI, similar to other popular music platforms as Spotify. However, it is a heavy client and a bit slow for my taste, I longed for ncmpcpp and its quick terminal user interface. This project is my attempt to have the best of both worlds.
⚠️ naviterm is now in a beta stage. I use it in a daily basis but bugs can occur.
- Home page with recently added/played albums, most played album/songs.
- Explore your music database with the album, playlist and artist panes.
- Global search for your songs, albums, playlists and artists.
- Add, edit, or delete playlists. Sync them with your server.
- Full MPRIS support using the amazing zbus.
- ReplayGain support
- Scrobbling of played media to your server.
Here you can find the possible installation methods. Please note that if you install from source or use a provided binary, you will need a working version of mpv in your path.
Naviterm is available in the ArchLinux AUR: naviterm-bin
Head over to the releases page and download the latest one. Then, extract the contents and copy the binary to your desired path, for instance:
tar -xzf naviterm_amd64_X_Y_Z.tar.gz
sudo cp target/release/naviterm /usr/bin/Run directly:
nix run "gitlab:detoxify92/naviterm"Add to your NixOS config:
Add the flake to your inputs.
{
inputs = {
...
naviterm = {
url = "gitlab:detoxify92/naviterm";
inputs.nixpkgs.follows = "nixpkgs";
};
}
...
}Then add the package to your environment.systemPackages or home.packages.
{pkgs, inputs, ...}: {
...
environment.systemPackages = [
...
inputs.naviterm.packages.${pkgs.system}.default
];
}Supported platforms: x86_64-linux and aarch64-linux.
You don't need to install mpv separately when using the flake.
First, clone this repository and switch to the desired branch: main for latest release or develop for unstable. Then run the following commands in the cloned directory:
cargo buildThat should build the executable at CLONED_DIR/target/debug/naviterm. This can be useful for testing local changes. If a more permanent installation is desired, one can do:
cargo build --release
sudo cp target/release/naviterm /usr/bin/This would generate a more lightweight executable, and it can be placed anywhere in your PATH for convenient access to the executable.
A configuration file is needed for the program to start. It must be at ~/.config/naviterm/config.ini, and should have the following items:
| Parameter | Definition | Default | Mandatory |
|---|---|---|---|
| server_address | The address your server is running in, including the path. It should have the following format (note no trailing slash): http(s)://name-or-ip/navidrome |
- | Yes |
| user | Your user in Navidrome | - | Yes |
| password | The password for the user (only used if password_store=plain) | - | No |
| password_store | Storage method for the password (plain, secretservice) | plain | No |
| server_auth | The authentication method to use, to choose from plain or token | token | No |
| mpv_path | The path to the mpv executable. If left empty, Navidrome will try to use mpv from $PATH |
mpv | No |
| replay_gain | The replay gain mode. The possible values are: track, album, auto | track | No |
| primary_accent | The primary accent color to be used. Possible values: rgb hex (#ffffff), ANSI colors as used by ratatui | yellow | No |
| secondary_accent | The secondary accent color to be used. Possible values: rgb hex (#ffffff), ANSI colors as used by ratatui | gray | No |
| home_list_size | The size of the lists for the home pane (recently listened, recently added, most listened albums and tracks). | 30 | No |
| follow_cursor_queue | Whether the cursor will follow the currently playing track in queue | true | No |
| draw_while_unfocused | This flag controls whether the program will update its ui if the window loses focus. Setting to true could increase CPU usage. | false | No |
| save_player_status | Whether to save player status to disk. This includes the queue data, loop and random playback status, and volume level. | false | No |
| use_dbus | Whether to use dbus or not. Disabling this can be helpful for MacOs users. | true | No |
| wait_for_ipc_ms | Amount of time to wait before retrying to connect to the mpv process in ms. | 200 | No |
| mpv_custom_args | Custom arguments for mpv, in a comma separated list (--arg1=value,--arg2=value,etc). | [] | No |
| album_list_api | Version of the getAlbumList REST API to use. Navidrome uses v1 but other server applications might need to use v2. | v1 | No |
| reorder_random_queue | Show the actual queue order when in random playback. | false | No |
| parser_type | The parser type to use with subsonic requests, to choose from json or xml. |
json | No |
The config file has to be a ini config file:
server_address=https://your-navidrome-instance.com/navidrome
user=joe
password=secret_pass
password_store=plain
server_auth=token
mpv_path=/usr/bin/mpv
replay_gain=auto
primary_accent=yellow
secondary_accent=gray
home_list_size=30
follow_cursor_queue=true
draw_while_unfocused=false
save_player_status=false
use_dbus=true
wait_for_ipc_ms=200
mpv_custom_args=
album_list_api=v1
reorder_random_queue=false
parser_type=jsonShortcuts can also be configured. Refer to the Shortcuts section for more information.
If your config file is correct, the program should start and begin building a local database of your music collection, which will be stored at ~/.config/naviterm/database.bin. Please wait until is finished. After that you can start using naviterm to play some music!
In case of using the secretservice password storage, the program once asks for the password before startup.
This section includes lists of all shortcuts you can use in the app, heavily Vim inspired (media keys shortcuts have not been included, as they are self-explanatory). Most of them can be configured to your liking by using the key in the config file and assigning a new shortcut like mod_key:
go_pane_home=ctrl_1Valid modifiers are ctrl|alt|super, valid keys should include all ASCII characters. Please note the following considerations:
- To use a blank space as a key, use the word
space. - For other special keys, use the following mapping:
- Up,down,left and right arrows:
up,down,left,right - Enter:
enter - Home, end:
home,end - PageUp, PageDown:
pageup,pagedown - Tab:
tab - Escape:
esc - Function keys F1 to F9:
f1..f9
- Up,down,left and right arrows:
- To use a single quote or double quote char, escape it with a backwards slash:
\'or\".
| Shortcut | Key in config | Description |
|---|---|---|
1,2,3,4,5 |
go_pane_home, go_pane_albums, go_pane_playlists, go_pane_artists, go_pane_queue |
Navigate to corresponding pane |
j,k |
move_list_down, move_list_up |
Move the cursor down, up |
g,G |
move_to_first, move_to_last |
Move the cursor to the first, last element in list |
<Ctrl-d>,<Ctrl-u> |
move_page_down, move_page_up |
Move the cursor down, up by 5 elements |
q |
quit_application |
Quit the program |
<Tab> |
cycle_subpane |
Cycle through sub-panes |
<Ctrl-h><Ctrl-l> |
move_pane_left, move_pane_right |
Move to the sub-pane to the left,right |
<Enter> |
play_immediately |
Start playing item immediately |
/ |
search_start |
Start search |
<Enter> |
search_accept |
Confirm the entered term to allow navigating the results |
n | N |
search_next, search_previous |
Cycle through search results in one direction or the other |
<ESC> |
Cancel and clears the search | |
l |
cycle_loop_mode |
Cycle through loop playing modes |
<space> |
toggle_play_pause |
Toggle play-pause |
o |
stop_playback |
Stop playback |
z |
toggle_random |
Toggles random playback on/off |
<Right> |
seek_forward |
Seek 10s forward |
<Left> |
seek_backwards |
Seek 10s backwards |
<Up> |
volume_up |
Increase the volume |
<Down> |
volume_down |
Decreases the volume |
u |
go_popup_update |
Open Update Database popup |
<Ctrl-f> |
go_popup_global_search |
Open Global Search popup |
| Shortcut | Key in config | Description |
|---|---|---|
<F1> |
go_popup_test |
Open Connection Testing popup |
<Ctrl-j><Ctrl-k> |
move_pane_down, move_pane_up |
Move to the sub-pane up,down |
i |
go_popup_info |
Open the Album Information popup of the selected item |
a |
go_popup_add_item_to |
Open the Add To popup for the selected item |
| Shortcut | Key in config | Description |
|---|---|---|
A |
go_popup_add_parent_to |
Open the Add To popup for whole album of selected item |
a |
go_popup_add_item_to |
Open the Add To popup for the selected item |
i |
go_popup_info |
Open the Album Information popup of the selected item |
e |
go_popup_genre |
Open the Genre Filter popup |
y |
go_popup_year |
Open the Year Filter popup |
m |
toggle_album_sort_method |
Toggle the sorting mode: alphabetical, most played |
r |
toggle_album_sort_order |
Toggle the sorting direction: ascending, descending |
| Shortcut | Key in config | Description |
|---|---|---|
J,K |
playlist_move_selected_down , playlist_move_selected_up |
Move the selected song item in playlist down, up |
A |
go_popup_add_parent_to |
Open the Add To popup for whole playlist of selected item |
a |
go_popup_add_item_to |
Open the Add To popup for the selected item |
s |
go_popup_sync_playlist |
Open the Synchronize Playlist popup |
d |
go_popup_delete_playlist |
Open the Delete playlist popup |
d |
playlist_delete_item |
Deletes the selected song from playlist (without confirmation) |
| Shortcut | Key in config | Description |
|---|---|---|
A |
go_popup_add_parent_to |
Open the Add To popup for whole album of selected item |
a |
go_popup_add_item_to |
Open the Add To popup for the selected item |
| Shortcut | Key in config | Description |
|---|---|---|
a |
queue_go_to_album |
Go to album of the selected queue item in Albums pane |
r |
queue_go_to_artist |
Go to artist of the selected queue item in Artist pane |
e |
queue_center_cursor |
Center cursor in currently playing song |
> |
track_next |
Play next song in queue |
< |
track_previous |
Play previous song in queue |
d |
queue_delete_song |
Delete selected song from queue |
c |
queue_clear |
Clear queue and stop playback |
| Shortcut | Key in config | Popup | Description |
|---|---|---|---|
a |
go_popup_add_item_to |
Album information | Open the Add To popup for the selected item |
A |
go_popup_add_parent_to |
Album information | Open the Add To popup for whole album |
n |
add_item_next |
Add item to | Add item to the queue after track currently being played |
e |
add_item_end |
Add item to | Add item to the queue at the end of the queue |
p |
add_item_playlist |
Add item to | Open the playlist popup to select a playlist for adding the item to |
r |
playlist_pull_remote |
Synchronize playlist | Pull the remote version of the selected playlist |
l |
playlist_push_local |
Synchronize playlist | Push the local version of the selected playlist |
y |
- | Delete playlist | Confirm playlist deletion |
n |
- | Delete playlist | Cancel playlist deletion |
r |
- | Test Navidrome server | Generate new salt and token |
t |
- | Test Navidrome server | Test connection to server |
o |
- | Connection Error | Switch to offline mode after error communicating with server |
r |
- | Connection Error | Retry after error communicating with server |
<Enter> |
- | Global Search | Accept current query while typing |
<r> |
global_search_go_to_pane |
Global Search | Go to corresponding pane for the selected search result item |
q |
close_popup |
- | Close the current popup |
This is a known issue with older versions of mpv, like the ones in repositories of distributions derived from Ubuntu. Please try to update to a newer version, I am running v0.41.0 at the time of writing with no issues.
naviterm can be a bit heavy on the CPU side. It is in part due to the nature of ratatui, as it re-draws the whole ui on each call to the draw method. Even if there are no changes in the app state, it needs to compute all the widgets based on the app information, and compare the frame with the previous one. This can be CPU expensive, so I tried to reduce the painting calls to only twice per second (to ensure smooth playing time tracking) or whenever a key is pressed. If you find it still too heavy, you can disable the painting whenever the window looses focus, using the following configuration key:
draw_while_unfocused=falseThis error means that the connection with the mpv process could not be established. We currently wait for a predetermined time (200ms) and try again, but if it still fails, this error will raise. You can try increasing the waiting time using the option:
wait_for_ipc_ms=200When dealing with very big playlists, it is possible that you encounter an error stating that "414 Request-URI Too Long". This is due to the fact that when syncing a playlist with the server, we send the content of the playlist in the url. If the playlist have too many items, this could be an issue. There is another Subsonic API that could be used, but it makes playlist updating substantially harder, especially when dealing with songs reordering.
Found a bug (pretends to be shocked)? Please open a bug report and try to describe the issue as much as possible. By default, naviterm logs some information at /tmp/naviterm.log. The verbosity of this log can be controlled using the environment variable APP_DEBUG (by default is set to INFO). Setting it to DEBUG prior to running the program can be very helpful for debugging issues:
APP_DEBUG=DEBUG navitermThe mpv process controlled by naviterm logs at /tmp/naviterm_mpv.log, which could also be helpful. Please attach both logs to the issue when possible.
If you have a feature request, also open an issue. No guarantees that I will implement it, but I will always take a look to see the feasibility/impact. Contributions are very welcome.
Please note that I developed the application with Navidrome in mind. Although the Subsonic API is used by other server applications, it might be the case that naviterm does not work well with them. I might not be able to test/reproduce all issues of that kind, so bear that in mind when opening issues. If you are willing to help building bugfix branches and testing, that would help me a lot.
Server applications tested:
- Navidrome
- Nextcloud Music app
- LMS - Lightweight Music Server. LMS uses the album list v2 API, check the configuration section
The app does mostly all I expect from a client (at least for my use cases). The following are some pending issues/wishlist that I will work on, time permits:
- Global fuzzy search in all songs,albums,playlists,artists
- Allow to reconfigure shortcuts
- Implement a more secure password storage
- Allow to reorganize the home pane
- React to different terminal sizes (responsive design?)
