/** * Runs the ffmpeg program (ffmpeg.mjs, beside this file) for johnmcm.com's * /dav-to-mp4 and /dss-to-mp3, one conversion per message, each in a fresh * instance (ffmpeg's main() is not made to run twice). * * The input File is mounted read-only with WORKERFS, so it is read in place * in slices however large it is. The output is a device that hands what * ffmpeg writes straight out into Blob pieces (run.mjs), so a * multi-gigabyte MP4 never sits whole in WebAssembly memory. * * Messages in: { args: string[] (reading /in/, writing /out/), file: File, output: string, type: string } * Messages out: { type: 'log', line } while running, then { type: 'done', code, blob, size } or { type: 'error', message }. * * Written for johnmcm.com (2026); part of the module published at /source/ffmpeg/. */ import createFFmpeg from './ffmpeg.mjs'; import { run } from './run.mjs'; let compiled = null; function wasmModule() { compiled ??= WebAssembly.compileStreaming(fetch(new URL('./ffmpeg.wasm', import.meta.url))); return compiled; } self.onmessage = async (e) => { const { args, file, output, type } = e.data; try { const module = await wasmModule(); const ff = await createFFmpeg({ print: (line) => self.postMessage({ type: 'log', line }), printErr: (line) => self.postMessage({ type: 'log', line }), instantiateWasm(imports, done) { WebAssembly.instantiate(module, imports).then((instance) => done(instance)); return {}; }, }); const { code, blob, size } = run(ff, { args, name: file.name, file, output, type }); self.postMessage({ type: 'done', code, blob, size }); } catch (err) { self.postMessage({ type: 'error', message: String(err?.message || err) }); } };