diff --git a/README.md b/README.md index 27e05f8..f9844c4 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,10 @@ Try it: [https://ffmpegwasm.netlify.app](https://ffmpegwasm.netlify.app#demo) $ npm install @ffmpeg/ffmpeg @ffmpeg/core ``` -> As we are using the latest experimental features, you need to add few flags to run in Node.js +> As we are using experimental features, you need to add flags to run in Node.js ``` -$ node --experimental-wasm-threads --experimental-wasm-bulk-memory transcode.js +$ node --experimental-wasm-threads transcode.js ``` **Browser** diff --git a/package-lock.json b/package-lock.json index 66855fd..9a91645 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2035,23 +2035,10 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "globals": { "version": "12.4.0", @@ -2396,15 +2383,23 @@ } }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } } }, "ajv-keywords": { @@ -2689,12 +2684,6 @@ "schema-utils": "^2.6.5" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, "mkdirp": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", @@ -3863,12 +3852,6 @@ } } }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -4038,9 +4021,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.0.tgz", - "integrity": "sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg==", + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", "dev": true }, "forwarded": { @@ -4528,14 +4511,6 @@ "dev": true, "requires": { "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, "leven": { @@ -4599,12 +4574,6 @@ "requires": { "minimist": "^1.2.0" } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true } } }, @@ -4810,9 +4779,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "mkdirp": { @@ -5646,9 +5615,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { @@ -5675,9 +5644,9 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "pend": { @@ -6114,23 +6083,10 @@ "ajv-keywords": "^3.4.1" }, "dependencies": { - "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" } } }, @@ -6670,18 +6626,6 @@ "terser": "^5.3.8" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -6691,8 +6635,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "p-limit": { "version": "3.0.2", @@ -6760,12 +6703,6 @@ "requires": { "minimist": "^1.2.0" } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true } } }, @@ -6956,18 +6893,6 @@ "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", "dev": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -6977,8 +6902,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "find-up": { "version": "4.1.0", @@ -7105,18 +7029,6 @@ "schema-utils": "^3.0.0" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -7126,8 +7038,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "mime-db": { "version": "1.44.0", diff --git a/package.json b/package.json index b4f31b2..365f995 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "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 --experimental-wasm-threads --experimental-wasm-bulk-memory node_modules/.bin/_mocha --exit --bail --require ./scripts/test-helper.js", + "test:node": "node --experimental-wasm-threads 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 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" diff --git a/scripts/webpack.config.dev.js b/scripts/webpack.config.dev.js index b630863..2bfd2d0 100644 --- a/scripts/webpack.config.dev.js +++ b/scripts/webpack.config.dev.js @@ -1,5 +1,4 @@ const path = require('path'); -const webpack = require('webpack'); const common = require('./webpack.config.common'); const genConfig = ({ diff --git a/src/createFFmpeg.js b/src/createFFmpeg.js index f4ba9f2..5432f98 100644 --- a/src/createFFmpeg.js +++ b/src/createFFmpeg.js @@ -1,6 +1,4 @@ const { defaultArgs, baseOptions } = require('./config'); -const { setLogging, setCustomLogger, log } = require('./utils/log'); -const parseProgress = require('./utils/parseProgress'); const parseArgs = require('./utils/parseArgs'); const { defaultOptions, getCreateFFmpegCore } = require('./node'); const { version } = require('../package.json'); @@ -23,14 +21,49 @@ module.exports = (_options = {}) => { let runResolve = null; let runReject = null; let running = false; + let customLogger = () => {}; let progress = optProgress; + let duration = 0; + let ratio = 0; + const detectCompletion = (message) => { if (message === 'FFMPEG_END' && runResolve !== null) { runResolve(); runResolve = null; + runReject = null; running = false; } }; + const log = (type, message) => { + customLogger({ type, message }); + if (logging) { + console.log(`[${type}] ${message}`); + } + }; + const ts2sec = (ts) => { + const [h, m, s] = ts.split(':'); + return (parseFloat(h) * 60 * 60) + (parseFloat(m) * 60) + parseFloat(s); + }; + const parseProgress = (message, progress) => { + if (typeof message === 'string') { + if (message.startsWith(' Duration')) { + const ts = message.split(', ')[0].split(': ')[1]; + const d = ts2sec(ts); + progress({ duration: d, ratio }); + if (duration === 0 || duration > d) { + duration = d; + } + } else if (message.startsWith('frame') || message.startsWith('size')) { + const ts = message.split('time=')[1].split(' ')[0]; + const t = ts2sec(ts); + ratio = t / duration; + progress({ ratio, time: t }); + } else if (message.startsWith('video:')) { + progress({ ratio: 1 }); + duration = 0; + } + } + }; const parseMessage = ({ type, message }) => { log(type, message); parseProgress(message, progress); @@ -89,7 +122,7 @@ module.exports = (_options = {}) => { return prefix + path; }, }); - ffmpeg = Core.cwrap('proxy_main', 'number', ['number', 'number']); + ffmpeg = Core.cwrap(options.mainName || 'proxy_main', 'number', ['number', 'number']); log('info', 'ffmpeg-core loaded'); } else { throw Error('ffmpeg.wasm was loaded, you should not load it again, use ffmpeg.isLoaded() to check next time.'); @@ -179,10 +212,15 @@ module.exports = (_options = {}) => { if (Core === null) { throw NO_LOAD; } else { + // if there's any pending runs, reject them + if(runReject) { + runReject('ffmpeg has exited') + } running = false; try { Core.exit(1); } catch (err) { + log(err.message); if (runReject) { runReject(err); } @@ -200,11 +238,12 @@ module.exports = (_options = {}) => { }; const setLogger = (_logger) => { - setCustomLogger(_logger); + customLogger = _logger; }; - setLogging(logging); - setCustomLogger(logger); + const setLogging = (_logging) => { + logging = _logging; + }; log('info', `use ffmpeg.wasm v${version}`); diff --git a/src/index.d.ts b/src/index.d.ts index 5d0b749..5d6bc25 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,6 +1,7 @@ export const FS: { - writeFile: (fileName: string, binaryData: Uint8Array) => void, + writeFile: (fileName: string, binaryData: Uint8Array | string) => void, readFile: (fileName: string) => Uint8Array, + readdir: (pathName: string) => string[], unlink: (fileName: string) => void, } diff --git a/tests/ffmpeg.test.js b/tests/ffmpeg.test.js index 2a434cd..270ad3d 100644 --- a/tests/ffmpeg.test.js +++ b/tests/ffmpeg.test.js @@ -48,6 +48,16 @@ describe('run()', () => { } }, 500); }).timeout(TIMEOUT); + + it('should terminate the run if exit is called', async () => { + const ffmpeg = createFFmpeg(OPTIONS); + await ffmpeg.load(); + + ffmpeg.run('-h').catch(e=> { + expect(e).to.be.equal('ffmpeg has exited') + }); + expect(ffmpeg.exit()).to.throw(); + }).timeout(TIMEOUT); }); describe('FS()', () => {