From 8ae80804262cc7cb4679ed9eaa5218167c7cff1a Mon Sep 17 00:00:00 2001 From: JakeBreath Date: Thu, 17 Sep 2026 21:13:49 -0500 Subject: [PATCH] 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. --- .../src/features/optimize/OptimizeModal.tsx | 32 +++++++++++++++---- frontend/src/features/optimize/detect.ts | 20 ++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/frontend/src/features/optimize/OptimizeModal.tsx b/frontend/src/features/optimize/OptimizeModal.tsx index f4c284b..e2f2ebb 100644 --- a/frontend/src/features/optimize/OptimizeModal.tsx +++ b/frontend/src/features/optimize/OptimizeModal.tsx @@ -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…

) : usableCodecs.length === 0 ? ( -

- This browser cannot produce {container.toUpperCase()} video - samples — switch the container to{" "} - {container === "mp4" ? "WebM" : "MP4"}. -

+
+

+ {browserLabel()} cannot produce{" "} + {container.toUpperCase()} video samples + {container === "mp4" && isFirefox + ? " — Firefox does not implement H.264/HEVC encoding" + : ""} + . +

+ +
) : (

- Encoders:{" "} + {browserLabel()} · encoders:{" "} {probes .map( (probe) => diff --git a/frontend/src/features/optimize/detect.ts b/frontend/src/features/optimize/detect.ts index 1844c17..dbdc0e8 100644 --- a/frontend/src/features/optimize/detect.ts +++ b/frontend/src/features/optimize/detect.ts @@ -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"; +}