File size: 5,085 Bytes
e19951b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="webworker" />
import { CORE_URL, FFMessageType } from "./const.js";
import { ERROR_UNKNOWN_MESSAGE_TYPE, ERROR_NOT_LOADED, ERROR_IMPORT_FAILURE, } from "./errors.js";
let ffmpeg;
const load = async ({ coreURL: _coreURL, wasmURL: _wasmURL, workerURL: _workerURL, }) => {
const first = !ffmpeg;
try {
if (!_coreURL)
_coreURL = CORE_URL;
// when web worker type is `classic`.
importScripts(_coreURL);
}
catch {
if (!_coreURL || _coreURL === CORE_URL)
_coreURL = CORE_URL.replace('/umd/', '/esm/');
// when web worker type is `module`.
self.createFFmpegCore = (await import(
/* @vite-ignore */ _coreURL)).default;
if (!self.createFFmpegCore) {
throw ERROR_IMPORT_FAILURE;
}
}
const coreURL = _coreURL;
const wasmURL = _wasmURL ? _wasmURL : _coreURL.replace(/.js$/g, ".wasm");
const workerURL = _workerURL
? _workerURL
: _coreURL.replace(/.js$/g, ".worker.js");
ffmpeg = await self.createFFmpegCore({
// Fix `Overload resolution failed.` when using multi-threaded ffmpeg-core.
// Encoded wasmURL and workerURL in the URL as a hack to fix locateFile issue.
mainScriptUrlOrBlob: `${coreURL}#${btoa(JSON.stringify({ wasmURL, workerURL }))}`,
});
ffmpeg.setLogger((data) => self.postMessage({ type: FFMessageType.LOG, data }));
ffmpeg.setProgress((data) => self.postMessage({
type: FFMessageType.PROGRESS,
data,
}));
return first;
};
const exec = ({ args, timeout = -1 }) => {
ffmpeg.setTimeout(timeout);
ffmpeg.exec(...args);
const ret = ffmpeg.ret;
ffmpeg.reset();
return ret;
};
const ffprobe = ({ args, timeout = -1 }) => {
ffmpeg.setTimeout(timeout);
ffmpeg.ffprobe(...args);
const ret = ffmpeg.ret;
ffmpeg.reset();
return ret;
};
const writeFile = ({ path, data }) => {
ffmpeg.FS.writeFile(path, data);
return true;
};
const readFile = ({ path, encoding }) => ffmpeg.FS.readFile(path, { encoding });
// TODO: check if deletion works.
const deleteFile = ({ path }) => {
ffmpeg.FS.unlink(path);
return true;
};
const rename = ({ oldPath, newPath }) => {
ffmpeg.FS.rename(oldPath, newPath);
return true;
};
// TODO: check if creation works.
const createDir = ({ path }) => {
ffmpeg.FS.mkdir(path);
return true;
};
const listDir = ({ path }) => {
const names = ffmpeg.FS.readdir(path);
const nodes = [];
for (const name of names) {
const stat = ffmpeg.FS.stat(`${path}/${name}`);
const isDir = ffmpeg.FS.isDir(stat.mode);
nodes.push({ name, isDir });
}
return nodes;
};
// TODO: check if deletion works.
const deleteDir = ({ path }) => {
ffmpeg.FS.rmdir(path);
return true;
};
const mount = ({ fsType, options, mountPoint }) => {
const str = fsType;
const fs = ffmpeg.FS.filesystems[str];
if (!fs)
return false;
ffmpeg.FS.mount(fs, options, mountPoint);
return true;
};
const unmount = ({ mountPoint }) => {
ffmpeg.FS.unmount(mountPoint);
return true;
};
self.onmessage = async ({ data: { id, type, data: _data }, }) => {
const trans = [];
let data;
try {
if (type !== FFMessageType.LOAD && !ffmpeg)
throw ERROR_NOT_LOADED; // eslint-disable-line
switch (type) {
case FFMessageType.LOAD:
data = await load(_data);
break;
case FFMessageType.EXEC:
data = exec(_data);
break;
case FFMessageType.FFPROBE:
data = ffprobe(_data);
break;
case FFMessageType.WRITE_FILE:
data = writeFile(_data);
break;
case FFMessageType.READ_FILE:
data = readFile(_data);
break;
case FFMessageType.DELETE_FILE:
data = deleteFile(_data);
break;
case FFMessageType.RENAME:
data = rename(_data);
break;
case FFMessageType.CREATE_DIR:
data = createDir(_data);
break;
case FFMessageType.LIST_DIR:
data = listDir(_data);
break;
case FFMessageType.DELETE_DIR:
data = deleteDir(_data);
break;
case FFMessageType.MOUNT:
data = mount(_data);
break;
case FFMessageType.UNMOUNT:
data = unmount(_data);
break;
default:
throw ERROR_UNKNOWN_MESSAGE_TYPE;
}
}
catch (e) {
self.postMessage({
id,
type: FFMessageType.ERROR,
data: e.toString(),
});
return;
}
if (data instanceof Uint8Array) {
trans.push(data.buffer);
}
self.postMessage({ id, type, data }, trans);
};
|