feat: support embedded cover for video preview

This commit is contained in:
sxyazi 2025-04-19 23:04:00 +08:00
parent ce23dcd81b
commit 13deece2f6
No known key found for this signature in database

View file

@ -27,12 +27,6 @@ function M:seek(job)
end end
function M:preload(job) function M:preload(job)
local percent = 5 + job.skip
if percent > 95 then
ya.mgr_emit("peek", { 90, only_if = job.file.url, upper_bound = true })
return false
end
local cache = ya.file_cache(job) local cache = ya.file_cache(job)
if not cache then if not cache then
return true return true
@ -43,23 +37,39 @@ function M:preload(job)
return true return true
end end
local meta, err = self.list_meta(job.file.url, "format=duration") local meta, err = self.list_meta(job.file.url, "format=duration:stream_disposition=attached_pic")
if not meta then if not meta then
return true, err return true, err
elseif not meta.format.duration then elseif not meta.format.duration then
return true, Err("Failed to get video duration") return true, Err("Failed to get video duration")
end end
local ss = math.floor(meta.format.duration * percent / 100) local pic = M.has_pic(meta)
local qv = 31 - math.floor(rt.preview.image_quality * 0.3) local percent = (pic and 0 or 5) + job.skip
if percent > 95 then
ya.mgr_emit("peek", { pic and 95 or 90, only_if = job.file.url, upper_bound = true })
return false
end
-- stylua: ignore -- stylua: ignore
local status, err = Command("ffmpeg"):args({ local cmd = Command("ffmpeg"):args({
"-v", "quiet", "-threads", 1, "-hwaccel", "auto", "-v", "quiet", "-threads", 1, "-hwaccel", "auto",
"-skip_frame", "nokey", "-ss", ss, "-skip_frame", "nokey",
"-an", "-sn", "-dn", "-an", "-sn", "-dn",
"-i", tostring(job.file.url), })
if percent ~= 0 then
cmd:args { "-ss", math.floor(meta.format.duration * percent / 100) }
end
cmd:args { "-i", tostring(job.file.url) }
if percent == 0 then
cmd:args { "-map", "disp:attached_pic" }
end
-- stylua: ignore
local status, err = cmd:args({
"-vframes", 1, "-vframes", 1,
"-q:v", qv, "-q:v", 31 - math.floor(rt.preview.image_quality * 0.3),
"-vf", string.format("scale='min(%d,iw)':'min(%d,ih)':force_original_aspect_ratio=decrease:flags=fast_bilinear", rt.preview.max_width, rt.preview.max_height), "-vf", string.format("scale='min(%d,iw)':'min(%d,ih)':force_original_aspect_ratio=decrease:flags=fast_bilinear", rt.preview.max_width, rt.preview.max_height),
"-f", "image2", "-f", "image2",
"-y", tostring(cache), "-y", tostring(cache),
@ -115,8 +125,12 @@ function M:spot_base(job)
end end
function M.list_meta(url, entries) function M.list_meta(url, entries)
local output, err = local cmd = Command("ffprobe"):args { "-v", "quiet" }
Command("ffprobe"):args({ "-v", "quiet", "-show_entries", entries, "-of", "json=c=1", tostring(url) }):output() if not entries:find("attached_pic", 1, true) then
cmd = cmd:args { "-select_streams", "v" }
end
local output, err = cmd:args({ "-show_entries", entries, "-of", "json=c=1", tostring(url) }):output()
if not output then if not output then
return nil, Err("Failed to start `ffprobe`, error: %s", err) return nil, Err("Failed to start `ffprobe`, error: %s", err)
end end
@ -133,4 +147,12 @@ function M.list_meta(url, entries)
return t return t
end end
function M.has_pic(meta)
for _, s in ipairs(meta.streams) do
if s.disposition and s.disposition.attached_pic == 1 then
return true
end
end
end
return M return M