worker.js 4.5 KB

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