Refactor remote script loading code

This commit is contained in:
Jerome Wu 2020-11-24 11:26:53 +08:00
parent 7a3b66faa3
commit 36a148bb43
3 changed files with 73 additions and 17 deletions

View File

@ -1,23 +1,50 @@
/* eslint-disable no-undef */
const resolveURL = require('resolve-url'); const resolveURL = require('resolve-url');
const { log } = require('../utils/log'); const { log } = require('../utils/log');
/*
* Fetch data from remote URL and convert to blob URL
* to avoid CORS issue
*/
const toBlobURL = async (url, mimeType) => {
log('info', `fetch ${url}`);
const buf = await (await fetch(url)).arrayBuffer();
log('info', `${url} file size = ${buf.byteLength} bytes`);
const blob = new Blob([buf], { type: mimeType });
const blobURL = URL.createObjectURL(blob);
log('info', `${url} blob URL = ${blobURL}`);
return blobURL;
};
module.exports = async ({ corePath: _corePath }) => { module.exports = async ({ corePath: _corePath }) => {
if (typeof _corePath !== 'string') { if (typeof _corePath !== 'string') {
throw Error('corePath should be a string!'); throw Error('corePath should be a string!');
} }
if (typeof window.createFFmpegCore === 'undefined') { const coreRemotePath = resolveURL(_corePath);
log('info', 'fetch ffmpeg-core.worker.js script'); const corePath = await toBlobURL(
const corePath = resolveURL(_corePath); coreRemotePath,
const workerBlob = await (await fetch(corePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js'))).blob(); 'application/javascript',
window.FFMPEG_CORE_WORKER_SCRIPT = URL.createObjectURL(workerBlob); );
log('info', `worker object URL=${window.FFMPEG_CORE_WORKER_SCRIPT}`); const wasmPath = await toBlobURL(
log('info', `download ffmpeg-core script (~25 MB) from ${corePath}`); coreRemotePath.replace('ffmpeg-core.js', 'ffmpeg-core.wasm'),
'application/wasm',
);
const workerPath = await toBlobURL(
coreRemotePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js'),
'application/javascript',
);
if (typeof createFFmpegCore === 'undefined') {
return new Promise((resolve) => { return new Promise((resolve) => {
const script = document.createElement('script'); const script = document.createElement('script');
const eventHandler = () => { const eventHandler = () => {
script.removeEventListener('load', eventHandler); script.removeEventListener('load', eventHandler);
log('info', 'initialize ffmpeg-core'); log('info', 'ffmpeg-core.js script loaded');
resolve(window.createFFmpegCore); resolve({
createFFmpegCore,
corePath,
wasmPath,
workerPath,
});
}; };
script.src = corePath; script.src = corePath;
script.type = 'text/javascript'; script.type = 'text/javascript';
@ -25,6 +52,11 @@ module.exports = async ({ corePath: _corePath }) => {
document.getElementsByTagName('head')[0].appendChild(script); document.getElementsByTagName('head')[0].appendChild(script);
}); });
} }
log('info', 'ffmpeg-core is loaded already'); log('info', 'ffmpeg-core.js script is loaded already');
return Promise.resolve(window.createFFmpegCore); return Promise.resolve({
createFFmpegCore,
corePath,
wasmPath,
workerPath,
});
}; };

View File

@ -51,15 +51,39 @@ module.exports = (_options = {}) => {
log('info', 'load ffmpeg-core'); log('info', 'load ffmpeg-core');
if (Core === null) { if (Core === null) {
log('info', 'loading ffmpeg-core'); log('info', 'loading ffmpeg-core');
const createFFmpegCore = await getCreateFFmpegCore(options); /*
* In node environment, all paths are undefined as there
* is no need to set them.
*/
const {
createFFmpegCore,
corePath,
workerPath,
wasmPath,
} = await getCreateFFmpegCore(options);
Core = await createFFmpegCore({ Core = await createFFmpegCore({
/*
* 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 }), printErr: (message) => parseMessage({ type: 'fferr', message }),
print: (message) => parseMessage({ type: 'ffout', message }), print: (message) => parseMessage({ type: 'ffout', message }),
/*
* 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) => { locateFile: (path, prefix) => {
if (typeof window !== 'undefined' if (typeof window !== 'undefined') {
&& typeof window.FFMPEG_CORE_WORKER_SCRIPT !== 'undefined' if (typeof wasmPath !== 'undefined'
&& path.endsWith('ffmpeg-core.worker.js')) { && path.endsWith('ffmpeg-core.wasm')) {
return window.FFMPEG_CORE_WORKER_SCRIPT; return wasmPath;
}
if (typeof workerPath !== 'undefined'
&& path.endsWith('ffmpeg-core.worker.js')) {
return workerPath;
}
} }
return prefix + path; return prefix + path;
}, },

View File

@ -3,5 +3,5 @@ const { log } = require('../utils/log');
module.exports = ({ corePath }) => new Promise((resolve) => { module.exports = ({ corePath }) => new Promise((resolve) => {
log('info', `fetch ffmpeg.wasm-core script from ${corePath}`); log('info', `fetch ffmpeg.wasm-core script from ${corePath}`);
// eslint-disable-next-line import/no-dynamic-require // eslint-disable-next-line import/no-dynamic-require
resolve(require(corePath)); resolve({ createFFmpegCore: require(corePath) });
}); });