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 return false
end end
-- stylua: ignore local cmd = Command("ffmpeg")
local cmd = Command("ffmpeg"):arg({ :stderr(Command.PIPED)
"-v", "quiet", "-threads", 1, "-hwaccel", "auto", :arg { "-v", "warning", "-hwaccel", "auto", "-threads", 1, "-an", "-sn", "-dn" }
"-skip_frame", "nokey",
"-an", "-sn", "-dn",
})
if percent ~= 0 then if percent ~= 0 then
cmd:arg { "-ss", math.floor(meta.format.duration * percent / 100) } cmd:arg { "-ss", math.floor(meta.format.duration * percent / 100) }
end end
cmd:arg { "-i", tostring(job.file.url) } cmd:arg { "-skip_frame", "nokey", "-i", tostring(job.file.url) }
if percent == 0 then if percent == 0 then
cmd:arg { "-map", "disp:attached_pic" } cmd:arg { "-map", "disp:attached_pic" }
end end
-- stylua: ignore -- stylua: ignore
local status, err = cmd:arg({ local output, err = cmd:arg({
"-vframes", 1, "-vframes", 1,
"-q:v", 31 - math.floor(rt.preview.image_quality * 0.3), "-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),
}):status() }):output()
if not status then if not output then
return true, Err("Failed to start `ffmpeg`, error: %s", err) return true, Err("Failed to start `ffmpeg`, error: %s", err)
elseif not status.success then elseif output.status.success then
return false, Err("`ffmpeg` exited with error code: %s", status.code)
else
return true 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
end end

View file

@ -1,6 +1,6 @@
use std::{any::TypeId, ffi::OsStr, io, process::Stdio}; 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 tokio::process::{ChildStderr, ChildStdin, ChildStdout};
use yazi_binding::Error; use yazi_binding::Error;
use yazi_shared::wtf8::FromWtf8; use yazi_shared::wtf8::FromWtf8;
@ -139,22 +139,21 @@ impl UserData for Command {
) )
} }
methods.add_function_mut("arg", |_, (ud, arg): (AnyUserData, Value)| { methods.add_function_mut("arg", |lua, (ud, arg): (AnyUserData, Value)| {
{ let mut me = ud.borrow_mut::<Self>()?;
let mut me = ud.borrow_mut::<Self>()?; match arg {
match arg { Value::Nil => return lua.create_sequence_from(me.inner.as_std().get_args())?.into_lua(lua),
Value::String(s) => { Value::String(s) => {
me.inner.arg(OsStr::from_wtf8(&s.as_bytes())?); 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()),
} }
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)| { methods.add_function_mut("cwd", |_, (ud, dir): (AnyUserData, mlua::String)| {
ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?.as_ref()); ud.borrow_mut::<Self>()?.inner.current_dir(dir.to_str()?.as_ref());