feat: support embedded cover for video preview (#2640)

This commit is contained in:
三咲雅 · Misaki Masa 2025-04-19 23:13:11 +08:00 committed by GitHub
parent ce23dcd81b
commit 88bbbac7dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

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