Skip to content

Commit

Permalink
Merge pull request #4 from ente-io/single-thread
Browse files Browse the repository at this point in the history
Single thread
  • Loading branch information
abhinavkgrd authored Feb 1, 2024
2 parents 761b30d + 65725b8 commit c3aab22
Show file tree
Hide file tree
Showing 14 changed files with 9,255 additions and 74 deletions.
4 changes: 0 additions & 4 deletions .yarnrc.yml

This file was deleted.

2 changes: 1 addition & 1 deletion examples/browser/transcode.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h3>Upload a video to transcode to mp4 (x264) and play!</h3>

const transcode = async ({ target: { files } }) => {
if (ffmpeg === null) {
ffmpeg = createFFmpeg({ log: true });
ffmpeg = createFFmpeg({ log: true, corePath: '/ffmpeg-core.js' });
}
const message = document.getElementById('message');
const { name } = files[0];
Expand Down
9,165 changes: 9,144 additions & 21 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@
"dependencies": {
"is-url": "^1.2.4",
"node-fetch": "^2.6.1",
"regenerator-runtime": "^0.13.7",
"resolve-url": "^0.2.1"
"regenerator-runtime": "^0.13.7"
},
"devDependencies": {
"@babel/core": "^7.12.3",
Expand Down
3 changes: 1 addition & 2 deletions src/browser/defaultOptions.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
const resolveURL = require('resolve-url');
const { devDependencies } = require('../../package.json');

/*
* Default options for browser environment
*/
module.exports = {
corePath: typeof process !== 'undefined' && process.env.NODE_ENV === 'development'
? resolveURL('/node_modules/@ffmpeg/core/dist/ffmpeg-core.js')
? '/node_modules/@ffmpeg/core/dist/ffmpeg-core.js'
: `https://unpkg.com/@ffmpeg/core@${devDependencies['@ffmpeg/core'].substring(1)}/dist/ffmpeg-core.js`,
};
4 changes: 1 addition & 3 deletions src/browser/fetchFile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const resolveURL = require('resolve-url');

const readFromBlobOrFile = (blob) => (
new Promise((resolve, reject) => {
const fileReader = new FileReader();
Expand Down Expand Up @@ -27,7 +25,7 @@ module.exports = async (_data) => {
.map((c) => c.charCodeAt(0));
/* From remote server/URL */
} else {
const res = await fetch(resolveURL(_data));
const res = await fetch(_data);
data = await res.arrayBuffer();
}
/* From Blob or File */
Expand Down
63 changes: 36 additions & 27 deletions src/browser/getCreateFFmpegCore.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
/* eslint-disable no-undef */
const resolveURL = require('resolve-url');
const { log } = require('../utils/log');
const {
CREATE_FFMPEG_CORE_IS_NOT_DEFINED,
} = require('../utils/errors');
const { CREATE_FFMPEG_CORE_IS_NOT_DEFINED } = require('../utils/errors');

/*
* Fetch data from remote URL and convert to blob URL
Expand All @@ -19,7 +16,7 @@ const {
// return blobURL;
// };

module.exports = async ({ corePath: _corePath }) => {
module.exports = async ({ corePath: _corePath, mt: _mt, runningInWorker: _runningInWorker }) => {
if (typeof _corePath !== 'string') {
throw Error('corePath should be a string!');
}
Expand All @@ -35,31 +32,43 @@ module.exports = async ({ corePath: _corePath }) => {
// coreRemotePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js'),
// 'application/javascript',
// );
const coreRemotePath = resolveURL(_corePath);
const coreRemotePath = _corePath;
const corePath = coreRemotePath;
const wasmPath = coreRemotePath.replace('ffmpeg-core.js', 'ffmpeg-core.wasm');
const workerPath = coreRemotePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js');

const wasmPath = coreRemotePath.replace(
'ffmpeg-core.js',
'ffmpeg-core.wasm',
);
let workerPath = null;
if (_mt) {
workerPath = coreRemotePath.replace(
'ffmpeg-core.js',
'ffmpeg-core.worker.js',
);
}
if (typeof createFFmpegCore === 'undefined') {
return new Promise((resolve) => {
const script = document.createElement('script');
const eventHandler = () => {
script.removeEventListener('load', eventHandler);
if (typeof createFFmpegCore === 'undefined') {
throw Error(CREATE_FFMPEG_CORE_IS_NOT_DEFINED(coreRemotePath));
}
log('info', 'ffmpeg-core.js script loaded');
resolve({
createFFmpegCore,
corePath,
wasmPath,
workerPath,
});
};
script.src = corePath;
script.type = 'text/javascript';
script.addEventListener('load', eventHandler);
document.getElementsByTagName('head')[0].appendChild(script);
if (_runningInWorker) {
importScripts(coreRemotePath);
} else {
const script = document.createElement('script');
const eventHandler = () => {
script.removeEventListener('load', eventHandler);
if (typeof createFFmpegCore === 'undefined') {
throw CREATE_FFMPEG_CORE_IS_NOT_DEFINED(coreRemotePath);
}
log('info', 'ffmpeg-core.js script loaded');
};
script.src = corePath;
script.type = 'text/javascript';
script.addEventListener('load', eventHandler);
document.getElementsByTagName('head')[0].appendChild(script);
}
resolve({
createFFmpegCore,
corePath,
wasmPath,
workerPath,
});
});
}
log('info', 'ffmpeg-core.js script is loaded already');
Expand Down
4 changes: 4 additions & 0 deletions src/browser/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
const defaultOptions = require('./defaultOptions');
const getCreateFFmpegCore = require('./getCreateFFmpegCore');
const fetchFile = require('./fetchFile');
const { getCore: getCoreMT, ffmpeg: ffmpegMT } = require('./mt');
const { getCore: getCoreST, ffmpeg: ffmpegST } = require('./st');

module.exports = {
defaultOptions,
getCreateFFmpegCore,
fetchFile,
getCore: (mt) => (mt ? getCoreMT : getCoreST),
ffmpeg: (mt) => (mt ? ffmpegMT : ffmpegST)

Check failure on line 12 in src/browser/index.js

View workflow job for this annotation

GitHub Actions / Test on node 12 and ubuntu-latest

Missing trailing comma
};
20 changes: 20 additions & 0 deletions src/browser/mt/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* eslint-disable no-undef */
const parseArgs = require('../../utils/parseArgs');

const getCore = (opts) => (
createFFmpegCore(opts)
);

const ffmpeg = ({ Core, args }) => (
Core.ccall(
'emscripten_proxy_main',
'number',
['number', 'number'],
parseArgs(Core, args),
)
);

module.exports = {
getCore,
ffmpeg,
};
17 changes: 17 additions & 0 deletions src/browser/st/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const parseArgs = require('../../utils/parseArgs');

const getCore = (opts) => (
createFFmpegCore(opts)

Check failure on line 4 in src/browser/st/index.js

View workflow job for this annotation

GitHub Actions / Test on node 12 and ubuntu-latest

'createFFmpegCore' is not defined
);
const ffmpeg = ({ Core, args }) => (
Core.ccall(
'main',
'number',
['number', 'number'],
parseArgs(Core, args),
)
);

module.exports = {
getCore, ffmpeg,
};
8 changes: 8 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,13 @@ module.exports = {
* each environment.
*/
corePath: '',
/*
* Whether to use the multi-thread version of ffmpeg.
* Most of the time, the multi-thread version is much faster
* than single thread, but it requires SharedArrayBuffer which
* is not well supported by most of the browsers.
*/
mt: true,
runningInWorker: typeof importScripts === 'function',
},
};
26 changes: 15 additions & 11 deletions src/createFFmpeg.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
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 {
defaultOptions,
getCreateFFmpegCore,
getCore: _getCore,
ffmpeg: _ffmpeg,
} = require('./node');
const { version } = require('../package.json');

const NO_LOAD = Error('ffmpeg.wasm is not ready, make sure you have completed load().');
Expand All @@ -18,8 +22,10 @@ module.exports = (_options = {}) => {
...defaultOptions,
..._options,
};
const { mt } = options;
const getCore = _getCore(mt);
const ffmpeg = _ffmpeg(mt);
let Core = null;
let ffmpeg = null;
let runResolve = null;
let running = false;
let progress = optProgress;
Expand All @@ -30,7 +36,7 @@ module.exports = (_options = {}) => {
running = false;
}
};
const parseMessage = ({ type, message }) => {
const parseMessage = (type) => (message) => {
log(type, message);
parseProgress(message, progress);
detectCompletion(message);
Expand All @@ -56,26 +62,25 @@ module.exports = (_options = {}) => {
* is no need to set them.
*/
const {
createFFmpegCore,
corePath,
workerPath,
wasmPath,
} = await getCreateFFmpegCore(options);
Core = await createFFmpegCore({
Core = await getCore({
/*
* Assign mainScriptUrlOrBlob fixes chrome extension web worker issue
* as there is no document.currentScript in the context of content_scripts
*/
mainScriptUrlOrBlob: corePath,
printErr: (message) => parseMessage({ type: 'fferr', message }),
print: (message) => parseMessage({ type: 'ffout', message }),
printErr: parseMessage('fferr'),
print: parseMessage('ffout'),
/*
* locateFile overrides paths of files that is loaded by main script (ffmpeg-core.js).
* It is critical for browser environment and we override both wasm and worker paths
* as we are using blob URL instead of original URL to avoid cross origin issues.
*/
locateFile: (path, prefix) => {
if (typeof window !== 'undefined') {
if (typeof window !== 'undefined' || typeof importScripts !== 'undefined') {
if (typeof wasmPath !== 'undefined'
&& path.endsWith('ffmpeg-core.wasm')) {
return wasmPath;
Expand All @@ -88,7 +93,6 @@ module.exports = (_options = {}) => {
return prefix + path;
},
});
ffmpeg = Core.cwrap('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.');
Expand Down Expand Up @@ -129,7 +133,7 @@ module.exports = (_options = {}) => {
return new Promise((resolve) => {
const args = [...defaultArgs, ..._args].filter((s) => s.length !== 0);
runResolve = resolve;
ffmpeg(...parseArgs(Core, args));
ffmpeg({ Core, args });
});
}
};
Expand Down
4 changes: 3 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const FS: {
writeFile: (fileName: string, binaryData: Uint8Array) => void,
readFile: (fileName: string) => Uint8Array,
unlink: (fileName: string) => void,
}
};

type FSMethodNames = { [K in keyof typeof FS]: (typeof FS)[K] extends (...args: any[]) => any ? K : never }[keyof typeof FS];
type FSMethodArgs = { [K in FSMethodNames]: Parameters<(typeof FS)[K]> };
Expand All @@ -16,6 +16,8 @@ export interface CreateFFmpegOptions {
corePath?: string;
/** a boolean to turn on all logs, default is false */
log?: boolean;
/** a boolean to specify if the core is single or multi-threaded */
mt?:boolean
/** a function to get log messages, a quick example is ({ message }) => console.log(message) */
logger?: LogCallback;
/** a function to trace the progress, a quick example is p => console.log(p) */
Expand Down
6 changes: 4 additions & 2 deletions src/utils/errors.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const CREATE_FFMPEG_CORE_IS_NOT_DEFINED = (corePath) => (`
const NO_LOAD = Error(''.trim('\n'));

Check failure on line 1 in src/utils/errors.js

View workflow job for this annotation

GitHub Actions / Test on node 12 and ubuntu-latest

'NO_LOAD' is assigned a value but never used

const CREATE_FFMPEG_CORE_IS_NOT_DEFINED = (corePath) => (Error(`
createFFmpegCore is not defined. ffmpeg.wasm is unable to find createFFmpegCore after loading ffmpeg-core.js from ${corePath}. Use another URL when calling createFFmpeg():
const ffmpeg = createFFmpeg({
corePath: 'http://localhost:3000/ffmpeg-core.js',
});
`);
`));

module.exports = {
CREATE_FFMPEG_CORE_IS_NOT_DEFINED,
Expand Down

0 comments on commit c3aab22

Please sign in to comment.