mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
27.81k stars 2.87k forks source link

How to make sure all MPV windows always have a ipc connection? for command line control #12714

Closed RalfReddings closed 9 months ago

RalfReddings commented 10 months ago

For some time now, I have been looking for a way to control specific MPV windows from the command line.

After searching and asking around, for example, HERE and HERE, I managed to find a way.

I first need to make sure I create this "ipc server" thing at the time of opening the video:

 mpv  "C:\temp\cat.mp4" "--input-ipc-server=\\.\pipe\mpy_win"

From then, I can send commands only to that specific window with:

'cycle pause' | Out-File -literalPath '\\.\pipe\mpy_win'

This gets me 80% there. The problem is that 90% of the I am creating MPV windows from a File Explorer window by double clicking on video files. So I cant create an "ipc server" right then.

I tried placing the --input-ipc-server= command in my MPV.conf file:

--input-ipc-server=\\.\pipe\mpv_${window-id}

I tried to solve the issue of the ipc server name not being unique per window, by appending the property window-id to the server name. But it seems, you cannot use property expansion with this command.

I am out of ideas. Is there a better or perhaps a more conventional way to do this?

I am on windows 11 on the latest MPV

Any help would be greatly appreciated!

guidocella commented 10 months ago

https://github.com/wis/mpvSockets

RalfReddings commented 10 months ago

@guidocella

https://github.com/wis/mpvSockets

Hey thank you for the help.

I installed the script you linked to, by placing the mpvSockets.lua in mpv/scripts directory. I created a new MPV window by opening a video file from File Explorer, and tried to use the provided .ps1 file:

socat.ps1 25032 cycle pause    # I am not sure what the IPC name is so I just passed the MPV windows PID number

but this just returns a bunch of PowerShell errors. Furthermore in the socat.ps1 file, the first two lines:

$sockedName = args[0]
$message = args[1]

Dont seem to be valid PowerShell code.

Also, Do you by any chance know how to find out if a specific MPV instance has a IPC server associated with it?

guidocella commented 10 months ago

Run print-text ${input-ipc-server} in the ` console to see in what folder that script puts named pipes, then you can send command to the sockets like before since you don't care about receiving a response. You can also trivially replace mpvSockets with a custom 1 line-script that does something like mpv.set_property('input-ipc-server', '/tmp/mpv-socket-' .. mp.get_property('pid'))

RalfReddings commented 10 months ago

@guidocella

So I was able to get mpvSockets to work. but It has glaring flaws:

You can also trivially replace mpvSockets with a custom 1 line-script that does something like mpv.set_property('input-ipc-server', '/tmp/mpv-socket-' .. mp.get_property('pid'))

This sounds really promising. I gave it a try, as you can see in this image: |500

But I am not sure it if worked or not. I found a way to get the IPC pipes I thus far created (maybe its not an exhaustive list):

get-childitem -literalpath '\\.\pipe\' |? name -Match "mpv"
    Directory: \\.\pipe
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-----          01/01/1601    00:00              1 mpv-pipe
-----          01/01/1601    00:00              1 mpv-pipe1
-----          01/01/1601    00:00              1 mpv-pipe2

Only the IPC names that I manually created at the terminal are listed though.

On second hand your code snippet, mpv.set_property('input-ipc-server', '/tmp/mpv-socket-' .. mp.get_property('pid')), might have just been for illustration only. I would like to build something similar myself. I don't mind learning LUA (been meaning to anyways).

Do you know if there is an official MPV documentation page for its LUA scripting interface, where commands such as mpv.set_property()/mp.get_property() are explained.

Cheers for helping me out.

guidocella commented 10 months ago

There was a typo, try

mp.set_property('input-ipc-server', 'mpv-socket-' .. mp.get_property('pid'))

Lua's docs are at https://mpv.io/manual/master/#lua-scripting

mpvSockets's Windows support is clearly an afterthough. You will probably want to at least delete the named pipe when quitting mpv. I have no idea if this works with named pipes:

mp.register_event('shutdown', function ()
    os.remove([[\\.\pipe\]] .. mp.get_property('input-ipc-server'))
end)
RalfReddings commented 10 months ago

@guidocella Hey that worked :) . Thank you so much.

mpvSockets's Windows support is clearly an afterthought.

This seems to be the case with everything ported down from UNIX, one can only graciously accept what they get. As for deleting the pipes, when I close the MPV window. I cannot find the pipe by searching for it: get-childitem -literalpath '\\.\pipe\' |? name -Match "mpv"

Maybe its its just a coincidence and there is still hanging pipe process, So I placed your code into the same script file. I will leave it like that until I get my bearings with MPV scripting.