Name the browser in the encoder diagnostics and offer a container switch

The optimizer now shows which browser is running (e.g. "Firefox 141")
next to the encoder probe results, explains the common Firefox case
("Firefox does not implement H.264/HEVC encoding"), and offers a
one-click switch to the container that has working encoders.
This commit is contained in:
2026-09-17 21:13:49 -05:00
parent 01b9a6181a
commit 8ae8080426
2 changed files with 45 additions and 7 deletions
@@ -9,7 +9,7 @@ import { formatBytes } from "@/lib/format";
import type { MediaItem } from "@/lib/types";
import { estimateVideoBitrate, VIDEO_CODEC_CANDIDATES } from "./bitrate";
import { probeVideoEncoders, workingCodecs } from "./detect";
import { browserLabel, probeVideoEncoders, workingCodecs } from "./detect";
import { deleteStoredFile } from "./opfs";
import {
DEFAULT_OPTIONS,
@@ -196,6 +196,7 @@ export function OptimizeModal({
: "mp4"
: options.container;
const usableCodecs = workingCodecs(probes, container);
const isFirefox = browserLabel().startsWith("Firefox");
const applyMutation = useMutation({
mutationFn: async () => {
@@ -667,14 +668,31 @@ export function OptimizeModal({
work here…
</p>
) : usableCodecs.length === 0 ? (
<p className="rounded-md border border-ctp-red/40 bg-ctp-red/10 px-2 py-1.5 text-[11px] leading-relaxed text-ctp-red">
This browser cannot produce {container.toUpperCase()} video
samples — switch the container to{" "}
{container === "mp4" ? "WebM" : "MP4"}.
<div className="rounded-md border border-ctp-red/40 bg-ctp-red/10 px-2 py-1.5 text-[11px] leading-relaxed text-ctp-red">
<p>
{browserLabel()} cannot produce{" "}
{container.toUpperCase()} video samples
{container === "mp4" && isFirefox
? " — Firefox does not implement H.264/HEVC encoding"
: ""}
.
</p>
<button
type="button"
onClick={() =>
setOptions((current) => ({
...current,
container: container === "mp4" ? "webm" : "mp4",
}))
}
className="mt-1 font-medium text-ctp-blue underline"
>
Switch to {container === "mp4" ? "WebM" : "MP4"}
</button>
</div>
) : (
<p className="text-[11px] leading-relaxed text-ctp-overlay0">
Encoders:{" "}
{browserLabel()} · encoders:{" "}
{probes
.map(
(probe) =>
+20
View File
@@ -137,3 +137,23 @@ export function workingCodecs(
.map((probe) => probe.codec)
.filter((codec) => candidates.includes(codec));
}
/** Human-readable browser + platform, for the encoder diagnostics line. */
export function browserLabel(): string {
const ua = navigator.userAgent;
const patterns: [RegExp, string][] = [
[/(Firefox|FxiOS)\/([\d.]+)/, "Firefox"],
[/(Edg|EdgA|EdgiOS)\/([\d.]+)/, "Edge"],
[/(OPR)\/([\d.]+)/, "Opera"],
[/(Chrome|CriOS)\/([\d.]+)/, "Chrome"],
[/(Version)\/([\d.]+)[^)]*Safari/, "Safari"],
];
for (const [pattern, name] of patterns) {
const match = pattern.exec(ua);
if (match) {
const version = match[2]?.split(".")[0] ?? "";
return `${name}${version ? ` ${version}` : ""}`;
}
}
return "unknown browser";
}