KaFu Posted December 5, 2019 Share Posted December 5, 2019 https://mpv.io/ is a free, open source, and cross-platform media player. mpv can be controlled by external programs using the JSON-based IPC protocol. It can be enabled by specifying the path to a unix socket or a named pipe using the option --input-ipc-server. Clients can connect to this socket and send commands to the player or receive events from it. https://mpv.io/manual/stable/#json-ipc Find attached a proof of concept example on how to control MPV via Pipes by AutoIt. MediaInfo.dll is included to auto-rotated movies with "Orientation" flag set. Download MPV.exe from homepage and point to it with the var $s_Global_Path_MPV. Set $s_Global_Path_MediaFile to a movie file to run the test-script on. Have fun MPV-Test_v0011.zip Gianni 1 OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Gianni Posted December 8, 2019 Share Posted December 8, 2019 hi @KaFu, and thanks for sharing this stuffI'm doing some quick tests and I can't upload a new video while another video is being viewed.I reduced your script a bit (to be able to manage it more easily) and I put some buttons on the GUI to do some tests. The first button on the left should load a new video, but I get an error when I try to set the new video (see the lines related to the 'open file' button from 107 to 112)do you know how to set the json string to upload a new video and send it running? How I tried to use it doesn't work(reference: https://mpv.io/manual/stable/#command-interface-[%3Coptions%3E]])Thanks for your helpP.S.for those wishing to try the script, you also need to extract the mpv.exe file from this archive (https://sourceforge.net/projects/mpv-player-windows/files/32bit/) and save it in the same directory as the script renamed in AMT- mpv.exe expandcollapse popupGlobal $s_Global_Path_MediaFile = FileGetShortName(FileOpenDialog("peek a file", @ScriptDir, "All (*.*)", 3)) ; path of the mpv.exe Global $s_Global_Path_MPV = @ScriptDir & '\AMT-mpv.exe' ; '\mpv.exe' $s_Global_Path_MPV = '"' & $s_Global_Path_MPV & '"' #include <NamedPipes.au3> #include <WinAPIFiles.au3> #include <WinAPIHObj.au3> #include <WinAPI.au3> #include <WinAPIProc.au3> #include <Date.au3> #include <GUIConstantsEx.au3> ; Opt("GUIOnEventMode", 1) Global $s_Global_Pipe_Name = "\\.\pipe\AMT_mpvsocket" Global $h_Global_MPV_Pipe, $i_Global_MPV_PID Global $s_Screenshot_Directory = @ScriptDir & "\screen shot\" DirCreate($s_Screenshot_Directory) Global $h_DLL_kernel32 = DllOpen("kernel32.dll") ; gui with 16:9 aspect ratio Global $iWidth = 800 Global $iheight = ($iWidth / 16) * 9 Global $hGUI = GUICreate("", $iWidth, $iheight + 40) ; video placeholder ; dimension and location of this label will be dimension and location of the video on the GUI Global $c_Display_Label = GUICtrlCreateLabel("", 0, 0, $iWidth, $iheight) Global $h_Slider = GUICtrlCreateSlider(0, $iheight, $iWidth, 20, 0x0010) GUICtrlSetLimit(-1, 100, 0) ; change min/max value Global $iBtnW = $iWidth / 6, $iX = 0 Global $hButton1 = GUICtrlCreateButton("Open file", $iX, $iheight + 20, $iBtnW, 20) ; open file $iX += $iBtnW Global $hButton2 = GUICtrlCreateButton("backward 10%", $iX, $iheight + 20, $iBtnW, 20) ; backward 10% $iX += $iBtnW Global $hButton3 = GUICtrlCreateButton("play/pause", $iX, $iheight + 20, $iBtnW, 20) ; toggle play/pause $iX += $iBtnW Global $hButton4 = GUICtrlCreateButton("forward 10%", $iX, $iheight + 20, $iBtnW, 20) ; forward 10% $iX += $iBtnW Global $hButton5 = GUICtrlCreateButton("snapshot", $iX, $iheight + 20, $iBtnW, 20) ; take a snapshot $iX += $iBtnW Global $hButton6 = GUICtrlCreateButton("audio on/off", $iX, $iheight + 20, $iBtnW, 20) ; toggle audio on/off GUISetState() ; Global $h_DLL_MediaInfo = DllOpen(@ScriptDir & "\z_MediaInfo.dll") Global $s_Global_MPV_Args = " --vo=direct3d, " $s_Global_MPV_Args &= " --vf lavfi=[scale=w=320:h=-1] " ; to prescale output > huge performance improvment for HD+ files $s_Global_MPV_Args &= " --vf-add=lavfi=[eq=1:0:1:1,hue=h=0] " ; https://mpv.io/manual/stable/#video $s_Global_MPV_Args &= " --cache=yes " $s_Global_MPV_Args &= " --screenshot-format=png " $s_Global_MPV_Args &= " --no-keepaspect --no-config --no-quiet --terminal --no-msg-color --msg-level=ffmpeg/demuxer=error --no-fs " $s_Global_MPV_Args &= " --vd-lavc-threads=4 " ; Specify the hardware video decoding API that should be used if possible. $s_Global_MPV_Args &= " --hwdec=auto " $s_Global_MPV_Args &= " --priority=abovenormal --no-input-default-bindings --input-vo-keyboard=no --no-input-cursor --cursor-autohide=no --wid=" & Number(GUICtrlGetHandle($c_Display_Label)) & " --monitorpixelaspect=1 " $s_Global_MPV_Args &= " --osd-level=3 --osd-scale=1 --osd-bar-align-y=0.6 " $s_Global_MPV_Args &= " --sub-auto=fuzzy " $s_Global_MPV_Args &= " --sub-ass --embeddedfonts --sub-ass-line-spacing=0 --sub-scale=1 --sub-font=""Bodoni MT Poster Compressed"" --sub-color=#ffffffff --sub-shadow-color=#ff000000 --sub-border-color=#ff000000 --sub-border-size=0.75 --sub-shadow-offset=2.5 " $s_Global_MPV_Args &= " --sub-font-size=35 --sub-bold=no --sub-italic=no " $s_Global_MPV_Args &= " --sub-ass-force-style=PlayResX=512,PlayResY=320,Name=Default,Fontname=""Bodoni MT Poster Compressed"",Fontsize=14,PrimaryColour=#00ffffff,BackColour=#00000000,OutlineColour=#00000000,Bold=0,Italic=0,Alignment=2,BorderStyle=1,Outline=0.3,Shadow=1,MarginL=20,MarginR=20,MarginV=8 " $s_Run_Commandline = $s_Global_Path_MPV & " " & $s_Global_MPV_Args & " " & $s_Global_Path_MediaFile & " --input-ipc-server=" & $s_Global_Pipe_Name _MPV_CloseProcesses() Global $i_Global_MPV_PID = Run($s_Run_Commandline, $s_Screenshot_Directory, @SW_SHOW, $STDERR_MERGED + $STDIN_CHILD) OnAutoItExitRegister("_OnAutoItExitRegister") Func _OnAutoItExitRegister() ; DllClose($h_DLL_MediaInfo) DllClose($h_DLL_kernel32) _MPV_CloseProcesses() EndFunc ;==>_OnAutoItExitRegister $h_Global_MPV_Pipe = _MPV_GetHandle() $sRes = _MPV_Wait_for_Event('{"event":"playback-restart"}') ; Movie started ; https://mpv.io/manual/stable/#property-list ConsoleWrite(_MPV_Command_Send_and_Wait_for_Success('["set_property","mute","no"]') & @CRLF) ConsoleWrite(_MPV_Command_Send_and_Wait_for_Success('["set_property","volume",50]') & @CRLF) ; --------- ; main loop ; --------- ; Loop until the user exits. Global $iDelay = 3000, $iTimer = TimerInit(), $idMsg, $vResult Do $idMsg = GUIGetMsg() Switch $idMsg Case $h_Slider ConsoleWrite(GUICtrlRead($h_Slider) & @CRLF) $sCommand = '{"command":["seek","' & GUICtrlRead($h_Slider) & '","absolute-percent+keyframes"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Command_Read_Response() ; flush pipe Case $hButton1 ; file open $s_Global_Path_MediaFile = FileGetShortName(FileOpenDialog("load a file", @ScriptDir, "All (*.*)", 3)) ; $s_Global_Path_MediaFile = StringMid($s_Global_Path_MediaFile, StringInStr($s_Global_Path_MediaFile, '\', 0, -1) + 1) $sCommand = '{"command":["loadfile", "' & $s_Global_Path_MediaFile & '", "replace"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) MsgBox(262144, "Debug", $sCommand & @CRLF & _MPV_Wait_for_Event('')) Case $hButton2 ; step back $sCommand = '{"command":["seek","-10","relative-percent+keyframes"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Wait_for_Event('') ; flush pipe _SetSlider() Case $hButton3 ; play/pause $sCommand = '{"command":["cycle","pause"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Wait_for_Event('') ; flush pipe Case $hButton4 ; step forward $sCommand = '{"command":["seek","10","relative-percent+keyframes"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Wait_for_Event('') ; flush pipe _SetSlider() Case $hButton5 ; take snapshot $s_File_Screenshot = 'screenshot_' & @YEAR & @MON & @MDAY & @HOUR & @MIN & @SEC & @MSEC & '.png' $sCommand = '{"command":["screenshot-to-file","' & $s_File_Screenshot & '","video"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Wait_for_Event('') ; flush pipe Case $hButton6 ; audio on/off $sCommand = '{"command":["cycle","mute"]}' & @LF $sRes = _MPV_Command_Send_Request($sCommand) _MPV_Wait_for_Event('') ; flush pipe Case Else ; do noting EndSwitch If TimerDiff($iTimer) > $iDelay Then ; each "delay" period update the slider _SetSlider() EndIf Until $idMsg = $GUI_EVENT_CLOSE Func _SetSlider() $vResult = _MPV_Command_Send_and_Wait_for_Success('["get_property","percent-pos"]') $vResult = StringTrimLeft($vResult, StringInStr($vResult, ":")) $vResult = Int(Number(StringLeft($vResult, StringInStr($vResult, ",") - 1))) ConsoleWrite(" --> " & $vResult & @CRLF) GUICtrlSetData($h_Slider, $vResult) ; set cursor $iTimer = TimerInit() EndFunc ;==>_SetSlider Exit _MPV_CloseProcesses() Func _MPV_Command_Send_and_Wait_for_Success($sCommand, $iTimeout = 1000) Local $i_Request_ID = TimerInit() Local $sCommand_Send = '{"command":' & $sCommand & ',"request_id": ' & $i_Request_ID & '}' & @LF Local $sCommand_Success_String = '"request_id":' & $i_Request_ID & ',"error":"success"}' Local $sRes = _MPV_Command_Send_Request($sCommand_Send) If Not @error Then $sRes = _MPV_Wait_for_Event($sCommand_Success_String, $iTimeout) If Not @error Then Return $sRes EndIf ConsoleWrite("Debug: _MPV_Command_Send_and_Wait_for_Success error:" & @error & @CRLF) Return SetError(@error, @extended, $sRes) EndFunc ;==>_MPV_Command_Send_and_Wait_for_Success Func _MPV_Wait_for_Event($sEvent, $iTimeout = 1000) Local $iTimer_StartUp = TimerInit(), $sRes While Sleep(10) $sRes &= _MPV_Command_Read_Response($iTimeout) If @error Then Return SetError(@error, @extended, $sRes) If StringInStr($sRes, $sEvent) Then Return $sRes If TimerDiff($iTimer_StartUp) > 10000 Then Return SetError(1, "", "Playback not started-" & @ScriptLineNumber) WEnd EndFunc ;==>_MPV_Wait_for_Event Func _MPV_Command_Send_Request($sCommand) ; https://mpv.io/manual/stable/#commands ; https://mpv.io/manual/stable/#list-of-input-commands If Not IsHWnd($h_Global_MPV_Pipe) Then Return SetError(1, "", "Invalid pipe handle") Local $tBuffer = DllStructCreate("char[" & StringLen($sCommand) & "]") DllStructSetData($tBuffer, 1, $sCommand) Local $nBytes = 0 Local $iRes = _WinAPI_WriteFile($h_Global_MPV_Pipe, $tBuffer, DllStructGetSize($tBuffer), $nBytes) If $iRes = False Then Return SetError(2, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) Return $iRes EndFunc ;==>_MPV_Command_Send_Request Func _MPV_Command_Read_Response($iTimeout = 1000) ; https://mpv.io/manual/stable/#property-list If Not IsHWnd($h_Global_MPV_Pipe) Then Return SetError(1, "", "Invalid pipe handle") Local $tBuffer = DllStructCreate("char[4096]") Local $nBytes = 0, $iRes, $iTimer = TimerInit(), $aRes While 1 $iRes = _WinAPI_ReadFile($h_Global_MPV_Pipe, $tBuffer, DllStructGetSize($tBuffer), $nBytes) If $iRes = True Or _WinAPI_GetLastError() <> 232 Then ExitLoop ; 232 = NO_DATA If TimerDiff($iTimer) > 1000 Then ExitLoop Sleep(10) WEnd If $iRes = False Then Return SetError(3, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) Local $sRes = StringStripWS(_UTF8toUCS2(DllStructGetData($tBuffer, 1)), 3) Return $sRes EndFunc ;==>_MPV_Command_Read_Response Func _MPV_CloseProcesses() If $h_Global_MPV_Pipe Then If IsHWnd($h_Global_MPV_Pipe) Then _WinAPI_CloseHandle($h_Global_MPV_Pipe) EndIf $h_Global_MPV_Pipe = 0 EndIf Local $s_MPV_ProcessName = StringRight($s_Global_Path_MPV, StringLen($s_Global_Path_MPV) - StringInStr($s_Global_Path_MPV, "\", 0, -1)) If ProcessExists($s_MPV_ProcessName) Then Local $iTimer = TimerInit() While ProcessExists($s_MPV_ProcessName) ProcessClose($s_MPV_ProcessName) If TimerDiff($iTimer) > 3000 Then Return SetError(1, "", "Timeout") WEnd EndIf StdioClose($i_Global_MPV_PID) EndFunc ;==>_MPV_CloseProcesses Func _MPV_GetHandle() Local $iTimer = TimerInit() While 1 ; Local $hPipe = (_WinAPI_CreateFile($s_Global_Pipe_Name, 2, 6, 0)) ;_NamedPipes_CreateNamedPipe($s_Global_Pipe_Name);, 2,2,7) ; Local $hPipe = _WinAPI_CreateFile($s_Global_Pipe_Name, 2, 6, 0) If $hPipe = 0 Then If _WinAPI_GetLastError() <> 2 Then Return SetError(1, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) ElseIf IsHWnd($hPipe) Then _NamedPipes_SetNamedPipeHandleState($hPipe, 0, 1, 4096, 100) Return $hPipe EndIf If TimerDiff($iTimer) > 4000 Then ConsoleWrite("Debug: creat pipe Timeout" & @CRLF) Return SetError(2, "", "Timeout") EndIf Sleep(10) WEnd EndFunc ;==>_MPV_GetHandle Func _UCS2toUTF8($sString = "", $iFlag = 1) ; Convert UTF8 to ANSI to insert into DB ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497 ; ProgAndy ; Make ANSI-string representation out of UTF-8 ; $iFlag #cs Local Const $SF_ANSI = 1 Local Const $SF_UTF16_LE = 2 Local Const $SF_UTF16_BE = 3 Local Const $SF_UTF8 = 4 #ce Return BinaryToString(StringToBinary($sString, 4), $iFlag) EndFunc ;==>_UCS2toUTF8 Func _UTF8toUCS2($sString = "", $iFlag = 4) ; Extract ANSI and convert to UTF8 to display ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497 ; ProgAndy ; convert ANSI-UTF8 representation to ANSI/Unicode #cs Local Const $SF_ANSI = 1 Local Const $SF_UTF16_LE = 2 Local Const $SF_UTF16_BE = 3 Local Const $SF_UTF8 = 4 #ce Return BinaryToString(StringToBinary($sString, 1), $iFlag) EndFunc ;==>_UTF8toUCS2 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
KaFu Posted December 8, 2019 Author Share Posted December 8, 2019 URL is meant literally for that command: $sCommand = '{"command":["loadfile", "file:///' & StringReplace($s_Global_Path_MediaFile, "\", "/") & '","replace"]}' & @LF Gianni 1 OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Gianni Posted December 8, 2019 Share Posted December 8, 2019 in this way it works great! 👌 ...Interesting...Thanks KaFu Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
bladem2003 Posted April 17, 2021 Share Posted April 17, 2021 (edited) how can I write a variable to stdout? from the mpv manual: print-text <text> Print text to stdout. The string can contain properties (see Property Expansion). Take care to put the argument in quotes. I tried $s = '{"command":["print-text","${=chapter-list/count}"]}' _MPV_Command_Send_Request($s & @LF) but i don't get the number of chapters only INFO_CHAPTERS_COUNT=${=chapter-list/count} I have a little player attached Add mpv.exe and mpv.com to the mpv folder BasicMpvPlayer.zip Edited April 17, 2021 by bladem2003 Link to comment Share on other sites More sharing options...
KaFu Posted April 17, 2021 Author Share Posted April 17, 2021 ; https://github.com/mpv-player/mpv/issues/4026 $s = '{"command":["expand-properties","print-text","INFO_CHAPTERS_COUNT=${chapter-list/count}"]}' OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
bladem2003 Posted April 17, 2021 Share Posted April 17, 2021 Thanks KaFu Link to comment Share on other sites More sharing options...
bladem2003 Posted August 24, 2021 Share Posted August 24, 2021 Hi, I sometimes get an error from _MPV_GetHandle () "The system cannot find the file specified" and there is no connection to the pipe. The error is not reproducible, it runs 100 times without errors and then the error 5-6 times in a row. Link to comment Share on other sites More sharing options...
KaFu Posted August 24, 2021 Author Share Posted August 24, 2021 (edited) Hmm, doesn't ring a bell, did not happen to me as far as I can recall. Does mpv open up in that case? In your script above you use $s_Global_Pipe_Name = '\\.\pipe\mpv_' & $iPipeCount where $iPipeCount starts with 1. Is it possible that you restart the script and have a hanging pipe handle still open? In my scripts I use this to create a unique pipe name Global $s_Global_Pipe_Name = "\\.\pipe\MPVEnhancer" & TimerInit() Also I tweak the _MPV_GetHandle() code a little in my current player script (can't remember why 😉), maybe it helps too. Func _MPV_GetHandle($iTimeout = 5000) Local $iTimer = TimerInit() While 1 Local $hPipe = _WinAPI_CreateFile($s_Global_Pipe_Name, 2, 6, 0) If $hPipe = 0 And _WinAPI_GetLastError() > 0 Then If _WinAPI_GetLastError() <> 2 Then _ConsoleWrite("GetHandle-Error-1" & @CRLF) Return SetError(1, _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()) EndIf ElseIf IsHWnd($hPipe) Then Return $hPipe EndIf If TimerDiff($iTimer) > $iTimeout Then _ConsoleWrite("GetHandle-Error-2" & @CRLF) Return SetError(2, "", "_MPV_GetHandle-Timeout") EndIf Sleep(10) WEnd EndFunc ;==>_MPV_GetHandle Edited August 24, 2021 by KaFu OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
bladem2003 Posted August 25, 2021 Share Posted August 25, 2021 (edited) Hi KaFu, I changed the _MPV_GetHandle () with yours and change to $s_Global_Pipe_Name = "\\.\pipe\MPVEnhancer" & TimerInit() I get sometimes a pipe timeout (set to 10000) and sometimes error 231 All pipe instaces are busy. this happens when the pc is restarted and when it is called up for the first time very strange Edited August 25, 2021 by bladem2003 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now