feat: include stderr along with existing error code when video preview fails (#3383)

This commit is contained in:
三咲雅 misaki masa 2025-11-29 10:06:05 +08:00 committed by GitHub
parent 0b8aaba29b
commit 81ccdd8b64
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 28 deletions

View file

@ -52,36 +52,35 @@ function M:preload(job)
return false
end
-- stylua: ignore
local cmd = Command("ffmpeg"):arg({
"-v", "quiet", "-threads", 1, "-hwaccel", "auto",
"-skip_frame", "nokey",
"-an", "-sn", "-dn",
})
local cmd = Command("ffmpeg")
:stderr(Command.PIPED)
:arg { "-v", "warning", "-hwaccel", "auto", "-threads", 1, "-an", "-sn", "-dn" }
if percent ~= 0 then
cmd:arg { "-ss", math.floor(meta.format.duration * percent / 100) }
end
cmd:arg { "-i", tostring(job.file.url) }
cmd:arg { "-skip_frame", "nokey", "-i", tostring(job.file.url) }
if percent == 0 then
cmd:arg { "-map", "disp:attached_pic" }
end
-- stylua: ignore
local status, err = cmd:arg({
local output, err = cmd:arg({
"-vframes", 1,
"-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),
"-f", "image2",
"-y", tostring(cache),
}):status()
}):output()
if not status then
if not output then
return true, Err("Failed to start `ffmpeg`, error: %s", err)
elseif not status.success then
return false, Err("`ffmpeg` exited with error code: %s", status.code)
else
elseif output.status.success then
return true
elseif output.stderr:find("No filtered frames for output stream", 1, true) then
return true, Err("No more keyframes available")
else
return false, Err("`ffmpeg` exited with error code %s: %s", output.status.code, output.stderr)
end
end

View file

@ -1,6 +1,6 @@
use std::{any::TypeId, ffi::OsStr, io, process::Stdio};
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, MetaMethod, Table, UserData, Value};
use mlua::{AnyUserData, ExternalError, IntoLua, IntoLuaMulti, Lua, MetaMethod, Table, UserData, Value};
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
use yazi_binding::Error;
use yazi_shared::wtf8::FromWtf8;
@ -139,22 +139,21 @@ impl UserData for Command {
)
}
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, Value)| {
{
let mut me = ud.borrow_mut::<Self>()?;
match arg {
Value::String(s) => {
me.inner.arg(OsStr::from_wtf8(&s.as_bytes())?);
}
Value::Table(t) => {
for s in t.sequence_values::<mlua::String>() {
me.inner.arg(OsStr::from_wtf8(&s?.as_bytes())?);
}
}
_ => return Err("arg must be a string or table of strings".into_lua_err()),
methods.add_function_mut("arg", |lua, (ud, arg): (AnyUserData, Value)| {
let mut me = ud.borrow_mut::<Self>()?;
match arg {
Value::Nil => return lua.create_sequence_from(me.inner.as_std().get_args())?.into_lua(lua),
Value::String(s) => {
me.inner.arg(OsStr::from_wtf8(&s.as_bytes())?);
}
Value::Table(t) => {
for s in t.sequence_values::<mlua::String>() {
me.inner.arg(OsStr::from_wtf8(&s?.as_bytes())?);
}
}
_ => Err("arg must be a string or table of strings".into_lua_err())?,
}
Ok(ud)
ud.into_lua(lua)
});
methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?.as_ref());