Probe real encoder output, order codecs by it, and add a quality slider

Your machine's H.264/HEVC encoders report support and then emit no video
samples at all, which no configure-time check can see. The optimizer now
test-encodes three frames per codec (cached for 30 days), shows the result
as diagnostics in the modal (AVC x / VP9 (hardware) / ...), feeds the
working codecs to the worker so Auto tries them first, and tells you to
switch to WebM when a container has no usable encoder.

Video quality is now a 10-100 slider with a predicted bitrate and size
for this clip (mirroring Mediabunny's mapping), which makes the trade-off
visible instead of guessing from presets.
This commit is contained in:
2026-09-17 21:11:46 -05:00
parent 33ae790bd0
commit 01b9a6181a
6 changed files with 294 additions and 86 deletions
@@ -8,25 +8,17 @@ import { cn } from "@/lib/cn";
import { formatBytes } from "@/lib/format";
import type { MediaItem } from "@/lib/types";
import { detectVideoCodecs } from "./detect";
import { estimateVideoBitrate, VIDEO_CODEC_CANDIDATES } from "./bitrate";
import { probeVideoEncoders, workingCodecs } from "./detect";
import { deleteStoredFile } from "./opfs";
import {
DEFAULT_OPTIONS,
kindForExtension,
type OptimizeKind,
type OptimizeOptions,
type VideoQualityLevel,
} from "./types";
import { useOptimizer } from "./useOptimizer";
const QUALITY_LEVELS: { value: VideoQualityLevel; label: string }[] = [
{ value: "very-high", label: "Visually lossless" },
{ value: "high", label: "High (recommended)" },
{ value: "medium", label: "Balanced" },
{ value: "low", label: "Small" },
{ value: "very-low", label: "Smallest" },
];
const DIMENSION_CHOICES: { value: number | null; label: string }[] = [
{ value: null, label: "Keep original" },
{ value: 2560, label: "Max 2560 px" },
@@ -190,12 +182,20 @@ export function OptimizeModal({
const [resultInfo, setResultInfo] = useState<MediaInfo | null>(null);
const codecQuery = useQuery({
queryKey: ["optimize-codecs"],
queryFn: detectVideoCodecs,
queryKey: ["optimize-encoders"],
queryFn: () => probeVideoEncoders(),
enabled: kind === "video",
staleTime: Infinity,
retry: 0,
});
const probes = codecQuery.data ?? [];
const container: "mp4" | "webm" =
options.container === "keep"
? item.extension === "webm"
? "webm"
: "mp4"
: options.container;
const usableCodecs = workingCodecs(probes, container);
const applyMutation = useMutation({
mutationFn: async () => {
@@ -240,15 +240,45 @@ export function OptimizeModal({
: null;
const isVideo = kind === "video";
const hardwareAvailable =
codecQuery.data?.some((entry) => entry.supported && entry.hardware) ??
false;
const truncated =
isVideo &&
originalInfo?.duration != null &&
resultInfo?.duration != null &&
resultInfo.duration + 1 < originalInfo.duration;
// Predicted output size, mirroring Mediabunny's quality -> bitrate mapping.
const estimateCodec =
options.codec !== "auto"
? options.codec
: (usableCodecs[0] ?? VIDEO_CODEC_CANDIDATES[container][0]);
const estimate =
isVideo &&
originalInfo?.duration &&
originalInfo.width &&
originalInfo.height
? (() => {
const sourceHeight = originalInfo.height as number;
const sourceWidth = originalInfo.width as number;
const targetHeight =
options.height && options.height < sourceHeight
? options.height
: sourceHeight;
const targetWidth = Math.round(
sourceWidth * (targetHeight / sourceHeight),
);
const bitrate = estimateVideoBitrate(
estimateCodec,
targetWidth,
targetHeight,
options.quality,
);
return {
bitrate,
size: ((bitrate + 128_000) / 8) * (originalInfo.duration as number),
};
})()
: null;
function process() {
setApplied(false);
setApplyError(null);
@@ -259,6 +289,7 @@ export function OptimizeModal({
filename: item.filename,
kind,
options,
preferredCodecs: usableCodecs,
});
}
@@ -531,24 +562,28 @@ export function OptimizeModal({
{kind === "video" ? (
<>
<Field label="Quality">
<select
className={inputClass}
value={options.qualityLevel}
<Field label={`Quality — ${options.quality}`}>
<input
type="range"
min={10}
max={100}
value={options.quality}
onChange={(event) =>
setOptions((current) => ({
...current,
qualityLevel: event.target.value as VideoQualityLevel,
quality: Number(event.target.value),
}))
}
>
{QUALITY_LEVELS.map((level) => (
<option key={level.value} value={level.value}>
{level.label}
</option>
))}
</select>
className="w-full accent-ctp-mauve"
/>
</Field>
{estimate ? (
<p className="-mt-2 text-[11px] text-ctp-overlay0">
≈ {(estimate.bitrate / 1_000_000).toFixed(1)} Mbps · about{" "}
{formatBytes(estimate.size)} for{" "}
{originalInfo?.duration?.toFixed(1)} s
</p>
) : null}
<Field label="Resolution">
<select
className={inputClass}
@@ -584,14 +619,15 @@ export function OptimizeModal({
}
>
<option value="auto">Auto (best available)</option>
{(codecQuery.data ?? [])
.filter((entry) => entry.supported)
.map((entry) => (
<option key={entry.codec} value={entry.codec}>
{entry.codec.toUpperCase()}
{entry.hardware ? " (hardware)" : ""}
{usableCodecs.map((codec) => {
const probe = probes.find((entry) => entry.codec === codec);
return (
<option key={codec} value={codec}>
{codec.toUpperCase()}
{probe?.hardware ? " (hardware)" : ""}
</option>
))}
);
})}
</select>
</Field>
<Field label="Container">
@@ -625,13 +661,34 @@ export function OptimizeModal({
/>
Prefer hardware encoding
</label>
<p className="text-[11px] leading-relaxed text-ctp-overlay0">
{codecQuery.isPending
? "Checking the encoders this browser offers…"
: hardwareAvailable
? "Hardware-accelerated encoders are available on this machine."
: "No hardware encoder detected — encoding will use the CPU."}
</p>
{codecQuery.isPending ? (
<p className="text-[11px] leading-relaxed text-ctp-overlay0">
Test-encoding a few frames to see which encoders really
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"}.
</p>
) : (
<p className="text-[11px] leading-relaxed text-ctp-overlay0">
Encoders:{" "}
{probes
.map(
(probe) =>
`${probe.codec.toUpperCase()}${
probe.supported && probe.works
? probe.hardware
? " (hardware)"
: " ✓"
: " ✗"
}`,
)
.join(" · ")}
</p>
)}
</>
) : null}