2023-01-09

How to ask VLC what's currently playing

(Target audience: command-line fans on something Unixy, who have or will be able to find bash, vlc, curl and xmllint.)

My preferred method of music consumption is a collection-wide shuffle. My local media drive has, well, let's see...

  dad@arlo:/media/dad/brick/media/music$ find . -name "*.mp3" | wc -l
  65458

over 65 thousand tracks. (I've been collecting for a long time, all my vinyl is digitized, yada yada yada.) I have a script that creates a playlist of random selections from the collection, and then I open that playlist in VLC.

Quite often, an underappreciated track catches my ear, and I would like to add it to a favorites playlist. So I would flip over to the VLC window, right-click my way into the current selection's Information window, follow that with a mouse-select of the URI of the currently-playing mp3 and a paste into vim, where the favorites playlist is open.

This is why I hate GUIs.

Now, seriously, how un-Unix is that? What I need is a command-line utility that will just give me the currently-playing file, so that I can just append-pipe the filename into the favorites playlist.

So, how can I ask VLC to give me that?

Turns out, it's not too bad. VLC can be started with multiple live interfaces, one of which is HTTP. This gives us a web-based interface that can be opened in a browser, but more importantly for the task at hand, it gives us a REST API into the running VLC. And that REST API will give us an XML document describing the current playlist, including which track is currently playing.

One weird bit to note - the HTTP interface won't work unless you set a password to access it. Okay, that's not so weird, except that you don't (you cannot) set a user name, so the user name is (must be) the empty string.

The good news is that cURL handles empty-string user names just fine, by passing just a colon and password to the -u argument. Like so:


  # /bin/bash
  # get current playing by file name

  curl -u :myterriblepassword http://127.0.0.1:8080/requests/playlist.xml 2>/dev/null \
  | xmllint --xpath 'string(//leaf[@current="current"]/@uri)' - \
  >>favorites.m3u

That's it. Feel free to improve on this in the comments.