mirror of
https://github.com/jellyfin/jellyfin-mpv-shim.git
synced 2024-11-27 00:00:37 +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/default_shader_pack *
|
||||||
recursive-include jellyfin_mpv_shim/messages *.mo
|
recursive-include jellyfin_mpv_shim/messages *.mo
|
||||||
include jellyfin_mpv_shim/mouse.lua
|
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
|
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
|
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
|
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`
|
overriding the default MPV OSC, which may conflict with some custom user script. Trickplay is compatible
|
||||||
file contains the feature if you want to make a modified version.
|
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_enable` - Enable thumbnail feature. (Default: `true`)
|
||||||
- `thumbnail_jellyscrub` - Use JellyScrub as the thumbnail source instead of chapter images. (Default: `false`)
|
- `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`)
|
- `thumbnail_preferred_size` - The ideal size for thumbnails. (Default: `320`)
|
||||||
|
|
||||||
### SVP Integration
|
### SVP Integration
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
rd /s /q __pycache__ dist build
|
rd /s /q __pycache__ dist build
|
||||||
set PATH=%PATH%;%CD%
|
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%
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
del dist\run\run.exe.manifest
|
del dist\run\run.exe.manifest
|
||||||
copy hidpi.manifest dist\run\run.exe.manifest
|
copy hidpi.manifest dist\run\run.exe.manifest
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
rd /s /q __pycache__ dist build
|
rd /s /q __pycache__ dist build
|
||||||
set PATH=%PATH%;%CD%
|
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%
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
del dist\run\run.exe.manifest
|
del dist\run\run.exe.manifest
|
||||||
copy hidpi.manifest 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
|
skip_intro_prompt: bool = False
|
||||||
thumbnail_enable: bool = True
|
thumbnail_enable: bool = True
|
||||||
thumbnail_jellyscrub: bool = False
|
thumbnail_jellyscrub: bool = False
|
||||||
thumbnail_custom_script: Optional[str] = None
|
thumbnail_osc_builtin: bool = True
|
||||||
thumbnail_preferred_size: int = 320
|
thumbnail_preferred_size: int = 320
|
||||||
|
|
||||||
def __get_file(self, path: str, mode: str = "r", create: bool = True):
|
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 = TrickPlay(self)
|
||||||
self.trickplay.start()
|
self.trickplay.start()
|
||||||
|
|
||||||
if settings.thumbnail_custom_script:
|
scripts.append(get_resource("thumbfast.lua"))
|
||||||
scripts.append(settings.thumbnail_custom_script)
|
if settings.thumbnail_osc_builtin:
|
||||||
else:
|
scripts.append(get_resource("trickplay-osc.lua"))
|
||||||
scripts.append(get_resource("trickplay.lua"))
|
|
||||||
except Exception:
|
except Exception:
|
||||||
log.error("Could not enable trickplay.", exc_info=True)
|
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.
|
-- 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.
|
-- 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 assdraw = require 'mp.assdraw'
|
||||||
local msg = require 'mp.msg'
|
local msg = require 'mp.msg'
|
||||||
local opt = require 'mp.options'
|
local opt = require 'mp.options'
|
||||||
local utils = require 'mp.utils'
|
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
|
-- Parameters
|
||||||
--
|
--
|
||||||
@ -896,39 +860,23 @@ function render_elements(master_ass)
|
|||||||
|
|
||||||
-- BEGIN patch add thumbnails
|
-- BEGIN patch add thumbnails
|
||||||
local duration = mp.get_property_number("duration", nil)
|
local duration = mp.get_property_number("duration", nil)
|
||||||
if img_enabled and not ((duration == nil) or (sliderpos == nil)) then
|
if thumbfast.available 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
|
|
||||||
should_render_preview = true
|
should_render_preview = true
|
||||||
if frame ~= img_last_frame then
|
local sx, sy = get_virt_scale_factor()
|
||||||
if img_is_bif and frame >= img_count then
|
local mX, mY = get_virt_mouse_pos()
|
||||||
frame = img_count -1
|
mp.commandv("script-message-to", "thumbfast", "thumb",
|
||||||
end
|
duration * (sliderpos / 100),
|
||||||
local offset = frame * img_width * img_height * 4
|
math.floor(mX / sx - thumbfast.width / 2),
|
||||||
-- 46 is a random number, but hopefully it won't conflict with other extensions
|
math.floor((element.hitbox.y1 - 24) / sy - thumbfast.height)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
-- END patch add thumbnails
|
-- END patch add thumbnails
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- BEGIN patch add thumbnails
|
-- BEGIN patch add thumbnails
|
||||||
if img_is_shown and not should_render_preview then
|
if thumbfast.available and not should_render_preview then
|
||||||
mp.commandv("overlay-remove", 46)
|
mp.commandv("script-message-to", "thumbfast", "clear")
|
||||||
end
|
end
|
||||||
-- END patch add thumbnails
|
-- END patch add thumbnails
|
||||||
|
|
||||||
@ -2562,8 +2510,8 @@ function render()
|
|||||||
render_elements(ass)
|
render_elements(ass)
|
||||||
else
|
else
|
||||||
-- BEGIN patch add thumbnails
|
-- BEGIN patch add thumbnails
|
||||||
if img_is_shown then
|
if thumbfast.available then
|
||||||
mp.commandv("overlay-remove", 46)
|
mp.commandv("script-message-to", "thumbfast", "clear")
|
||||||
end
|
end
|
||||||
-- END patch add thumbnails
|
-- END patch add thumbnails
|
||||||
end
|
end
|
Loading…
Reference in New Issue
Block a user