Home

Awesome

mpv-sockets

A collection of bash scripts to allow easier and programmatic interaction with mpv sockets

When launching mpv, one can use --ipc-socket (or set the property in your mpv.conf) to launch mpv with the one socket, but I tend to have lots of instances of mpv open. One for a video I'm watching, another for some album I'm listening to, another for a playlist...

If you use the one IPC socket, whenever a new instance of mpv is launched, the old instance gets disconnected. The mpv wrapper script creates a unique IPC socket for each mpv instance launched at /tmp/mpvsockets.

mpv-active-sockets removes any inactive (leftover socket files from instances which have been quit) mpv sockets, and lists active mpv sockets

mpv-communicate is a basic socat wrapper to send commands to the IPC server. (sends all additional arguments to the socket described by the first argument)

To illustrate:

If I have two instances of mpv open:

$ mpv-active-sockets
/tmp/mpvsockets/1643226338072141025
/tmp/mpvsockets/1643226355764534189

To get metadata from the oldest (sockets are sorted by spawn time, so head gets the oldest) launched mpv instance:

$ mpv-communicate "$(mpv-active-sockets | head -n 1)" '{ "command": ["get_property", "metadata"] }' | jq
{
  "data": {
    "title": "Roundabout",
    "album": "Fragile",
    "genre": "Progressive Rock",
    "track": "01/9",
    "disc": "1/1",
    "artist": "Yes",
    "album_artist": "Yes",
    "date": "1972"
  },
  "request_id": 0,
  "error": "success"
}

mpv-get-property interpolates the second argument into the get_property command syntax, but is practically no different from mpv-communicate

$ mpv-get-property "$(mpv-active-sockets)" path  # this works if there's only one instance of mpv active
Music/Yes/Yes - Fragile/01 - Roundabout.mp3

mpv-currently-playing

mpv-currently-playing is a mpv-get-property wrapper that gets information about the currently playing mpv instance. If there are multiple sockets, prints multiple lines, with one for each socket.

By default that will print the full path of the song that's currently playing, but you can provide the --socket flag to print the sockets instead.

Lots of scripts here use mpv-currently-playing internally, as interacting with the currently playing mpv instance is pretty useful.

$ mpv-song-description
Yellow Submarine - The Beatles (Revolver)
mpv-communicate $(mpv-currently-playing --socket | tail -n1) '{ "command": ["playlist-next"] }'
mpv-communicate $(mpv-currently-playing --socket | tail -n1) 'quit'

To list currently paused mpv instances:

$ diff -y --suppress-common-lines <(mpv-currently-playing --socket) <(mpv-active-sockets) | grep -oP '(\/tmp\/mpvsockets\/\d+)'


I bind lots of these scripts to keybindings, so I can easily play/pause and skip songs without switching to the terminal with mpv running; search for mpv in my config file

There are lots of properties/commands one can send to mpv, see mpv --list-properties and these (1, 2) for reference.

Install

Dependencies: mpv, socat, jq, sed, (fzf for mpv-quit-pick)

To install this, clone and copy all the scripts somewhere onto your $PATH:

git clone https://github.com/purarue/mpv-sockets
cd ./mpv-sockets
make

That puts them in ~/.local/bin

I put the directory that the mpv wrapper script is installed into on my $PATH before /usr/bin, so the wrapper script intercepts calls that would typically call the mpv binary. In my shell profile, like:

PATH="${HOME}/.local/bin:${PATH}"
export PATH

You could alternatively rename the mpv wrapper script here to something like mpvs and then run mpvs instead of mpv when you want unique sockets.

This checks /usr/bin/mpv, /bin/mpv and /usr/local/bin/mpv for the mpv binary. If your mpv isn't at one of those locations, you can set the MPV_PATH variable in your shell profile:

export MPV_PATH=/home/user/bin/mpv

You can set the MPV_SOCKET_DIR environment variable to spawn sockets in a directory other than /tmp/mpvsockets, this uses the TMPDIR environment variable if it's set instead of /tmp

Alternative Installation Methods

To automate the manual git clone/cd/make, you could instead use bpkg:

bpkg install -g purarue/mpv-sockets

Or basher:

basher install purarue/mpv-sockets

Note that in this case the basher bin has to appear before the mpv binary, see my config as an example (I install basher in $XDG_DATA_HOME, by default it places itself in ~/.basher)

Daemon

I run mpv-history-daemon in the background, which polls for new sockets at /tmp/mpvsockets, grabbing file info, metadata, and whenever I play/pause/skip anything playing in mpv. That creates a local JSON scrobbling history for mpv, which I send up to my_feed, as well as to a websocket-based currently playing server

1598956534118491075|1598957274.3349547|mpv-launched|1598957274.334953
1598956534118491075|1598957274.335344|working-directory|/home/username/Music
1598956534118491075|1598957274.3356173|playlist-count|12
1598956534118491075|1598957274.3421223|playlist-pos|2
1598956534118491075|1598957274.342346|path|Masayoshi Takanaka/Masayoshi Takanaka - Alone (1988)/02 - Feedback's Feel.mp3
1598956534118491075|1598957274.3425295|media-title|Feedback's Feel
1598956534118491075|1598957274.3427346|metadata|{'title': "Feedback's Feel", 'album': 'Alone', 'genre': 'Jazz', 'album_artist': '高中正義', 'track': '02/8', 'disc': '1/1', 'artist': '高中正義', 'date': '1981'}
1598956534118491075|1598957274.342985|duration|351.033469
1598956534118491075|1598957274.343794|resumed|{'percent-pos': 66.85633}
1598956534118491075|1598957321.3952177|eof|None
1598956534118491075|1598957321.3955588|mpv-quit|1598957321.395554
Ignoring error: [Errno 32] Broken pipe
Connected refused for socket at /tmp/mpvsockets/1598956534118491075, removing dead socket file...
/tmp/mpvsockets/1598956534118491075: writing to file...