fix(cli): render names the FFmpeg that has no libx264 and how to point at another (#6819)

This commit is contained in:
Miguel Ángel
2026-10-30 10:52:46 +00:00
committed by GitHub
parent 054592c4de
commit 315969cda0
3 changed files with 16 additions and 5 deletions
+4
View File
@@ -121,6 +121,10 @@ describe("resolveH264EncoderMode", () => {
).rejects.toThrow(H264EncoderUnavailableError);
expect(probeGpu).toHaveBeenCalledOnce();
await expect(
detectH264EncoderModeForRender("/custom/ffmpeg", true, signal, probeGpu),
).rejects.toThrow("/custom/ffmpeg has no libx264");
mockRun.mockResolvedValue({ stdout: " V....D h264_nvenc H.264\n" } as never);
expect(await detectH264EncoderModeForRender("/custom/ffmpeg", true, signal)).toBe("gpu");
expect(gpuProbes.shared).toHaveBeenCalledOnce();
+10 -4
View File
@@ -8,8 +8,13 @@ export { FFMPEG_PATH_ENV, FFPROBE_PATH_ENV } from "@hyperframes/parsers/ff-binar
export type H264EncoderMode = "software" | "gpu";
export class H264EncoderUnavailableError extends Error {
constructor(readonly hevcEncoderAvailable = false) {
super("This FFmpeg build has no libx264 and no GPU H.264 encoder that works on this machine.");
constructor(
readonly hevcEncoderAvailable = false,
ffmpegPath?: string,
) {
super(
`${ffmpegPath ?? "This FFmpeg build"} has no libx264 and no GPU H.264 encoder that works on this machine.`,
);
this.name = "H264EncoderUnavailableError";
}
}
@@ -25,11 +30,12 @@ export function resolveH264EncoderMode(
ffmpegEncodersOutput: string,
gpuRequested: boolean,
usableGpu: boolean,
ffmpegPath?: string,
): H264EncoderMode {
if (gpuRequested && usableGpu) return "gpu";
if (hasLibx264(ffmpegEncodersOutput)) return "software";
if (usableGpu) return "gpu";
throw new H264EncoderUnavailableError(/\blibx265\b/.test(ffmpegEncodersOutput));
throw new H264EncoderUnavailableError(/\blibx265\b/.test(ffmpegEncodersOutput), ffmpegPath);
}
function hasLibx264(ffmpegEncodersOutput: string): boolean {
@@ -48,7 +54,7 @@ export async function detectH264EncoderModeForRender(
});
const needsGpu = gpuRequested || !hasLibx264(result.stdout);
const usableGpu = needsGpu && (await probeGpu()) !== null;
return resolveH264EncoderMode(result.stdout, gpuRequested, usableGpu);
return resolveH264EncoderMode(result.stdout, gpuRequested, usableGpu, ffmpegPath);
}
// `configuredMustExist`: the CLI surfaces an install hint when a binary is
+2 -1
View File
@@ -122,6 +122,7 @@ import {
import { runEnvironmentChecks } from "../browser/preflight.js";
import {
detectH264EncoderModeForRender,
FFMPEG_PATH_ENV,
getFFmpegInstallHint,
H264EncoderUnavailableError,
type H264EncoderMode,
@@ -1061,7 +1062,7 @@ async function executeLocalRender(
errorBox(
`${isHls ? "HLS" : "MP4"} H.264 encoder unavailable`,
error.message,
`Install an FFmpeg build with libx264 support (${getFFmpegInstallHint()})` +
`Install an FFmpeg build with libx264 support (${getFFmpegInstallHint()}), or point ${FFMPEG_PATH_ENV} at one` +
(isHls
? "."
: ", or render WebM instead: hyperframes render --format webm --output output.webm"),