site

files for beauhilton.com
git clone https://git.beauhilton.com/site.git
Log | Files | Refs

index.html (11116B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3  <head>
      4   <link rel="stylesheet" href="/style.css" type="text/css">
      5   <meta charset="utf-8">
      6   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      7   <meta name="viewport" content="width=device-width, initial-scale=1.0">
      8   <link rel="stylesheet" type="text/css" href="/style.css">
      9   <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🏕️</text></svg>">
     10   <title></title>
     11  </head>
     12  <body>
     13   <div id="page-wrapper">
     14    <div id="header" role="banner">
     15     <header class="banner">
     16      <div id="banner-text">
     17       <span class="banner-title"><a href="/">beauhilton</a></span>
     18      </div>
     19     </header>
     20     <nav>
     21      <a href="/about">about</a>
     22 <a href="/now">now</a>
     23 <a href="/thanks">thanks</a>
     24 <a class="nav-active" href="/posts">posts</a>
     25 <a href="https://notes.beauhilton.com">notes</a>
     26 <a href="https://talks.beauhilton.com">talks</a>
     27 <a href="https://git.beauhilton.com">git</a>
     28 <a href="/contact">contact</a>
     29 <a href="/atom.xml">rss</a>
     30     </nav>
     31    </div>
     32    <main>
     33     <h1>
     34      Command-line interfaces for self-hosted music
     35     </h1>
     36     <p>
     37      <time id="post-date">2023-09-28</time>
     38     </p>
     39     <p id="post-excerpt">
     40      Self-hosting a music server is great.
     41 Listening to the tunes via the command line is the way.
     42     </p>
     43     <h2>
     44      Subsonic-compatible server backbone
     45     </h2>
     46     <p>
     47      I have <a href="https://www.navidrome.org/">Navidrome</a> installed
     48 (via Docker on NixOS). It’s very nice.
     49     </p>
     50     <p>
     51      With a reverse proxy, <a href="https://tailscale.com/">tailscale</a>,
     52 and LetsEncrypt set up, I can access it via any Subsonic-compatible
     53 music player at <a href="https://music.beauslab.casa">https://music.beauslab.casa</a> (this
     54 URL is available only on my tailnet, so it will 404 for everyone
     55 else).
     56     </p>
     57     <h2>
     58      Desktop GUI interfaces
     59     </h2>
     60     <p>
     61      <a href="https://sublimemusic.app/">Sublime-music</a> is pretty good.
     62 I also often find myself using the Navidrome web UI.
     63     </p>
     64     <p>
     65      (On mobile, <a href="https://symfonium.app/">Symfonium</a> (paid) or
     66 <a href="https://substreamerapp.com/">SubStreamer</a> on Android and <a href="http://michaelsapps.dk/playsubapp/">play:Sub</a> (paid) or <a href="https://substreamerapp.com/">SubStreamer</a> on iOS are my go-tos,
     67 though there are many <a href="http://www.subsonic.org/pages/apps.jsp">others</a>)
     68     </p>
     69     <h2>
     70      CLI interfaces: contenders (STMP, jellycli, sksonic)
     71     </h2>
     72     <p>
     73      If I’m in programming mode, I prefer command-line interfaces,
     74 particularly if they let me use keyboard muscle-memory (i.e. vi
     75 bindings).
     76     </p>
     77     <p>
     78      As such, I tried a few CLI front-ends to access and play my
     79 Navidrome-served tunes.
     80     </p>
     81     <p>
     82      I’m sure there are others.
     83     </p>
     84     <p>
     85      <a href="https://github.com/wildeyedskies/stmp/tree/main">STMP</a> is
     86 clean and works well, but doesn’t have vi bindings yet.
     87     </p>
     88     <p>
     89      <a href="https://github.com/tryffel/jellycli/tree/master">jellycli</a> is
     90 the most polished, and uses vi bindings, but even so the in-app nav is
     91 finicky and doesn’t quite fit my brain (though that might be mostly due
     92 to conflicts with other terminal keybindings I have set up).
     93     </p>
     94     <p>
     95      <a href="https://gitlab.com/yvelon/sksonic">sksonic</a> is a
     96 suckless-style implementation in C, e.g. edit config.h and recompile. It
     97 works, but isn’t polished enough for daily usage (though I don’t expect
     98 it to be - the author states it’s a personal project, and I think
     99 they’re doing a great job, so will keep an eye on it). Partial vi-key
    100 support, could easily be added given the suckless style.
    101     </p>
    102     <h2>
    103      CLI interfaces: the one I picked (ncmpcpp with mopidy backend)
    104     </h2>
    105     <p>
    106      After these, I found myself wishing that I could use <a href="https://github.com/ncmpcpp/ncmpcpp">ncmpcpp</a> and hook it up to
    107 my Subsonic back end.
    108     </p>
    109     <p>
    110      And then I realized: hey, this is a Linux TUI, and ncmpcpp is just a
    111 front-end for <a href="https://www.musicpd.org/">mpd</a>, of course you
    112 can switch out mpd for something that’s Subsonic-aware.
    113     </p>
    114     <p>
    115      ncmpcpp is beautiful, polished, fast, with great vi-key support, and
    116 I’ve been using it for years for local music playback.
    117     </p>
    118     <p>
    119      <a href="https://mopidy.com/">mopidy</a> is a fairly drop-in mpd
    120 replacement that is pluggable, with a number of awesome <a href="https://mopidy.com/ext/">extensions</a>.
    121     </p>
    122     <p>
    123      I should have looked here first. C’est la vie.
    124     </p>
    125     <p>
    126      I perused a few blog posts to get a sense of what to do:
    127     </p>
    128     <ul>
    129      <li>
    130       <a href="https://fsylum.net/blog/setting-up-ncmpcpp-mopidy-spotify-arch-linux/">fsylum’s
    131 post</a>
    132      </li>
    133      <li>
    134       <a href="https://blog.deepjyoti30.dev/using-spotify-with-ncmpcpp-mopidy-linux">Deepjyoti
    135 Barman’s post</a>
    136      </li>
    137      <li>
    138       <a href="https://www.digitalneanderthal.com/post/ncmpcpp/">Digital
    139 Neanderthals’ post</a> (what a great online moniker, well done - his
    140 physical setup is also a delight, sheer cyberdeck practicality)
    141      </li>
    142     </ul>
    143     <p>
    144      It’s pretty easy.
    145     </p>
    146     <p>
    147      The rad thing is that you can get a unified frontend for all your
    148 sources, e.g. Subsonic, Spotify, local files, YouTube, SoundCloud, etc.,
    149 just install a plugin and add a config section and you’re off to the
    150 races, never having to leave the terminal.
    151     </p>
    152     <blockquote>
    153      <p>
    154       Source selection (could have many more items here).
    155      </p>
    156     </blockquote>
    157     <p>
    158      <img src="/images/ncmpcpp-mopidy-selector.png" alt="Source selection">
    159     </p>
    160     <blockquote>
    161      <p>
    162       Artist selection.
    163      </p>
    164     </blockquote>
    165     <p>
    166      <img src="/images/ncmpcpp-mopidy-full.png" alt="Preview">
    167     </p>
    168     <blockquote>
    169      <p>
    170       Track view.
    171      </p>
    172     </blockquote>
    173     <p>
    174      <img src="/images/ncmpcpp-mopidy-tracks.png" alt="Track view">
    175     </p>
    176     <h2>
    177      Set up
    178     </h2>
    179     <h3>
    180      Install the things
    181     </h3>
    182     <p>
    183      My main laptop still runs Arch (btw). If I ever switch to NixOS on
    184 this machine, or add this setup to the NixOS server, I’ll probably make
    185 a new post with the Nix way to do this. I bet it’s hardly different,
    186 other than the <code>.nix</code> files.
    187     </p>
    188     <p>
    189      e.g. <code>paru -S ncmpcpp mopidy mopidy-subidy mopidy-mpd</code>
    190     </p>
    191     <p>
    192      Also uninstall and stop mpd, if you’re using it.
    193     </p>
    194     <h3>
    195      Config files
    196     </h3>
    197     <p>
    198      (most of the what’s in the files below is unnecessary for this post,
    199 but I’ve never been mad that someone posted their whole config)
    200     </p>
    201     <p>
    202      (also note that the mopidy config file doesn’t allow # comments, I
    203 just used them for ease of reading with syntax highlighting, will have
    204 to delete prior to actually using)
    205     </p>
    206     <p>
    207      <code>~/.config/ncmpcpp/config</code>
    208     </p>
    209     <pre tabindex="0"><code class="language-sh">ncmpcpp_directory <span class="hl opt">=</span> ~<span class="hl opt">/</span>.config<span class="hl opt">/</span>ncmpcpp
    210 lyrics_directory <span class="hl opt">=</span> ~<span class="hl opt">/</span>.config<span class="hl opt">/</span>lyrics
    211 
    212 progressbar_look <span class="hl opt">= -&gt;</span>
    213 display_volume_level <span class="hl opt">=</span> no
    214 
    215 autocenter_mode <span class="hl opt">=</span> <span class="hl kwc">yes</span>
    216 message_delay_time <span class="hl opt">=</span> <span class="hl num">1</span>
    217 
    218 playlist_display_mode <span class="hl opt">=</span> columns
    219 playlist_editor_display_mode <span class="hl opt">=</span> columns
    220 browser_display_mode <span class="hl opt">=</span> columns
    221 
    222 media_library_primary_tag <span class="hl opt">=</span> album_artist
    223 media_library_albums_split_by_date <span class="hl opt">=</span> no
    224 
    225 ignore_leading_the <span class="hl opt">=</span> <span class="hl kwc">yes</span>
    226 ignore_diacritics <span class="hl opt">=</span> <span class="hl kwc">yes</span>
    227 external_editor <span class="hl opt">=</span> vim
    228 use_console_editor <span class="hl opt">=</span> <span class="hl kwc">yes</span>
    229 </code></pre>
    230     <p>
    231      <code>~/.config/mopidy/mopidy.conf</code>
    232     </p>
    233     <pre tabindex="0"><code class="language-sh"><span class="hl opt">[</span>core<span class="hl opt">]</span>
    234 cache_dir <span class="hl opt">=</span> <span class="hl kwd">$XDG_CACHE_DIR</span><span class="hl opt">/</span>mopidy
    235 config_dir <span class="hl opt">=</span> <span class="hl kwd">$XDG_CONFIG_DIR</span><span class="hl opt">/</span>mopidy
    236 data_dir <span class="hl opt">=</span> <span class="hl kwd">$XDG_DATA_DIR</span><span class="hl opt">/</span>mopidy
    237 max_tracklist_length <span class="hl opt">=</span> <span class="hl num">10000</span>
    238 restore_state <span class="hl opt">=</span> true
    239 
    240 <span class="hl opt">[</span><span class="hl kwc">file</span><span class="hl opt">]</span> <span class="hl slc"># might switch out for mopidy-local at some point, adds search support via sqlite metadata archive</span>
    241 enabled <span class="hl opt">=</span> true
    242 media_dirs <span class="hl opt">=</span> 
    243   ~<span class="hl opt">/</span>media<span class="hl opt">/</span>tunes
    244 excluded_file_extensions <span class="hl opt">=</span> 
    245  .directory
    246  .html
    247  .jpeg
    248  .jpg
    249  .log
    250  .nfo
    251  .pdf
    252  .png
    253  .txt
    254  .<span class="hl kwc">zip</span>
    255 show_dotfiles <span class="hl opt">=</span> false
    256 follow_symlinks <span class="hl opt">=</span> false
    257 metadata_timeout <span class="hl opt">=</span> <span class="hl num">1000</span>
    258 
    259 <span class="hl opt">[</span>m3u<span class="hl opt">]</span>
    260 playlists_dir <span class="hl opt">=</span> <span class="hl kwd">$XDG_CONFIG_DIR</span><span class="hl opt">/</span>mopidy<span class="hl opt">/</span>playlists
    261 
    262 <span class="hl opt">[</span>mpd<span class="hl opt">]</span>
    263 enabled <span class="hl opt">=</span> true
    264 hostname <span class="hl opt">=</span> <span class="hl num">127.0.0.1</span>
    265 port <span class="hl opt">=</span> <span class="hl num">6600</span> <span class="hl slc"># defaults ftw - no change to ncmpcpp config needed if defaults are kept</span>
    266 max_connections <span class="hl opt">=</span> <span class="hl num">20</span>
    267 connection_timeout <span class="hl opt">=</span> <span class="hl num">60</span>
    268 
    269 <span class="hl opt">[</span>subidy<span class="hl opt">]</span>
    270 enabled <span class="hl opt">=</span> true
    271 url <span class="hl opt">=</span> https<span class="hl opt">://</span>music.beauslab.casa
    272 username <span class="hl opt">=</span> admin
    273 password <span class="hl opt">=</span> admin <span class="hl slc"># behind a tailnet anyway, come at me bro</span>
    274 api_version <span class="hl opt">=</span> <span class="hl num">1.16</span>
    275 </code></pre>
    276     <h2>
    277      Future goals
    278     </h2>
    279     <ul>
    280      <li>
    281       snapcast for whole-house audio (<a href="https://www.reddit.com/r/selfhosted/comments/icjmiq/a_music_server_with_a_tli_client/">Reddit
    282 post</a> with some good tips)
    283      </li>
    284     </ul>
    285    </main>
    286    <div id="footnotes"></div>
    287    <footer></footer>
    288   </div>
    289  </body>
    290 </html>