mirror of
https://github.com/jellyfin/jellyfin-mpv-shim.git
synced 2024-11-22 21:49:41 +00:00
Add thumbfast compatibility layer to support alternate OSCs.
This commit is contained in:
parent
6710f2deb8
commit
acbc3e9d0c
@ -3,4 +3,5 @@ recursive-include jellyfin_mpv_shim/integration *
|
||||
recursive-include jellyfin_mpv_shim/default_shader_pack *
|
||||
recursive-include jellyfin_mpv_shim/messages *.mo
|
||||
include jellyfin_mpv_shim/mouse.lua
|
||||
include jellyfin_mpv_shim/trickplay.lua
|
||||
include jellyfin_mpv_shim/trickplay-osc.lua
|
||||
include jellyfin_mpv_shim/thumbfast.lua
|
||||
|
@ -313,12 +313,12 @@ MPV will automatically display thumbnail previews. By default it uses the Jellyf
|
||||
but it can also use JellyScrub as the source. Please note that this feature will download and
|
||||
uncompress all of the chapter images before it becomes available for a video. For a 4 hour movie this
|
||||
causes disk usage of about 250 MB, but for the average TV episode it is around 40 MB. It also requires
|
||||
overriding the default MPV OSC, which may conflict with some custom user script. The `trickplay.lua`
|
||||
file contains the feature if you want to make a modified version.
|
||||
overriding the default MPV OSC, which may conflict with some custom user script. Trickplay is compatible
|
||||
with any OSC that uses [thumbfast](https://github.com/po5/thumbfast), as I have added a [compatibility layer](https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/jellyfin_mpv_shim/thumbfast.lua).
|
||||
|
||||
- `thumbnail_enable` - Enable thumbnail feature. (Default: `true`)
|
||||
- `thumbnail_jellyscrub` - Use JellyScrub as the thumbnail source instead of chapter images. (Default: `false`)
|
||||
- `thumbnail_custom_script` - If enabled, it disables the default `trickplay.lua` so you can provide a modified version. (Default: `null`)
|
||||
- `thumbnail_osc_builtin` - Disable this setting if you want to use your own custom osc but leave trickplay enabled. (Default: `true`)
|
||||
- `thumbnail_preferred_size` - The ideal size for thumbnails. (Default: `320`)
|
||||
|
||||
### SVP Integration
|
||||
|
@ -1,7 +1,7 @@
|
||||
@echo off
|
||||
rd /s /q __pycache__ dist build
|
||||
set PATH=%PATH%;%CD%
|
||||
pyinstaller -w --add-binary "mpv-2.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\trickplay.lua;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
pyinstaller -w --add-binary "mpv-2.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\trickplay-osc.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\thumbfast.lua;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
del dist\run\run.exe.manifest
|
||||
copy hidpi.manifest dist\run\run.exe.manifest
|
||||
|
@ -1,7 +1,7 @@
|
||||
@echo off
|
||||
rd /s /q __pycache__ dist build
|
||||
set PATH=%PATH%;%CD%
|
||||
pyinstaller -w --add-binary "mpv-2.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\trickplay.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
pyinstaller -w --add-binary "mpv-2.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\trickplay-osc.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\thumbfast.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
del dist\run\run.exe.manifest
|
||||
copy hidpi.manifest dist\run\run.exe.manifest
|
||||
|
@ -128,7 +128,7 @@ class Settings(SettingsBase):
|
||||
skip_intro_prompt: bool = False
|
||||
thumbnail_enable: bool = True
|
||||
thumbnail_jellyscrub: bool = False
|
||||
thumbnail_custom_script: Optional[str] = None
|
||||
thumbnail_osc_builtin: bool = True
|
||||
thumbnail_preferred_size: int = 320
|
||||
|
||||
def __get_file(self, path: str, mode: str = "r", create: bool = True):
|
||||
|
@ -176,10 +176,10 @@ class PlayerManager(object):
|
||||
self.trickplay = TrickPlay(self)
|
||||
self.trickplay.start()
|
||||
|
||||
if settings.thumbnail_custom_script:
|
||||
scripts.append(settings.thumbnail_custom_script)
|
||||
else:
|
||||
scripts.append(get_resource("trickplay.lua"))
|
||||
scripts.append(get_resource("thumbfast.lua"))
|
||||
if settings.thumbnail_osc_builtin:
|
||||
scripts.append(get_resource("trickplay-osc.lua"))
|
||||
|
||||
except Exception:
|
||||
log.error("Could not enable trickplay.", exc_info=True)
|
||||
|
||||
|
111
jellyfin_mpv_shim/thumbfast.lua
Normal file
111
jellyfin_mpv_shim/thumbfast.lua
Normal file
@ -0,0 +1,111 @@
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
img_count = 0
|
||||
img_multiplier = 0
|
||||
img_width = 0
|
||||
img_height = 0
|
||||
img_file = ""
|
||||
img_last_frame = -1
|
||||
img_is_shown = false
|
||||
img_enabled = false
|
||||
img_is_bif = false
|
||||
img_chapters = {}
|
||||
img_overlay_id = 46
|
||||
|
||||
function send_thumbfast_message()
|
||||
local json, err = utils.format_json({
|
||||
width = img_width,
|
||||
height = img_height,
|
||||
disabled = not img_enabled,
|
||||
available = img_enabled,
|
||||
overlay_id = img_overlay_id
|
||||
})
|
||||
if err ~= nil
|
||||
then
|
||||
mp.log("error", "Failed to format JSON: " .. err)
|
||||
else
|
||||
mp.commandv("script-message", "thumbfast-info", json)
|
||||
end
|
||||
end
|
||||
|
||||
function client_message_handler(event)
|
||||
local event_name = event["args"][1]
|
||||
if event_name == "shim-trickplay-clear"
|
||||
then
|
||||
mp.log("info", "Clearing trickplay.")
|
||||
img_enabled = false
|
||||
if img_is_shown
|
||||
then
|
||||
mp.commandv("overlay-remove", 46)
|
||||
img_is_shown = false
|
||||
end
|
||||
send_thumbfast_message()
|
||||
elseif event_name == "shim-trickplay-bif"
|
||||
then
|
||||
mp.log("info", "Received BIF data.")
|
||||
img_count = tonumber(event["args"][2])
|
||||
img_multiplier = tonumber(event["args"][3])
|
||||
img_width = tonumber(event["args"][4])
|
||||
img_height = tonumber(event["args"][5])
|
||||
img_file = event["args"][6]
|
||||
img_last_frame = -1
|
||||
img_enabled = true
|
||||
img_is_bif = true
|
||||
send_thumbfast_message()
|
||||
elseif event_name == "shim-trickplay-chapters"
|
||||
then
|
||||
mp.log("info", "Received chapter metadata.")
|
||||
img_width = tonumber(event["args"][2])
|
||||
img_height = tonumber(event["args"][3])
|
||||
img_file = event["args"][4]
|
||||
|
||||
img_chapters = {}
|
||||
for timestamp in string.gmatch(event["args"][5], '([^,]+)') do
|
||||
table.insert(img_chapters, tonumber(timestamp))
|
||||
end
|
||||
|
||||
img_last_frame = -1
|
||||
img_enabled = true
|
||||
img_is_bif = false
|
||||
send_thumbfast_message()
|
||||
elseif event_name == "thumb"
|
||||
then
|
||||
local offset_seconds = tonumber(event["args"][2])
|
||||
local x = tonumber(event["args"][3])
|
||||
local y = tonumber(event["args"][4])
|
||||
if offset_seconds == nil or x == nil or y == nil then
|
||||
return
|
||||
end
|
||||
|
||||
if img_enabled then
|
||||
local frame = 0;
|
||||
if img_is_bif then
|
||||
frame = math.floor(offset_seconds / (img_multiplier / 1000))
|
||||
else
|
||||
for i = #img_chapters, 1, -1 do
|
||||
if img_chapters[i] <= offset_seconds then
|
||||
frame = i - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
should_render_preview = true
|
||||
if frame ~= img_last_frame then
|
||||
if img_is_bif and frame >= img_count then
|
||||
frame = img_count -1
|
||||
end
|
||||
local offset = frame * img_width * img_height * 4
|
||||
img_is_shown = true
|
||||
mp.commandv("overlay-add", img_overlay_id, x, y, img_file, offset, "bgra", img_width, img_height, img_width * 4)
|
||||
end
|
||||
end
|
||||
elseif event_name == "clear"
|
||||
then
|
||||
if img_is_shown
|
||||
then
|
||||
mp.commandv("overlay-remove", img_overlay_id)
|
||||
img_is_shown = false
|
||||
end
|
||||
end
|
||||
end
|
||||
mp.register_event("client-message", client_message_handler)
|
@ -2,65 +2,29 @@
|
||||
-- Sadly there is no way to do this without forking the entire OSC script.
|
||||
-- All of my changes are marked with -- BEGIN patch and -- END patch.
|
||||
|
||||
-- BEGIN patch add thumbnails
|
||||
img_count = 0
|
||||
img_multiplier = 0
|
||||
img_width = 0
|
||||
img_height = 132
|
||||
img_file = ""
|
||||
img_last_frame = -1
|
||||
img_is_shown = false
|
||||
img_enabled = false
|
||||
img_is_bif = false
|
||||
img_chapters = {}
|
||||
|
||||
function client_message_handler(event)
|
||||
local event_name = event["args"][1]
|
||||
if event_name == "shim-trickplay-clear"
|
||||
then
|
||||
mp.log("info", "Clearing trickplay.")
|
||||
img_enabled = false
|
||||
if img_is_shown
|
||||
then
|
||||
mp.commandv("overlay-remove", 46)
|
||||
img_is_shown = false
|
||||
end
|
||||
elseif event_name == "shim-trickplay-bif"
|
||||
then
|
||||
mp.log("info", "Received BIF data.")
|
||||
img_count = tonumber(event["args"][2])
|
||||
img_multiplier = tonumber(event["args"][3])
|
||||
img_width = tonumber(event["args"][4])
|
||||
img_height = tonumber(event["args"][5])
|
||||
img_file = event["args"][6]
|
||||
img_last_frame = -1
|
||||
img_enabled = true
|
||||
img_is_bif = true
|
||||
elseif event_name == "shim-trickplay-chapters"
|
||||
then
|
||||
mp.log("info", "Received chapter metadata.")
|
||||
img_width = tonumber(event["args"][2])
|
||||
img_height = tonumber(event["args"][3])
|
||||
img_file = event["args"][4]
|
||||
|
||||
img_chapters = {}
|
||||
for timestamp in string.gmatch(event["args"][5], '([^,]+)') do
|
||||
table.insert(img_chapters, tonumber(timestamp))
|
||||
end
|
||||
|
||||
img_last_frame = -1
|
||||
img_enabled = true
|
||||
img_is_bif = false
|
||||
end
|
||||
end
|
||||
mp.register_event("client-message", client_message_handler)
|
||||
-- END patch add thumbnails
|
||||
|
||||
local assdraw = require 'mp.assdraw'
|
||||
local msg = require 'mp.msg'
|
||||
local opt = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
-- BEGIN patch add thumbnails
|
||||
local thumbfast = {
|
||||
width = 0,
|
||||
height = 0,
|
||||
disabled = true,
|
||||
available = false
|
||||
}
|
||||
|
||||
mp.register_script_message("thumbfast-info", function(json)
|
||||
local data = utils.parse_json(json)
|
||||
if type(data) ~= "table" or not data.width or not data.height then
|
||||
msg.error("thumbfast-info: received json didn't produce a table with thumbnail information")
|
||||
else
|
||||
thumbfast = data
|
||||
end
|
||||
end)
|
||||
-- END patch add thumbnails
|
||||
|
||||
--
|
||||
-- Parameters
|
||||
--
|
||||
@ -896,39 +860,23 @@ function render_elements(master_ass)
|
||||
|
||||
-- BEGIN patch add thumbnails
|
||||
local duration = mp.get_property_number("duration", nil)
|
||||
if img_enabled and not ((duration == nil) or (sliderpos == nil)) then
|
||||
local frame = 0;
|
||||
if img_is_bif then
|
||||
frame = math.floor(duration * (sliderpos / 100) / (img_multiplier / 1000))
|
||||
else
|
||||
local current_time = duration * (sliderpos / 100)
|
||||
for i = #img_chapters, 1, -1 do
|
||||
if img_chapters[i] <= current_time then
|
||||
frame = i - 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if thumbfast.available and not ((duration == nil) or (sliderpos == nil)) then
|
||||
should_render_preview = true
|
||||
if frame ~= img_last_frame then
|
||||
if img_is_bif and frame >= img_count then
|
||||
frame = img_count -1
|
||||
end
|
||||
local offset = frame * img_width * img_height * 4
|
||||
-- 46 is a random number, but hopefully it won't conflict with other extensions
|
||||
local sx, sy = get_virt_scale_factor()
|
||||
local mX, mY = get_virt_mouse_pos()
|
||||
img_is_shown = true
|
||||
mp.commandv("overlay-add", 46, math.floor(mX / sx - img_width / 2), math.floor((element.hitbox.y1 - 24) / sy - img_height), img_file, offset, "bgra", img_width, img_height, img_width * 4)
|
||||
end
|
||||
local sx, sy = get_virt_scale_factor()
|
||||
local mX, mY = get_virt_mouse_pos()
|
||||
mp.commandv("script-message-to", "thumbfast", "thumb",
|
||||
duration * (sliderpos / 100),
|
||||
math.floor(mX / sx - thumbfast.width / 2),
|
||||
math.floor((element.hitbox.y1 - 24) / sy - thumbfast.height)
|
||||
)
|
||||
end
|
||||
-- END patch add thumbnails
|
||||
end
|
||||
end
|
||||
|
||||
-- BEGIN patch add thumbnails
|
||||
if img_is_shown and not should_render_preview then
|
||||
mp.commandv("overlay-remove", 46)
|
||||
if thumbfast.available and not should_render_preview then
|
||||
mp.commandv("script-message-to", "thumbfast", "clear")
|
||||
end
|
||||
-- END patch add thumbnails
|
||||
|
||||
@ -2562,8 +2510,8 @@ function render()
|
||||
render_elements(ass)
|
||||
else
|
||||
-- BEGIN patch add thumbnails
|
||||
if img_is_shown then
|
||||
mp.commandv("overlay-remove", 46)
|
||||
if thumbfast.available then
|
||||
mp.commandv("script-message-to", "thumbfast", "clear")
|
||||
end
|
||||
-- END patch add thumbnails
|
||||
end
|
Loading…
Reference in New Issue
Block a user