Metadata - mpv-jellyfin - MPV script for adding an interface for Jellyfin.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit e674db1a8e8867e6ed06a3023a54d5cc10e37afc
(DIR) parent 04bef7fbe5bcbfd42f4366228394d1b2e6a5d7cc
(HTM) Author: EmperorPenguin18 <60635017+EmperorPenguin18@users.noreply.github.com>
Date: Tue, 15 Nov 2022 14:31:09 -0500
Metadata
Diffstat:
M script-opts/jellyfin.conf | 2 ++
M scripts/jellyfin.lua | 147 +++++++++++++++++++++++++------
2 files changed, 122 insertions(+), 27 deletions(-)
---
(DIR) diff --git a/script-opts/jellyfin.conf b/script-opts/jellyfin.conf
@@ -1,3 +1,5 @@
url=
username=
password=
+image_path=
+hide_spoilers=
(DIR) diff --git a/scripts/jellyfin.lua b/scripts/jellyfin.lua
@@ -4,21 +4,25 @@ local utils = require 'mp.utils'
local options = {
url = "",
username = "",
- password = ""
+ password = "",
+ image_path = "",
+ hide_spoilers = "on"
}
opt.read_options(options, mp.get_script_name())
local overlay = mp.create_osd_overlay("ass-events")
+local meta_overlay = mp.create_osd_overlay("ass-events")
local connected = false
local shown = false
-local user_id = nil
-local api_key = nil
+local user_id = ""
+local api_key = ""
local library_id = nil
local title_id = nil
local season_id = nil
-local video_id = nil
+local video_id = ""
local selection = 1
local items = {}
+local ow, oh, op = 0, 0, 0
local toggle_overlay
@@ -36,26 +40,74 @@ local function send_request(url)
return nil
end
-local function connect()
- local request = mp.command_native({
- name = "subprocess",
- capture_stdout = true,
- capture_stderr = true,
- playback_only = false,
- args = {"curl", options.url.."/Users/AuthenticateByName", "-H", "accept: application/json", "-H", "content-type: application/json", "-H", "x-emby-authorization: MediaBrowser Client=\"Custom Client\", Device=\"Custom Device\", DeviceId=\"1\", Version=\"0.0.1\"", "-d", "{\"username\":\""..options.username.."\",\"Pw\":\""..options.password.."\"}"}
- })
- local result = utils.parse_json(request.stdout)
- user_id = result.User.Id
- api_key = result.AccessToken
- connected = true
+local function line_break(str, flags, space)
+ if str == nil then return "" end
+ local text = flags
+ local n = 0
+ for i = 1, #str do
+ local c = str:sub(i, i)
+ if (c == ' ' and i-n > space) or c == '\n' then
+ text = text..str:sub(n, i-1).."\n"..flags
+ n = i+1
+ end
+ end
+ text = text..str:sub(n, -1)
+ return text
+end
+
+local function update_metadata()
+ local metadata = send_request(options.url.."/Users/"..user_id.."/Items/"..items[selection].Id.."?api_key="..api_key)
+ local image_data = nil
+ for _, image in ipairs(send_request(options.url.."/Items/"..metadata.Id.."/Images?api_key="..api_key)) do
+ if image.ImageType == "Primary" then
+ image_data = image
+ end
+ end
+ mp.commandv("overlay-remove", "0")
+ if image_data then
+ local filepath = options.image_path.."/"..metadata.Name..".bgra"
+ local ratio = image_data.Height / image_data.Width
+ if ratio > 0.5 then
+ local width = math.floor(ow/3)
+ local height = math.floor(width*ratio)
+ local res = mp.command_native({ name = "subprocess", args = { "mpv", options.url.."/Items/"..metadata.Id.."/Images/Primary?api_key="..api_key, "--no-config", "--msg-level=all=no", "--vf=lavfi=[scale="..width..":"..height..",format=bgra]", "--of=rawvideo", "--o="..filepath }, playback_only = false })
+ mp.commandv("overlay-add", "0", tostring(math.floor(ow/2.5)), tostring(10), filepath, "0", "bgra", tostring(width), tostring(height), tostring(width*4))
+ end
+ end
+
+ meta_overlay.data = ""
+ local name = line_break(metadata.Name, "{\\a7}{\\fs24}", 30)
+ meta_overlay.data = meta_overlay.data..name.."\n"
+ local year = ""
+ if metadata.ProductionYear then year = metadata.ProductionYear end
+ local time = ""
+ if metadata.RunTimeTicks then time = " "..math.floor(metadata.RunTimeTicks/600000000).."m" end
+ local rating = ""
+ if metadata.CommunityRating then rating = " "..metadata.CommunityRating end
+ local hidden = ""
+ local watched = ""
+ if metadata.UserData.Played == false then
+ if options.hide_spoilers ~= "off" then hidden = "{\\bord0}{\\1a&HFF&}" end
+ else
+ watched = " Watched"
+ end
+ local favourite = ""
+ if metadata.UserData.IsFavorite == true then
+ favourite = " Favorite"
+ end
+ meta_overlay.data = meta_overlay.data.."{\\a7}{\\fs16}"..year..time..rating..watched..favourite.."\n\n"
+ local tagline = line_break(metadata.Taglines[1], "{\\a7}{\\fs20}", 35)
+ meta_overlay.data = meta_overlay.data..tagline.."\n"
+ local description = line_break(metadata.Overview, "{\\a7}{\\fs16}"..hidden, 45)
+ meta_overlay.data = meta_overlay.data..description
+ meta_overlay:update()
end
local function update_data()
overlay.data = ""
- local ow, oh, op = mp.get_osd_size()
for _, item in ipairs(items) do
- if _ >= selection - (19.5 * op / 1.12) + 1 then
- if _ - selection < (19.5 * op / 1.12) then
+ if _ > selection - (53 / op) then
+ if _ < selection + (20 * op) then
if _ == selection then
overlay.data = overlay.data.."{\\fs16}{\\c&HFF&}"..item.Name.."\n"
else
@@ -67,6 +119,20 @@ local function update_data()
overlay:update()
end
+local function resize()
+ ow, oh, op = mp.get_osd_size()
+end
+
+local function refresh()
+ resize()
+ update_data()
+ update_metadata()
+end
+
+local function property_change(name, data)
+ refresh()
+end
+
local function update_overlay()
local result
if not library_id then
@@ -79,18 +145,20 @@ local function update_overlay()
result = send_request(options.url.."/Items?api_key="..api_key.."&userID="..user_id.."&parentId="..season_id)
end
items = result.Items
- update_data()
+ if ow > 0 then refresh() end
end
local function play_video()
toggle_overlay()
mp.commandv("loadfile", options.url.."/Videos/"..video_id.."/stream?static=true&api_key="..api_key)
+ mp.set_property("force-media-title", items[selection].Name)
end
local function key_up()
selection = selection - 1
if selection == 0 then selection = table.getn(items) end
update_data()
+ update_metadata()
end
local function key_right()
@@ -115,11 +183,12 @@ local function key_down()
selection = selection + 1
if selection > table.getn(items) then selection = 1 end
update_data()
+ update_metadata()
end
local function key_left()
if not library_id then
- --nothing
+ return
elseif not title_id then
library_id = nil
elseif not season_id then
@@ -130,20 +199,44 @@ local function key_left()
update_overlay()
end
+local function connect()
+ local request = mp.command_native({
+ name = "subprocess",
+ capture_stdout = true,
+ capture_stderr = true,
+ playback_only = false,
+ args = {"curl", options.url.."/Users/AuthenticateByName", "-H", "accept: application/json", "-H", "content-type: application/json", "-H", "x-emby-authorization: MediaBrowser Client=\"Custom Client\", Device=\"Custom Device\", DeviceId=\"1\", Version=\"0.0.1\"", "-d", "{\"username\":\""..options.username.."\",\"Pw\":\""..options.password.."\"}"}
+ })
+ local result = utils.parse_json(request.stdout)
+ user_id = result.User.Id
+ api_key = result.AccessToken
+ connected = true
+end
+
toggle_overlay = function()
if shown then
- overlay:remove()
mp.remove_key_binding("jup")
mp.remove_key_binding("jright")
mp.remove_key_binding("jdown")
mp.remove_key_binding("jleft")
+ mp.unobserve_property(property_change)
+ mp.commandv("overlay-remove", "0")
+ overlay:remove()
+ meta_overlay:remove()
else
- if not connected then connect() end
- if table.getn(items) == 0 then update_overlay() end
- mp.add_forced_key_binding("UP", "jup", key_up)
+ mp.add_forced_key_binding("UP", "jup", key_up, { repeatable = true })
mp.add_forced_key_binding("RIGHT", "jright", key_right)
- mp.add_forced_key_binding("DOWN", "jdown", key_down)
+ mp.add_forced_key_binding("DOWN", "jdown", key_down, { repeatable = true })
mp.add_forced_key_binding("LEFT", "jleft", key_left)
+ if not connected then
+ mp.observe_property("osd-width", number, property_change)
+ connect()
+ end
+ if table.getn(items) == 0 then
+ update_overlay()
+ else
+ refresh()
+ end
end
shown = not shown
end
@@ -151,7 +244,7 @@ end
local function mark_watched(data)
if data.reason == "eof" then
send_request(options.url.."/Users/"..user_id.."/PlayedItems/"..video_id.."?api_key="..api_key)
- video_id = nil
+ video_id = ""
end
end