Write video output to a real OPFS file instead of assembling chunks

The hand-rolled chunk assembly was verified correct in Node but still
produced a broken MP4 in the browser, so stop relying on it: the muxer now
streams into an Origin Private File System file (random access is exactly
what MP4 needs), the worker returns the OPFS File directly, and the entry
is deleted after a successful apply (stale ones are purged hourly). The
chunk collector remains only as a fallback for browsers without OPFS.

The result is validated before it reaches the UI: MP4s must contain a
moov box and WebM files must start with the EBML magic, so a broken muxer
output surfaces as an error instead of a 0x0 preview.
This commit is contained in:
2026-09-17 20:58:26 -05:00
parent 9162cf23ce
commit bd812bb601
7 changed files with 181 additions and 16 deletions
@@ -9,6 +9,7 @@ import { formatBytes } from "@/lib/format";
import type { MediaItem } from "@/lib/types";
import { detectVideoCodecs } from "./detect";
import { deleteStoredFile } from "./opfs";
import {
DEFAULT_OPTIONS,
kindForExtension,
@@ -220,6 +221,7 @@ export function OptimizeModal({
}
},
onSuccess: () => {
if (result?.storageKey) void deleteStoredFile(result.storageKey);
setApplied(true);
setApplyError(null);
void queryClient.invalidateQueries({ queryKey: ["file", item.j_id] });
@@ -250,6 +252,7 @@ export function OptimizeModal({
function process() {
setApplied(false);
setApplyError(null);
if (result?.storageKey) void deleteStoredFile(result.storageKey);
setResultInfo(null);
run({
url: item.raw_url,
@@ -259,6 +262,11 @@ export function OptimizeModal({
});
}
function resetRun() {
if (result?.storageKey) void deleteStoredFile(result.storageKey);
reset();
}
return (
<div
className="fixed inset-0 z-[70] flex items-start justify-center overflow-y-auto bg-ctp-crust/70 px-4 py-8 backdrop-blur-sm"
@@ -645,7 +653,7 @@ export function OptimizeModal({
<div className="flex flex-wrap items-center gap-2">
<Button
variant="ghost"
onClick={reset}
onClick={resetRun}
disabled={status === "running" || (!result && !error)}
>
Reset