diff --git a/package-lock.json b/package-lock.json index a6f9684..4db8a4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2034,9 +2034,9 @@ } }, "@ffmpeg/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.6.0.tgz", - "integrity": "sha512-5VNyabaCPZJEFmn92C5SIh2vFChL2l9OVGut1hmst8IPuChZahF6yniFjEdF2Ri8ZZFKXTAQrPh3WfpVaEPK9A==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.7.0.tgz", + "integrity": "sha512-ulDKwckLF4NrNIn98sYe8KCzKM9GfIfc9kR2Mel4pA8URQ9GEr2tGDMST5xW63Usnr6ybZCZKgwiDkAHK7VWCQ==" }, "@hapi/address": { "version": "2.1.2", diff --git a/package.json b/package.json index 745aece..c05d929 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,13 @@ "wait": "rimraf dist && wait-on http://localhost:3000/dist/ffmpeg.dev.js", "test": "npm-run-all -p -r start test:all", "test:all": "npm-run-all wait test:browser:ffmpeg test:node:all", - "test:node": "NODE_OPTIONS=--experimental-worker nyc mocha --exit --bail --require ./scripts/test-helper.js", + "test:node": "node --experimental-wasm-threads --experimental-wasm-bulk-memory node_modules/.bin/_mocha --exit --bail --require ./scripts/test-helper.js", "test:node:all": "npm run test:node -- ./tests/*.test.js", - "test:browser": "mocha-headless-chrome -a incognito -a no-sandbox -a disable-setuid-sandbox -a disable-logging -t 300000", + "test:browser": "mocha-headless-chrome -a allow-file-access-from-files -a incognito -a no-sandbox -a disable-setuid-sandbox -a disable-logging -t 300000", "test:browser:ffmpeg": "npm run test:browser -- -f ./tests/ffmpeg.test.html" }, "browser": { - "./src/worker/node/index.js": "./src/worker/browser/index.js" + "./src/node/index.js": "./src/browser/index.js" }, "repository": { "type": "git", @@ -37,11 +37,11 @@ "url": "https://github.com/ffmpegjs/ffmpeg.js/issues" }, "engines": { - "node": ">=10.5.0" + "node": ">=12.16.1" }, "homepage": "https://github.com/ffmpegjs/ffmpeg.js#readme", "dependencies": { - "@ffmpeg/core": "^0.6.0", + "@ffmpeg/core": "^0.7.0", "idb": "^4.0.5", "is-electron": "^2.2.0", "is-url": "^1.2.4", diff --git a/scripts/webpack.config.dev.js b/scripts/webpack.config.dev.js index 25299a7..cbe7469 100644 --- a/scripts/webpack.config.dev.js +++ b/scripts/webpack.config.dev.js @@ -32,8 +32,4 @@ module.exports = [ library: 'FFmpeg', libraryTarget: 'umd', }), - genConfig({ - entry: path.resolve(__dirname, '..', 'src', 'worker-script', 'browser', 'index.js'), - filename: 'worker.dev.js', - }), ]; diff --git a/scripts/webpack.config.prod.js b/scripts/webpack.config.prod.js index 74ef83d..8f1bac3 100644 --- a/scripts/webpack.config.prod.js +++ b/scripts/webpack.config.prod.js @@ -23,8 +23,4 @@ module.exports = [ library: 'FFmpeg', libraryTarget: 'umd', }), - genConfig({ - entry: path.resolve(__dirname, '..', 'src', 'worker-script', 'browser', 'index.js'), - filename: 'worker.min.js', - }), ]; diff --git a/src/browser/defaultOptions.js b/src/browser/defaultOptions.js new file mode 100644 index 0000000..1d9db84 --- /dev/null +++ b/src/browser/defaultOptions.js @@ -0,0 +1,13 @@ +const resolveURL = require('resolve-url'); +const { dependencies } = require('../../package.json'); +const defaultOptions = require('../constants/defaultOptions'); + +/* + * Default options for browser worker + */ +module.exports = { + ...defaultOptions, + corePath: (typeof process !== 'undefined' && process.env.FFMPEG_ENV === 'development') + ? resolveURL('/node_modules/@ffmpeg/core/ffmpeg-core.js') + : `https://unpkg.com/@ffmpeg/core@v${dependencies['@ffmpeg/core'].substring(1)}/ffmpeg-core.js`, +}; diff --git a/src/worker/browser/fetchFile.js b/src/browser/fetchFile.js similarity index 100% rename from src/worker/browser/fetchFile.js rename to src/browser/fetchFile.js diff --git a/src/browser/getModule.js b/src/browser/getModule.js new file mode 100644 index 0000000..7a87c6c --- /dev/null +++ b/src/browser/getModule.js @@ -0,0 +1,23 @@ +const { log } = require('../utils/log'); + +module.exports = ({ corePath }) => new Promise((resolve) => { + if (typeof window.Module === 'undefined') { + log('info', `download ffmpeg-core script (~25 MB) from ${corePath}`); + const script = document.createElement('script'); + const eventHandler = () => { + script.removeEventListener('load', eventHandler); + log('info', 'initialize ffmpeg-core'); + window.Module.onRuntimeInitialized = () => { + log('info', 'ffmpeg-core initialized'); + resolve(window.Module); + }; + }; + script.src = corePath; + script.type = 'text/javascript'; + script.addEventListener('load', eventHandler); + document.getElementsByTagName('head')[0].appendChild(script); + } else { + log('info', 'ffmpeg-core is loaded already'); + resolve(window.Module); + } +}); diff --git a/src/worker/node/index.js b/src/browser/index.js similarity index 56% rename from src/worker/node/index.js rename to src/browser/index.js index 997cb10..85ade1f 100644 --- a/src/worker/node/index.js +++ b/src/browser/index.js @@ -1,11 +1,9 @@ const defaultOptions = require('./defaultOptions'); -const spawnWorker = require('./spawnWorker'); -const onMessage = require('./onMessage'); +const getModule = require('./getModule'); const fetchFile = require('./fetchFile'); module.exports = { defaultOptions, - spawnWorker, - onMessage, + getModule, fetchFile, }; diff --git a/src/worker-script/constants/defaultArgs.js b/src/constants/defaultArgs.js similarity index 72% rename from src/worker-script/constants/defaultArgs.js rename to src/constants/defaultArgs.js index 55aae4f..196b8e0 100755 --- a/src/worker-script/constants/defaultArgs.js +++ b/src/constants/defaultArgs.js @@ -1,4 +1,5 @@ module.exports = [ './ffmpeg', // args[0] is always binary path '-nostdin', // Disable interaction mode + '-hide_banner', // Not to output banner ]; diff --git a/src/constants/defaultOptions.js b/src/constants/defaultOptions.js index 6955b45..f1732fe 100644 --- a/src/constants/defaultOptions.js +++ b/src/constants/defaultOptions.js @@ -1,4 +1,5 @@ module.exports = { + log: false, logger: () => {}, progress: () => {}, }; diff --git a/src/createFFmpeg.js b/src/createFFmpeg.js new file mode 100644 index 0000000..35f0b80 --- /dev/null +++ b/src/createFFmpeg.js @@ -0,0 +1,130 @@ +const defaultArgs = require('./constants/defaultArgs'); +const { setLogging, log } = require('./utils/log'); +const resolvePaths = require('./utils/resolvePaths'); +const parseProgress = require('./utils/parseProgress'); +const stringList2pointer = require('./utils/stringList2pointer'); +const { + defaultOptions, + getModule, + fetchFile, +} = require('./node'); + +const NO_LOAD = Error('FFmpeg.js is not ready, make sure you have completed load().'); +const NO_MULTIPLE_RUN = Error('FFmpeg.js can only run one command at a time'); +let Module = null; +let ffmpeg = null; + +module.exports = (_options = {}) => { + let runResolve = null; + let running = false; + const { + log: logging, + logger, + progress, + ...options + } = resolvePaths({ + ...defaultOptions, + ..._options, + }); + const detectCompletion = ({ message, type }) => { + if (type === 'ffmpeg-stdout' + && message === 'FFMPEG_END' + && runResolve !== null) { + runResolve(); + runResolve = null; + running = false; + } + }; + + setLogging(logging); + + const load = async () => { + if (Module === null) { + log('info', 'load ffmpeg-core'); + Module = await getModule(options); + Module.setLogger((_log) => { + detectCompletion(_log); + parseProgress(_log, progress); + logger(_log); + log(_log.type, _log.message); + }); + if (ffmpeg === null) { + ffmpeg = Module.cwrap('proxy_main', 'number', ['number', 'number']); + } + log('info', 'ffmpeg-core loaded'); + } + }; + + const FS = (method, args) => { + if (Module === null) { + throw NO_LOAD; + } else { + log('info', `FS.${method} ${args[0]}`); + return Module.FS[method](...args); + } + }; + + const write = async (path, data) => ( + FS('writeFile', [path, await fetchFile(data)]) + ); + + const writeText = (path, text) => ( + FS('writeFile', [path, text]) + ); + + const read = (path) => ( + FS('readFile', [path]) + ); + + const remove = (path) => ( + FS('unlink', [path]) + ); + + const ls = (path) => ( + FS('readir', [path]) + ); + + const run = (_args) => { + if (ffmpeg === null) { + throw NO_LOAD; + } else if (running) { + throw NO_MULTIPLE_RUN; + } else { + running = true; + return new Promise((resolve) => { + const args = [...defaultArgs, ..._args.trim().split(' ')].filter((s) => s.length !== 0); + log('info', `ffmpeg command: ${args.join(' ')}`); + runResolve = resolve; + ffmpeg(args.length, stringList2pointer(Module, args)); + }); + } + }; + + const transcode = (input, output, opts = '') => ( + run(`-i ${input} ${opts} ${output}`) + ); + + const trim = (input, output, from, to, opts = '') => ( + run(`-i ${input} -ss ${from} -to ${to} ${opts} ${output}`) + ); + + const concatDemuxer = (input, output, opts = '') => { + const text = input.reduce((acc, path) => `${acc}\nfile ${path}`, ''); + writeText('concat_list.txt', text); + return run(`-f concat -safe 0 -i concat_list.txt ${opts} ${output}`); + }; + + return { + load, + FS, + write, + writeText, + read, + remove, + ls, + run, + transcode, + trim, + concatDemuxer, + }; +}; diff --git a/src/createJob.js b/src/createJob.js deleted file mode 100644 index f90364d..0000000 --- a/src/createJob.js +++ /dev/null @@ -1,21 +0,0 @@ -const getId = require('./utils/getId'); - -let jobCounter = 0; - -module.exports = ({ - id: _id, - action, - payload = {}, -}) => { - let id = _id; - if (typeof id === 'undefined') { - id = getId('Job', jobCounter); - jobCounter += 1; - } - - return { - id, - action, - payload, - }; -}; diff --git a/src/createWorker.js b/src/createWorker.js deleted file mode 100644 index dcd25ee..0000000 --- a/src/createWorker.js +++ /dev/null @@ -1,217 +0,0 @@ -const createJob = require('./createJob'); -const { log } = require('./utils/log'); -const getId = require('./utils/getId'); -const parseProgress = require('./utils/parseProgress'); -const resolvePaths = require('./utils/resolvePaths'); -const getTransferables = require('./utils/getTransferables'); -const { - defaultOptions, - spawnWorker, - onMessage, - fetchFile, -} = require('./worker/node'); - -let workerCounter = 0; - -module.exports = (_options = {}) => { - const id = getId('Worker', workerCounter); - const { - logger, - progress, - ...options - } = resolvePaths({ - ...defaultOptions, - ..._options, - }); - const resolves = {}; - const rejects = {}; - let worker = spawnWorker(options); - - workerCounter += 1; - - const setResolve = (action, res) => { - resolves[action] = res; - }; - - const setReject = (action, rej) => { - rejects[action] = rej; - }; - - const startJob = ({ id: jobId, action, payload }) => ( - new Promise((resolve, reject) => { - const packet = { - workerId: id, - jobId, - action, - payload, - }; - log(`[${id}]: Start ${jobId}, action=${action}`); - setResolve(action, resolve); - setReject(action, reject); - /* - * By using Transferable in postMessage, we are able - * to send large files to worker - * @ref: https://github.com/ffmpegjs/ffmpeg.js/issues/8#issuecomment-572230128 - */ - worker.postMessage(packet, getTransferables(packet)); - }) - ); - - const load = (jobId) => ( - startJob(createJob({ - id: jobId, action: 'load', payload: { options }, - })) - ); - - const write = async (path, data, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'FS', - payload: { - method: 'writeFile', - args: [path, await fetchFile(data)], - }, - })) - ); - - const writeText = (path, text, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'FS', - payload: { - method: 'writeFile', - args: [path, text], - }, - })) - ); - - const read = (path, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'FS', - payload: { - method: 'readFile', - args: [path], - }, - })) - ); - - const remove = (path, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'FS', - payload: { - method: 'unlink', - args: [path], - }, - })) - ); - - const run = (args, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'run', - payload: { - args, - }, - })) - ); - - const ls = (path, jobId) => ( - startJob(createJob({ - id: jobId, - action: 'FS', - payload: { - method: 'readdir', - args: [path], - }, - })) - ); - - const transcode = (input, output, opts = '', jobId) => ( - run( - `-i ${input} ${opts} ${output}`, - jobId, - ) - ); - - const trim = (input, output, from, to, opts = '', jobId) => ( - run( - `-i ${input} -ss ${from} -to ${to} ${opts} ${output}`, - jobId, - ) - ); - - const concatDemuxer = async (input, output, opts = '', jobId) => { - const text = input.reduce((acc, path) => `${acc}\nfile ${path}`, ''); - await writeText('concat_list.txt', text); - return run(`-f concat -safe 0 -i concat_list.txt ${opts} ${output}`, jobId); - }; - - const terminate = async () => { - if (worker !== null) { - /* - await startJob(createJob({ - id: jobId, - action: 'terminate', - })); - */ - worker.terminate(); - worker = null; - } - return Promise.resolve(); - }; - - onMessage(worker, ({ - workerId, jobId, action, status, payload, - }) => { - if (status === 'resolve') { - const { message, data } = payload; - log(`[${workerId}]: Complete ${jobId}`); - resolves[action]({ - workerId, - jobId, - message, - data, - }); - } else if (status === 'reject') { - rejects[action](payload); - throw Error( - `${payload} - - To get more informaion for debugging, please add logger in createWorker(): - - const worker = createWorker({ - logger: ({ message }) => console.log(message), - }); - - Even more details: - - const { setLogging } = require('@ffmpeg/ffmpeg'); - setLogging(true); - `, - ); - } else if (status === 'progress') { - parseProgress(payload, progress); - logger(payload); - } - }); - - return { - id, - worker, - setResolve, - setReject, - load, - write, - writeText, - read, - remove, - ls, - run, - transcode, - trim, - concatDemuxer, - terminate, - }; -}; diff --git a/src/index.js b/src/index.js old mode 100755 new mode 100644 index ab96c68..36f717e --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,6 @@ require('regenerator-runtime/runtime'); -const { logging, setLogging } = require('./utils/log'); -const createWorker = require('./createWorker'); +const createFFmpeg = require('./createFFmpeg'); module.exports = { - logging, - setLogging, - createWorker, + createFFmpeg, }; diff --git a/src/node/defaultOptions.js b/src/node/defaultOptions.js new file mode 100644 index 0000000..b3d3568 --- /dev/null +++ b/src/node/defaultOptions.js @@ -0,0 +1,8 @@ +const defaultOptions = require('../constants/defaultOptions'); + +/* + * Default options for node environment + */ +module.exports = { + ...defaultOptions, +}; diff --git a/src/worker/node/fetchFile.js b/src/node/fetchFile.js similarity index 100% rename from src/worker/node/fetchFile.js rename to src/node/fetchFile.js diff --git a/src/node/getModule.js b/src/node/getModule.js new file mode 100644 index 0000000..51f54fa --- /dev/null +++ b/src/node/getModule.js @@ -0,0 +1,6 @@ +module.exports = () => new Promise((resolve) => { + const Module = require('@ffmpeg/core'); + Module.onRuntimeInitialized = () => { + resolve(Module); + }; +}); diff --git a/src/node/index.js b/src/node/index.js new file mode 100644 index 0000000..85ade1f --- /dev/null +++ b/src/node/index.js @@ -0,0 +1,9 @@ +const defaultOptions = require('./defaultOptions'); +const getModule = require('./getModule'); +const fetchFile = require('./fetchFile'); + +module.exports = { + defaultOptions, + getModule, + fetchFile, +}; diff --git a/src/utils/getId.js b/src/utils/getId.js deleted file mode 100644 index 8c2b119..0000000 --- a/src/utils/getId.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (prefix, cnt) => ( - `${prefix}-${cnt}-${Math.random().toString(16).slice(3, 8)}` -); diff --git a/src/utils/getTransferables.js b/src/utils/getTransferables.js deleted file mode 100644 index 11c9112..0000000 --- a/src/utils/getTransferables.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = (packet) => { - const transferables = []; - const check = (b) => { - if (b instanceof Uint8Array) { - transferables.push(b.buffer); - } else if (b instanceof ArrayBuffer) { - transferables.push(b); - } - }; - const { payload: { args, data } } = packet; - check(data); - if (Array.isArray(args)) { - args.forEach((arg) => check(arg)); - } - return transferables; -}; diff --git a/src/utils/log.js b/src/utils/log.js index 4faac26..34ef0ce 100644 --- a/src/utils/log.js +++ b/src/utils/log.js @@ -6,4 +6,4 @@ exports.setLogging = (_logging) => { logging = _logging; }; -exports.log = (...args) => (logging ? console.log.apply(this, args) : null); +exports.log = (type, message) => (logging ? console.log(`[${type}] ${message}`) : null); diff --git a/src/utils/resolvePaths.js b/src/utils/resolvePaths.js index 93be72f..717d9fc 100644 --- a/src/utils/resolvePaths.js +++ b/src/utils/resolvePaths.js @@ -3,7 +3,7 @@ const resolveURL = isBrowser ? require('resolve-url') : s => s; // eslint-disabl module.exports = (options) => { const opts = { ...options }; - ['corePath', 'workerPath'].forEach((key) => { + ['corePath'].forEach((key) => { if (typeof options[key] !== 'undefined') { opts[key] = resolveURL(opts[key]); } diff --git a/src/worker-script/utils/str2ptr.js b/src/utils/string2pointer.js similarity index 100% rename from src/worker-script/utils/str2ptr.js rename to src/utils/string2pointer.js diff --git a/src/worker-script/utils/strList2ptr.js b/src/utils/stringList2pointer.js similarity index 71% rename from src/worker-script/utils/strList2ptr.js rename to src/utils/stringList2pointer.js index a3af49f..d9523cb 100644 --- a/src/worker-script/utils/strList2ptr.js +++ b/src/utils/stringList2pointer.js @@ -1,10 +1,10 @@ -const str2ptr = require('./str2ptr'); +const string2pointer = require('./string2pointer'); module.exports = (Module, strList) => { const listPtr = Module._malloc(strList.length * Uint32Array.BYTES_PER_ELEMENT); strList.forEach((s, idx) => { - const strPtr = str2ptr(Module, s); + const strPtr = string2pointer(Module, s); Module.setValue(listPtr + (4 * idx), strPtr, 'i32'); }); diff --git a/src/worker-script/browser/.eslintrc b/src/worker-script/browser/.eslintrc deleted file mode 100644 index e88da2e..0000000 --- a/src/worker-script/browser/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "worker": true - } -} diff --git a/src/worker-script/browser/getCore.js b/src/worker-script/browser/getCore.js deleted file mode 100644 index 521d008..0000000 --- a/src/worker-script/browser/getCore.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = (corePath) => { - if (typeof global.Module === 'undefined') { - global.importScripts(corePath); - } - return global.Module; -}; diff --git a/src/worker-script/browser/index.js b/src/worker-script/browser/index.js deleted file mode 100644 index 86fb0b5..0000000 --- a/src/worker-script/browser/index.js +++ /dev/null @@ -1,10 +0,0 @@ -const worker = require('..'); -const getCore = require('./getCore'); - -global.addEventListener('message', ({ data }) => { - worker.dispatchHandlers(data, postMessage); -}); - -worker.setAdapter({ - getCore, -}); diff --git a/src/worker-script/index.js b/src/worker-script/index.js deleted file mode 100644 index 57ebfef..0000000 --- a/src/worker-script/index.js +++ /dev/null @@ -1,96 +0,0 @@ -require('regenerator-runtime/runtime'); -const defaultArgs = require('./constants/defaultArgs'); -const strList2ptr = require('./utils/strList2ptr'); -const getTransferables = require('../utils/getTransferables'); - -const NO_LOAD_ERROR = 'FFmpegCore is not ready, make sure you have completed Worker.load().'; - -let action = 'unknown'; -let Module = null; -let adapter = null; -let ffmpeg = null; - -const load = ({ workerId, payload: { options: { corePath } } }, res) => { - if (Module === null) { - const Core = adapter.getCore(corePath); - Core() - .then(async (_Module) => { - Module = _Module; - Module.setLogger((message, type) => { - res.progress({ - workerId, action, type, message, - }); - }); - ffmpeg = Module.cwrap('ffmpeg', 'number', ['number', 'number']); - res.resolve({ message: 'Loaded ffmpeg-core' }); - }); - } else { - res.resolve({ message: 'Loaded ffmpeg-core' }); - } -}; - -const FS = ({ - payload: { - method, - args, - }, -}, res) => { - if (Module === null) { - throw NO_LOAD_ERROR; - } else { - res.resolve({ - message: `Complete ${method}`, - data: Module.FS[method](...args), - }); - } -}; - -const run = ({ - payload: { - args: _args, - }, -}, res) => { - if (Module === null) { - throw NO_LOAD_ERROR; - } else { - const args = [...defaultArgs, ..._args.trim().split(' ')].filter((s) => s.length !== 0); - ffmpeg(args.length, strList2ptr(Module, args)); - res.resolve({ - message: `Complete ${args.join(' ')}`, - }); - } -}; - -exports.dispatchHandlers = (packet, send) => { - const { workerId, jobId, action: act } = packet; - const res = (status, payload) => { - const pkt = { - workerId, - jobId, - action: act, - status, - payload, - }; - send(pkt, getTransferables(pkt)); - }; - res.resolve = res.bind(this, 'resolve'); - res.reject = res.bind(this, 'reject'); - res.progress = res.bind(this, 'progress'); - - action = act; - try { - ({ - load, - FS, - run, - })[act](packet, res); - } catch (err) { - /** Prepare exception to travel through postMessage */ - res.reject(err.toString()); - } - action = 'unknown'; -}; - -exports.setAdapter = (_adapter) => { - adapter = _adapter; -}; diff --git a/src/worker-script/node/getCore.js b/src/worker-script/node/getCore.js deleted file mode 100644 index af4bb5f..0000000 --- a/src/worker-script/node/getCore.js +++ /dev/null @@ -1,8 +0,0 @@ -let FFmpegCore = null; - -module.exports = () => { - if (FFmpegCore === null) { - FFmpegCore = require('@ffmpeg/core'); - } - return FFmpegCore; -}; diff --git a/src/worker-script/node/index.js b/src/worker-script/node/index.js deleted file mode 100644 index 8f9baf1..0000000 --- a/src/worker-script/node/index.js +++ /dev/null @@ -1,16 +0,0 @@ -const { parentPort } = require('worker_threads'); -const worker = require('..'); -const getCore = require('./getCore'); - -parentPort.on('message', (packet) => { - worker.dispatchHandlers( - packet, - (...args) => { - parentPort.postMessage(...args); - }, - ); -}); - -worker.setAdapter({ - getCore, -}); diff --git a/src/worker/browser/defaultOptions.js b/src/worker/browser/defaultOptions.js deleted file mode 100644 index 61bd237..0000000 --- a/src/worker/browser/defaultOptions.js +++ /dev/null @@ -1,15 +0,0 @@ -const resolveURL = require('resolve-url'); -const { version, dependencies } = require('../../../package.json'); -const defaultOptions = require('../../constants/defaultOptions'); - -/* - * Default options for browser worker - */ -module.exports = { - ...defaultOptions, - workerPath: (typeof process !== 'undefined' && process.env.FFMPEG_ENV === 'development') - ? resolveURL(`/dist/worker.dev.js?nocache=${Math.random().toString(36).slice(3)}`) - : `https://unpkg.com/@ffmpeg/ffmpeg@v${version}/dist/worker.min.js`, - corePath: `https://unpkg.com/@ffmpeg/core@v${dependencies['@ffmpeg/core'].substring(1)}/ffmpeg-core.js`, - workerBlobURL: true, -}; diff --git a/src/worker/browser/index.js b/src/worker/browser/index.js deleted file mode 100644 index 467d4bb..0000000 --- a/src/worker/browser/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Tesseract Worker adapter for browser - * - * @fileoverview Tesseract Worker adapter for browser - * @author Kevin Kwok - * @author Guillermo Webster - * @author Jerome Wu - */ -const defaultOptions = require('./defaultOptions'); -const spawnWorker = require('./spawnWorker'); -const onMessage = require('./onMessage'); -const fetchFile = require('./fetchFile'); - -module.exports = { - defaultOptions, - spawnWorker, - onMessage, - fetchFile, -}; diff --git a/src/worker/browser/onMessage.js b/src/worker/browser/onMessage.js deleted file mode 100644 index ec74783..0000000 --- a/src/worker/browser/onMessage.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = (worker, handler) => { - worker.onmessage = ({ data }) => { // eslint-disable-line - handler(data); - }; -}; diff --git a/src/worker/browser/spawnWorker.js b/src/worker/browser/spawnWorker.js deleted file mode 100644 index 5ae4ccb..0000000 --- a/src/worker/browser/spawnWorker.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * spawnWorker - * - * @name spawnWorker - * @function create a new Worker in browser - * @access public - */ -module.exports = ({ workerPath, workerBlobURL }) => { - let worker; - if (Blob && URL && workerBlobURL) { - /* Use Blob to load cross domain worker script */ - const blob = new Blob([`importScripts("${workerPath}");`], { - type: 'text/javascript', - }); - worker = new Worker(URL.createObjectURL(blob)); - } else { - worker = new Worker(workerPath); - } - return worker; -}; diff --git a/src/worker/node/defaultOptions.js b/src/worker/node/defaultOptions.js deleted file mode 100644 index 053c1e3..0000000 --- a/src/worker/node/defaultOptions.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); -const defaultOptions = require('../../constants/defaultOptions'); - -/* - * Default options for node worker - */ -module.exports = { - ...defaultOptions, - workerPath: path.join(__dirname, '..', '..', 'worker-script', 'node', 'index.js'), -}; diff --git a/src/worker/node/onMessage.js b/src/worker/node/onMessage.js deleted file mode 100644 index 7100e71..0000000 --- a/src/worker/node/onMessage.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (worker, handler) => { - worker.on('message', handler); -}; diff --git a/src/worker/node/spawnWorker.js b/src/worker/node/spawnWorker.js deleted file mode 100644 index 5bba13c..0000000 --- a/src/worker/node/spawnWorker.js +++ /dev/null @@ -1,12 +0,0 @@ -const { Worker } = require('worker_threads'); - -/** - * spawnWorker - * - * @name spawnWorker - * @function fork a new worker thread in node - * @access public - */ -module.exports = ({ workerPath }) => ( - new Worker(workerPath) -); diff --git a/tests/assets/StarWars3.wav b/tests/assets/StarWars3.wav new file mode 100644 index 0000000..1a2dd7a Binary files /dev/null and b/tests/assets/StarWars3.wav differ diff --git a/tests/constants.js b/tests/constants.js index af74d63..0e7a163 100644 --- a/tests/constants.js +++ b/tests/constants.js @@ -1,11 +1,9 @@ -const TIMEOUT = 30000; +const TIMEOUT = 60000; const BASE_URL = 'http://localhost:3000/tests/assets'; const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined'; const OPTIONS = { corePath: '../node_modules/@ffmpeg/core/ffmpeg-core.js', - ...(IS_BROWSER ? { workerPath: '../dist/worker.dev.js' } : {}), }; -const FLAME_MP4_LENGTH = 100374; if (typeof module !== 'undefined') { module.exports = { @@ -13,6 +11,5 @@ if (typeof module !== 'undefined') { BASE_URL, IS_BROWSER, OPTIONS, - FLAME_MP4_LENGTH, }; } diff --git a/tests/ffmpeg.test.js b/tests/ffmpeg.test.js index 56258e9..337a2e5 100644 --- a/tests/ffmpeg.test.js +++ b/tests/ffmpeg.test.js @@ -1,20 +1,27 @@ -const { createWorker } = FFmpeg; -const worker = createWorker(OPTIONS); +const { createFFmpeg } = FFmpeg; +const ffmpeg = createFFmpeg(OPTIONS); before(async function cb() { this.timeout(0); - await worker.load(); + await ffmpeg.load(); }); describe('transcode()', () => { describe('should transcode different format', () => { - ['flame.avi'].forEach((name) => ( - it(`transcode ${name}`, async () => { - await worker.write(name, `${BASE_URL}/${name}`); - await worker.transcode(name, 'output.mp4'); - const { data } = await worker.read('output.mp4'); - expect(data.length).to.be(FLAME_MP4_LENGTH); - }).timeout(TIMEOUT) - )); + [1, 2, 4].forEach((n) => { + [ + { from: 'flame.avi', to: 'flame.mp4' }, + { from: 'flame.avi', to: 'flame.webm' }, + { from: 'StarWars3.wav', to: 'StarWars3.mp3' }, + ].forEach(({ from, to }) => ( + it(`transcode ${from} to ${to} (${n} threads)`, async () => { + await ffmpeg.write(from, `${BASE_URL}/${from}`); + await ffmpeg.transcode(from, to, `-threads ${n}`); + const data = ffmpeg.read(to); + ffmpeg.remove(to); + expect(data.length).not.to.be(0); + }).timeout(TIMEOUT) + )); + }); }); });