Commit Graph
3 Commits
Author SHA1 Message Date
JakeBreath e7657a3dd0 Fix the OPFS output lifecycle (locked stream on close)
StreamTarget closes the underlying writer when the output is finalized —
that is also what commits an OPFS file — so closing it ourselves threw
"Can not close locked stream". finalize() now simply reads the committed
file back, and every failure path (invalid attempt, encode error,
validation failure) aborts the write and deletes the temporary entry.
2026-09-17 21:01:15 -05:00
JakeBreath bd812bb601 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.
2026-09-17 20:58:26 -05:00
JakeBreath 9162cf23ce Fix the streaming assembler duplicating overlapped bytes
When the muxer patched a byte range inside an already-written chunk (the
mdat header, for example), the merge trimmed the right side of the old
segment but left its full blob on the left, duplicating megabytes and
shifting every box offset — the MP4 still reported its duration but had
no usable video track (0x0 in the browser, "moov atom not found" in
ffprobe).

The collector/assembler now lives in its own module and was verified in
Node with a real transmux of J-81: the assembled file matches the source
(h264 1280x720, 500 frames, AAC, 20.84 s) byte for byte in structure.
2026-09-17 20:50:08 -05:00