
hi, i have vibe coded a VLC plugin to view my jellyfin library directly from VLC (no copy stream URL necessary). maybe helpful for some of you too. here are the necessary steps for macOS, for windows/linux i have no idea:
- navigate to
System/Volumes/Data/Applications/VLC.app/Contents/MacOS/share/lua/sd - create a file called
jellyfin.lua - paste the following content in the file:
-- jellyfin.lua (Single-File Service Discovery)
local json = require("dkjson")
-- ================= CONFIGURATION =================
local JELLYFIN_URL = "YOUR_JELLYFIN_URL"
local API_KEY = "YOUR_JELLYFIN_API_KEY" -- generate api key in jellyfin admin dashboard
local USER_ID = "YOUR_JELLYFIN_USER_ID" -- not the username, click on your profile in the jellyfin browser page, will appear in the url then
-- =================================================
function descriptor()
return { title = "Jellyfin Library" }
end
-- Helper to download and parse JSON from the API
function fetch_json(url)
local stream = vlc.stream(url)
if not stream then return {} end
local content = ""
local line = ""
repeat
line = stream:readline()
if line then content = content .. line end
until line == nil
return json.decode(content) or {}
end
-- Main function builds the entire tree on load
function main()
-- Get the user's libraries (e.g., "Movies", "TV Shows")
local views_url = JELLYFIN_URL .. "/Users/" .. USER_ID .. "/Views?api_key=" .. API_KEY
local views_data = fetch_json(views_url)
if views_data and views_data.Items then
for _, library in ipairs(views_data.Items) do
local ctype = library.CollectionType or "unknown"
if ctype == "tvshows" then
-- 1. Create the main "TV Shows" Folder
local tv_node = vlc.sd.add_node({ title = "📺 " .. library.Name })
-- 2. Fetch all TV Series inside this library
local shows_url = JELLYFIN_URL .. "/Users/" .. USER_ID .. "/Items?ParentId=" .. library.Id .. "&IncludeItemTypes=Series&Recursive=true&api_key=" .. API_KEY
local shows_data = fetch_json(shows_url)
for _, show in ipairs(shows_data.Items or {}) do
-- 3. Create a Folder for each specific TV Show (e.g., "The Discounters")
local show_node = tv_node:add_subnode({ title = "📂 " .. show.Name })
-- 4. Fetch all Episodes for this specific TV Show
local eps_url = JELLYFIN_URL .. "/Users/" .. USER_ID .. "/Items?ParentId=" .. show.Id .. "&IncludeItemTypes=Episode&Recursive=true&api_key=" .. API_KEY
local eps_data = fetch_json(eps_url)
for _, ep in ipairs(eps_data.Items or {}) do
-- 5. Add the actual playable episode files into the Show folder
local season = ep.ParentIndexNumber or 0
local ep_num = ep.IndexNumber or 0
local formatted_title = string.format("S%02dE%02d - %s", season, ep_num, ep.Name)
show_node:add_subitem({
title = formatted_title,
path = JELLYFIN_URL .. "/Videos/" .. ep.Id .. "/stream?static=true&api_key=" .. API_KEY,
arturl = JELLYFIN_URL .. "/Items/" .. ep.Id .. "/Images/Primary?api_key=" .. API_KEY
})
end
end
else
-- 1. Create the main "Movies" Folder
local movie_node = vlc.sd.add_node({ title = "🎬 " .. library.Name })
-- 2. Fetch all Movies and add them directly as playable items
local movies_url = JELLYFIN_URL .. "/Users/" .. USER_ID .. "/Items?ParentId=" .. library.Id .. "&IncludeItemTypes=Movie&Recursive=true&api_key=" .. API_KEY
local movies_data = fetch_json(movies_url)
for _, movie in ipairs(movies_data.Items or {}) do
movie_node:add_subitem({
title = movie.Name,
path = JELLYFIN_URL .. "/Videos/" .. movie.Id .. "/stream?static=true&api_key=" .. API_KEY,
arturl = JELLYFIN_URL .. "/Items/" .. movie.Id .. "/Images/Primary?api_key=" .. API_KEY
})
end
end
end
end
end
- replace YOUR_JELLYFIN_URL, YOUR_JELLYFIN_API_KEY and YOUR_JELLYFIN_USER_ID with your credentials
- restart VLC
- done! you should see the jellyfin library as in the attached screenshot
u/Jochen_der_Rochen — 26 days ago