VLC Player插件和自动激活
我习惯用VLC Player播放视频。它有个功能,如果电影看了一半,下次再打开时,会提示是否从上次中断的地方继续播放下去。但这个功能貌似不是很可靠。所以想自己搞个可靠的解决方案。
VLC Player可以用Lua写插件。Lua语言也是第一次用,经过不少时间的查找资料和调试,终于成功运行。
require 'common' function descriptor() return { title = "Monitor Position on Stop", shortcode = "mps", capabilities = { "input-listener", "playing-listener" } } end local file = nil function activate() local input = vlc.object.input() if not input then vlc.msg.err("[Monitor Position]No input object2 available") return end local filename = "C:\\Temp\\foo.txt" file, err = io.open(filename, "a+") if not file then vlc.msg.err("Failed to open file: " .. (err or "unknown error")) return end local lines = {} for line in file:lines() do table.insert(lines, line) end for i = #lines, 1, -1 do startIdx, endIdx = string.find(lines[i], "|") if startIdx ~= nil and endIdx ~= nil then clean_path = getFilePath() if clean_path == string.sub(lines[i], 1, startIdx - 1) then common.seek(tonumber(string.sub(lines[i], endIdx + 1))) break end end end end function getFilePath() local input = vlc.object.input() if not input then vlc.msg.err("[Monitor Position] No input available") return "" end local item = vlc.input.item() local uri = item:uri() or "unknown" local decoded_path = vlc.strings.decode_uri(uri) or "unknown" local clean_path = decoded_path if decoded_path:match("^file:///") then clean_path = decoded_path:sub(9):gsub("/", "\\") end return '"' .. clean_path .. '"' end function playing_changed() local input = vlc.object.input() if not input then vlc.msg.err("[Monitor Position] No input available") return end local state = vlc.var.get(input, "state") -- 4=stopped, 3=paused vlc.msg.err("[Monitor Position] Playing state changed to: " .. state) if state == 4 or state == 3 then -- Stopped (or end-reached) local clean_path = getFilePath() local pos_us = vlc.var.get(input, "time") or 0 local pos_sec = pos_us / 1000000 local log_line = string.format('%s|%d\n\n', clean_path, pos_sec) if file then file:write(log_line) file:flush() end end end function meta_changed() end function input_changed() end
激活插件时,首先执行 activate 函数,从文件中读取记录,如果有和当前播放文件名相同的,则从记录的播放时间开始播放。当点击暂停按钮或者停止按钮或者关掉VLC Player时,就把当前的播放时间记录到文件里。
meta_changed() 和 input_changed() 两个函数是空的,作用是避免在日志文件里出现没必要的warning信息。调试语句都用vlc.msg.err而不用vlc.msg.info,目的是为了避免打开日志文件时,出现大量无关信息,影响阅读。当然,在调试完成,运行基本正常后,可以改成info。
但有个问题,这个插件不会自动激活,每次打开VLC Player后,都必须手工到View菜单下,找到插件,再点击激活。感觉很不方便。于是找自动激活的办法。
查找资料后,发现唯一的方法是通过Interface脚本实现。但是Interface脚本里,不能用上面的playing_changed函数,而只能用一个死循环,类似windows的消息循环来实现。感觉占用cpu,不是很满意。
花了不少时间,想了个办法,用autoit脚本去激活:
#include <Constants.au3> Opt("WinTitleMatchMode", $OPT_MATCHANY) $hWnd = _WinWaitActivate("- VLC media player","") $aPos = WinGetPos($hWnd) MouseClick("right", $aPos[0] + 100, $aPos[1] + $aPos[3] - 20) For $i = 1 to 10 Send("{DOWN}") Next Send("{RIGHT}") For $i = 1 to 9 Send("{DOWN}") Next Send("{ENTER}") Func _WinWaitActivate($title,$text,$timeout=0) WinWait($title,$text,$timeout) If Not WinActive($title,$text) Then WinActivate($title,$text) Return WinWaitActive($title,$text,$timeout) EndFunc
其中9这个数字是调试出来的,具体要循环几次,要看插件在菜单中的位置。
然后写个Interface脚本,就一行:
os.execute("C:\\autoit\\autoit3.exe C:\\autoit\\activateVlcExtension.au3")
然后在vlcrc文件(一般在C:\Users\<用户名>\AppData\Roaming\vlc目录下)里,找到
# Lua interface (string)
lua-intf=<Interface脚本名>
最后,打开VLC Player,点开Tools - Preference,勾选All,然后找到Main interfaces,点选Lua interpreter,保存。重新启动VLC Player,就可以了。
缺点:一是每次启动VLC时,要等一两秒钟,二是记录时间的文件会逐渐变大,需要手工定期清理。
另外说点对Lua语言的印象。觉得它的函数可以返回多个值,这个不错,string类没有split方法,不太方便。总体感觉语法还算简洁,用起来基本没什么难度。

浙公网安备 33010602011771号