oak-task: verify a hardware encoder actually works before using it
`ffmpeg -encoders` lists every compiled-in encoder — a full Windows
build advertises h264_nvenc/qsv/amf even when the machine has none of
that hardware — so probe_hw_encoder picked NVENC on the GPU-less Windows
runner and the proxy transcode failed ('Cannot load libcuda.so.1',
caught by engine_proxy_generate_and_delete now that the Windows package
ships an ffmpeg CLI). Probe a one-frame null encode per candidate and
fall through to the next, finally to libx264.
Reproduced locally with a full ffmpeg build: h264_nvenc exits 255
without the driver, libx264 succeeds.
This commit is contained in:
@@ -234,13 +234,44 @@ impl ProxyTask {
|
||||
]
|
||||
};
|
||||
for (name, enc) in preference {
|
||||
if has(name) {
|
||||
// `-encoders` lists every compiled-in encoder — a full build
|
||||
// advertises h264_nvenc/qsv/amf even on machines without the
|
||||
// matching hardware — so a one-frame null encode decides
|
||||
// whether the candidate can actually initialize. Failures fall
|
||||
// through to the next candidate and finally to software (the
|
||||
// old list-only check made proxy generation fail outright on
|
||||
// GPU-less Windows machines with such a build).
|
||||
if has(name) && Self::encoder_usable(ffmpeg_path, name) {
|
||||
return *enc;
|
||||
}
|
||||
}
|
||||
HwEncoder::Software
|
||||
}
|
||||
|
||||
/// Whether `encoder` can initialize and encode one tiny frame; see the
|
||||
/// caller for why the `-encoders` list is not enough.
|
||||
fn encoder_usable(ffmpeg_path: &str, encoder: &str) -> bool {
|
||||
let out = Command::new(ffmpeg_path)
|
||||
.args([
|
||||
"-hide_banner",
|
||||
"-loglevel",
|
||||
"error",
|
||||
"-f",
|
||||
"lavfi",
|
||||
"-i",
|
||||
"color=size=64x64:rate=1:duration=1",
|
||||
"-frames:v",
|
||||
"1",
|
||||
"-c:v",
|
||||
encoder,
|
||||
"-f",
|
||||
"null",
|
||||
"-",
|
||||
])
|
||||
.output();
|
||||
matches!(out, Ok(out) if out.status.success())
|
||||
}
|
||||
|
||||
/// libx264 预设名 → NVENC p1..p7(NVENC 预设是编号)。
|
||||
fn nvenc_preset(preset: &str) -> &'static str {
|
||||
match preset {
|
||||
|
||||
Reference in New Issue
Block a user