Complete major refactor
This commit is contained in:
parent
25f37fa00b
commit
265cf4c580
@ -1,13 +1,11 @@
|
||||
const resolveURL = require('resolve-url');
|
||||
const { dependencies } = require('../../package.json');
|
||||
const defaultOptions = require('../constants/defaultOptions');
|
||||
const { devDependencies } = require('../../package.json');
|
||||
|
||||
/*
|
||||
* Default options for browser worker
|
||||
* Default options for browser environment
|
||||
*/
|
||||
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`,
|
||||
? resolveURL('/node_modules/@ffmpeg/core/dist/ffmpeg-core.js')
|
||||
: `https://unpkg.com/@ffmpeg/core@v${devDependencies['@ffmpeg/core'].substring(1)}/ffmpeg-core.js`,
|
||||
};
|
||||
|
@ -1,12 +1,5 @@
|
||||
const resolveURL = require('resolve-url');
|
||||
|
||||
/**
|
||||
* readFromBlobOrFile
|
||||
*
|
||||
* @name readFromBlobOrFile
|
||||
* @function
|
||||
* @access private
|
||||
*/
|
||||
const readFromBlobOrFile = (blob) => (
|
||||
new Promise((resolve, reject) => {
|
||||
const fileReader = new FileReader();
|
||||
@ -23,19 +16,21 @@ const readFromBlobOrFile = (blob) => (
|
||||
module.exports = async (_data) => {
|
||||
let data = _data;
|
||||
if (typeof _data === 'undefined') {
|
||||
return 'undefined';
|
||||
return new Uint8Array();
|
||||
}
|
||||
|
||||
if (typeof _data === 'string') {
|
||||
// Base64 _data
|
||||
/* From base64 format */
|
||||
if (/data:_data\/([a-zA-Z]*);base64,([^"]*)/.test(_data)) {
|
||||
data = atob(_data.split(',')[1])
|
||||
.split('')
|
||||
.map((c) => c.charCodeAt(0));
|
||||
/* From remote server/URL */
|
||||
} else {
|
||||
const res = await fetch(resolveURL(_data));
|
||||
data = await res.arrayBuffer();
|
||||
}
|
||||
/* From Blob or File */
|
||||
} else if (_data instanceof File || _data instanceof Blob) {
|
||||
data = await readFromBlobOrFile(_data);
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
const resolveURL = require('resolve-url');
|
||||
const { log } = require('../utils/log');
|
||||
|
||||
module.exports = async ({ corePath }) => {
|
||||
if (typeof window.Module === 'undefined') {
|
||||
module.exports = async ({ corePath: _corePath }) => {
|
||||
if (typeof window.createFFmpegCore === 'undefined') {
|
||||
log('info', 'fetch ffmpeg-core.worker.js script');
|
||||
const corePath = resolveURL(_corePath);
|
||||
const workerBlob = await (await fetch(corePath.replace('ffmpeg-core.js', 'ffmpeg-core.worker.js'))).blob();
|
||||
window.FFMPEG_CORE_WORKER_SCRIPT = URL.createObjectURL(workerBlob);
|
||||
log('info', `worker object URL=${window.FFMPEG_CORE_WORKER_SCRIPT}`);
|
||||
@ -12,10 +14,7 @@ module.exports = async ({ corePath }) => {
|
||||
const eventHandler = () => {
|
||||
script.removeEventListener('load', eventHandler);
|
||||
log('info', 'initialize ffmpeg-core');
|
||||
window.Module.onRuntimeInitialized = () => {
|
||||
log('info', 'ffmpeg-core initialized');
|
||||
resolve(window.Module);
|
||||
};
|
||||
resolve(window.createFFmpegCore);
|
||||
};
|
||||
script.src = corePath;
|
||||
script.type = 'text/javascript';
|
||||
@ -24,5 +23,5 @@ module.exports = async ({ corePath }) => {
|
||||
});
|
||||
}
|
||||
log('info', 'ffmpeg-core is loaded already');
|
||||
return Promise.resolve(window.Module);
|
||||
return Promise.resolve(window.createFFmpegCore);
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
const defaultOptions = require('./defaultOptions');
|
||||
const getModule = require('./getModule');
|
||||
const getCreateFFmpegCore = require('./getCreateFFmpegCore');
|
||||
const fetchFile = require('./fetchFile');
|
||||
|
||||
module.exports = {
|
||||
defaultOptions,
|
||||
getModule,
|
||||
getCreateFFmpegCore,
|
||||
fetchFile,
|
||||
};
|
||||
|
52
src/config.js
Normal file
52
src/config.js
Normal file
@ -0,0 +1,52 @@
|
||||
module.exports = {
|
||||
defaultArgs: [
|
||||
/* args[0] is always the binary path */
|
||||
'./ffmpeg',
|
||||
/* Disable interaction mode */
|
||||
'-nostdin',
|
||||
/* Force to override output file */
|
||||
'-y',
|
||||
/* Not to output banner */
|
||||
'-hide_banner',
|
||||
],
|
||||
baseOptions: {
|
||||
/* Flag to turn on/off log messages in console */
|
||||
log: false,
|
||||
/*
|
||||
* Custom logger to get ffmpeg.wasm output messages.
|
||||
* a sample logger looks like this:
|
||||
*
|
||||
* ```
|
||||
* logger = ({ type, message }) => {
|
||||
* console.log(type, message);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* type can be one of following:
|
||||
*
|
||||
* info: internal workflow debug messages
|
||||
* fferr: ffmpeg native stderr output
|
||||
* ffout: ffmpeg native stdout output
|
||||
*/
|
||||
logger: () => {},
|
||||
/*
|
||||
* Progress handler to get current progress of ffmpeg command.
|
||||
* a sample progress handler looks like this:
|
||||
*
|
||||
* ```
|
||||
* progress = ({ ratio }) => {
|
||||
* console.log(ratio);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ratio is a float number between 0 to 1.
|
||||
*/
|
||||
progress: () => {},
|
||||
/*
|
||||
* Path to find/download ffmpeg.wasm-core,
|
||||
* this value should be overwriten by `defaultOptions` in
|
||||
* each environment.
|
||||
*/
|
||||
corePath: '',
|
||||
},
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
module.exports = [
|
||||
'./ffmpeg', // args[0] is always binary path
|
||||
'-nostdin', // Disable interaction mode
|
||||
'-hide_banner', // Not to output banner
|
||||
];
|
@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
log: false,
|
||||
logger: () => {},
|
||||
progress: () => {},
|
||||
};
|
@ -1,21 +1,14 @@
|
||||
const defaultArgs = require('./constants/defaultArgs');
|
||||
const { setLogging, log } = require('./utils/log');
|
||||
const resolvePaths = require('./utils/resolvePaths');
|
||||
const { defaultArgs, baseOptions } = require('./config');
|
||||
const { setLogging, setCustomLogger, log } = require('./utils/log');
|
||||
const parseProgress = require('./utils/parseProgress');
|
||||
const stringList2pointer = require('./utils/stringList2pointer');
|
||||
const parseArgs = require('./utils/parseArgs');
|
||||
const {
|
||||
defaultOptions,
|
||||
getModule,
|
||||
fetchFile,
|
||||
} = require('./node');
|
||||
const { defaultOptions, getCreateFFmpegCore } = 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;
|
||||
const NO_LOAD = Error('ffmpeg.wasm is not ready, make sure you have completed load().');
|
||||
|
||||
module.exports = (_options = {}) => {
|
||||
let Core = null;
|
||||
let ffmpeg = null;
|
||||
let runResolve = null;
|
||||
let running = false;
|
||||
const {
|
||||
@ -23,109 +16,134 @@ module.exports = (_options = {}) => {
|
||||
logger,
|
||||
progress,
|
||||
...options
|
||||
} = resolvePaths({
|
||||
} = {
|
||||
...baseOptions,
|
||||
...defaultOptions,
|
||||
..._options,
|
||||
});
|
||||
const detectCompletion = ({ message, type }) => {
|
||||
if (type === 'ffmpeg-stdout'
|
||||
&& message === 'FFMPEG_END'
|
||||
&& runResolve !== null) {
|
||||
};
|
||||
const detectCompletion = (message) => {
|
||||
if (message === 'FFMPEG_END' && runResolve !== null) {
|
||||
runResolve();
|
||||
runResolve = null;
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
const parseMessage = ({ type, message }) => {
|
||||
log(type, message);
|
||||
parseProgress(message, progress);
|
||||
detectCompletion(message);
|
||||
};
|
||||
|
||||
setLogging(logging);
|
||||
|
||||
/*
|
||||
* Load ffmpeg.wasm-core script.
|
||||
* In browser environment, the ffmpeg.wasm-core script is fetch from
|
||||
* CDN and can be assign to a local path by assigning `corePath`.
|
||||
* In node environment, we use dynamic require and the default `corePath`
|
||||
* is `$ffmpeg/core`.
|
||||
*
|
||||
* Typically the load() func might take few seconds to minutes to complete,
|
||||
* better to do it as early as possible.
|
||||
*
|
||||
*/
|
||||
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 (Core === null) {
|
||||
log('info', 'loading ffmpeg-core');
|
||||
const createFFmpegCore = await getCreateFFmpegCore(options);
|
||||
Core = await createFFmpegCore({
|
||||
printErr: (message) => parseMessage({ type: 'fferr', message }),
|
||||
print: (message) => parseMessage({ type: 'ffout', message }),
|
||||
});
|
||||
if (ffmpeg === null) {
|
||||
ffmpeg = Module.cwrap('proxy_main', 'number', ['number', 'number']);
|
||||
}
|
||||
ffmpeg = Core.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);
|
||||
throw Error('ffmpeg.wasm was loaded, you should not load it again, use ffmpeg.isLoaded() to check next time.');
|
||||
}
|
||||
};
|
||||
|
||||
const write = async (path, data) => (
|
||||
FS('writeFile', [path, await fetchFile(data)])
|
||||
);
|
||||
|
||||
const writeText = (path, text) => (
|
||||
FS('writeFile', [path, text])
|
||||
);
|
||||
/*
|
||||
* Determine whether the Core is loaded.
|
||||
*/
|
||||
const isLoaded = () => Core !== null;
|
||||
|
||||
const read = (path) => (
|
||||
FS('readFile', [path])
|
||||
);
|
||||
|
||||
const remove = (path) => (
|
||||
FS('unlink', [path])
|
||||
);
|
||||
|
||||
const ls = (path) => (
|
||||
FS('readdir', [path])
|
||||
);
|
||||
|
||||
const run = (_args) => {
|
||||
if (ffmpeg === null) {
|
||||
/*
|
||||
* Run ffmpeg command.
|
||||
* This is the major function in ffmpeg.wasm, you can just imagine it
|
||||
* as ffmpeg native cli and what you need to pass is the same.
|
||||
*
|
||||
* For example, you can convert native command below:
|
||||
*
|
||||
* ```
|
||||
* $ ffmpeg -i video.avi -c:v libx264 video.mp4
|
||||
* ```
|
||||
*
|
||||
* To
|
||||
*
|
||||
* ```
|
||||
* await ffmpeg.run('-i', 'video.avi', '-c:v', 'libx264', 'video.mp4');
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
const run = (..._args) => {
|
||||
log('info', `run ffmpeg command: ${_args.join(' ')}`);
|
||||
if (Core === null) {
|
||||
throw NO_LOAD;
|
||||
} else if (running) {
|
||||
throw NO_MULTIPLE_RUN;
|
||||
throw Error('ffmpeg.wasm can only run one command at a time');
|
||||
} else {
|
||||
running = true;
|
||||
return new Promise((resolve) => {
|
||||
const args = [...defaultArgs, ...parseArgs(_args)].filter((s) => s.length !== 0);
|
||||
log('info', `ffmpeg command: ${args.join(' ')}`);
|
||||
const args = [...defaultArgs, ..._args].filter((s) => s.length !== 0);
|
||||
runResolve = resolve;
|
||||
ffmpeg(args.length, stringList2pointer(Module, args));
|
||||
ffmpeg(...parseArgs(Core, 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}`);
|
||||
/*
|
||||
* Run FS operations.
|
||||
* For input/output file of ffmpeg.wasm, it is required to save them to MEMFS
|
||||
* first so that ffmpeg.wasm is able to consume them. Here we rely on the FS
|
||||
* methods provided by Emscripten.
|
||||
*
|
||||
* Common methods to use are:
|
||||
* ffmpeg.FS('writeFile', 'video.avi', new Uint8Array(...)): writeFile writes
|
||||
* data to MEMFS. You need to use Uint8Array for binary data.
|
||||
* ffmpeg.FS('readFile', 'video.mp4'): readFile from MEMFS.
|
||||
* ffmpeg.FS('unlink', 'video.map'): delete file from MEMFS.
|
||||
*
|
||||
* For more info, check https://emscripten.org/docs/api_reference/Filesystem-API.html
|
||||
*
|
||||
*/
|
||||
const FS = (method, ...args) => {
|
||||
log('info', `run FS.${method} ${args.map((arg) => (typeof arg === 'string' ? arg : `<${arg.length} bytes binary file>`)).join(' ')}`);
|
||||
if (Core === null) {
|
||||
throw NO_LOAD;
|
||||
} else {
|
||||
let ret = null;
|
||||
try {
|
||||
ret = Core.FS[method](...args);
|
||||
} catch (e) {
|
||||
if (method === 'readdir') {
|
||||
throw Error(`ffmpeg.FS('readdir', '${args[0]}') error. Check if the path exists, ex: ffmpeg.FS('readdir', '/')`);
|
||||
} else if (method === 'readFile') {
|
||||
throw Error(`ffmpeg.FS('readFile', '${args[0]}') error. Check if the path exists`);
|
||||
} else {
|
||||
throw Error('Oops, something went wrong in FS operation.');
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
setLogging(logging);
|
||||
setCustomLogger(logger);
|
||||
|
||||
return {
|
||||
load,
|
||||
FS,
|
||||
write,
|
||||
writeText,
|
||||
read,
|
||||
remove,
|
||||
ls,
|
||||
isLoaded,
|
||||
run,
|
||||
transcode,
|
||||
trim,
|
||||
concatDemuxer,
|
||||
FS,
|
||||
};
|
||||
};
|
||||
|
30
src/index.js
30
src/index.js
@ -1,6 +1,36 @@
|
||||
require('regenerator-runtime/runtime');
|
||||
const createFFmpeg = require('./createFFmpeg');
|
||||
const { fetchFile } = require('./node');
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
* Create ffmpeg instance.
|
||||
* Each ffmpeg instance owns an isolated MEMFS and works
|
||||
* independently.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* const ffmpeg = createFFmpeg({
|
||||
* log: true,
|
||||
* logger: () => {},
|
||||
* progress: () => {},
|
||||
* corePath: '',
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* For the usage of these four arguments, check config.js
|
||||
*
|
||||
*/
|
||||
createFFmpeg,
|
||||
/*
|
||||
* Helper function for fetching files from various resource.
|
||||
* Sometimes the video/audio file you want to process may located
|
||||
* in a remote URL and somewhere in your local file system.
|
||||
*
|
||||
* This helper function helps you to fetch to file and return an
|
||||
* Uint8Array variable for ffmpeg.wasm to consume.
|
||||
*
|
||||
*/
|
||||
fetchFile,
|
||||
};
|
||||
|
@ -1,8 +1,6 @@
|
||||
const defaultOptions = require('../constants/defaultOptions');
|
||||
|
||||
/*
|
||||
* Default options for node environment
|
||||
*/
|
||||
module.exports = {
|
||||
...defaultOptions,
|
||||
corePath: '@ffmpeg/core',
|
||||
};
|
||||
|
@ -10,14 +10,21 @@ module.exports = async (_data) => {
|
||||
}
|
||||
|
||||
if (typeof _data === 'string') {
|
||||
if (isURL(_data) || _data.startsWith('chrome-extension://') || _data.startsWith('file://')) {
|
||||
/* From remote URL/server */
|
||||
if (isURL(_data)
|
||||
|| _data.startsWith('moz-extension://')
|
||||
|| _data.startsWith('chrome-extension://')
|
||||
|| _data.startsWith('file://')) {
|
||||
const res = await fetch(_data);
|
||||
data = await res.arrayBuffer();
|
||||
/* From base64 format */
|
||||
} else if (/data:_data\/([a-zA-Z]*);base64,([^"]*)/.test(_data)) {
|
||||
data = Buffer.from(_data.split(',')[1], 'base64');
|
||||
/* From local file path */
|
||||
} else {
|
||||
data = await util.promisify(fs.readFile)(_data);
|
||||
}
|
||||
/* From Buffer */
|
||||
} else if (Buffer.isBuffer(_data)) {
|
||||
data = _data;
|
||||
}
|
||||
|
7
src/node/getCreateFFmpegCore.js
Normal file
7
src/node/getCreateFFmpegCore.js
Normal file
@ -0,0 +1,7 @@
|
||||
const { log } = require('../utils/log');
|
||||
|
||||
module.exports = ({ corePath }) => new Promise((resolve) => {
|
||||
log('info', `fetch ffmpeg.wasm-core script from ${corePath}`);
|
||||
// eslint-disable-next-line import/no-dynamic-require
|
||||
resolve(require(corePath));
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
module.exports = () => new Promise((resolve) => {
|
||||
const Module = require('@ffmpeg/core');
|
||||
Module.onRuntimeInitialized = () => {
|
||||
resolve(Module);
|
||||
};
|
||||
});
|
@ -1,9 +1,9 @@
|
||||
const defaultOptions = require('./defaultOptions');
|
||||
const getModule = require('./getModule');
|
||||
const getCreateFFmpegCore = require('./getCreateFFmpegCore');
|
||||
const fetchFile = require('./fetchFile');
|
||||
|
||||
module.exports = {
|
||||
defaultOptions,
|
||||
getModule,
|
||||
getCreateFFmpegCore,
|
||||
fetchFile,
|
||||
};
|
||||
|
@ -1,21 +0,0 @@
|
||||
const isElectron = require('is-electron');
|
||||
|
||||
module.exports = (key) => {
|
||||
const env = {};
|
||||
|
||||
if (isElectron()) {
|
||||
env.type = 'electron';
|
||||
} else if (typeof window === 'object') {
|
||||
env.type = 'browser';
|
||||
} else if (typeof importScripts === 'function') {
|
||||
env.type = 'webworker';
|
||||
} else if (typeof process === 'object' && typeof require === 'function') {
|
||||
env.type = 'node';
|
||||
}
|
||||
|
||||
if (typeof key === 'undefined') {
|
||||
return env;
|
||||
}
|
||||
|
||||
return env[key];
|
||||
};
|
@ -1,9 +1,24 @@
|
||||
let logging = false;
|
||||
let customLogger = () => {};
|
||||
|
||||
exports.logging = logging;
|
||||
|
||||
exports.setLogging = (_logging) => {
|
||||
const setLogging = (_logging) => {
|
||||
logging = _logging;
|
||||
};
|
||||
|
||||
exports.log = (type, message) => (logging ? console.log(`[${type}] ${message}`) : null);
|
||||
const setCustomLogger = (logger) => {
|
||||
customLogger = logger;
|
||||
};
|
||||
|
||||
const log = (type, message) => {
|
||||
customLogger({ type, message });
|
||||
if (logging) {
|
||||
console.log(`[${type}] ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
logging,
|
||||
setLogging,
|
||||
setCustomLogger,
|
||||
log,
|
||||
};
|
||||
|
@ -1,51 +1,9 @@
|
||||
module.exports = (cmd) => {
|
||||
const args = [];
|
||||
let nextDelimiter = 0;
|
||||
let prevDelimiter = 0;
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((nextDelimiter = cmd.indexOf(' ', prevDelimiter)) >= 0) {
|
||||
let arg = cmd.substring(prevDelimiter, nextDelimiter);
|
||||
let quoteIdx = arg.indexOf('\'');
|
||||
let dblQuoteIdx = arg.indexOf('"');
|
||||
|
||||
if (quoteIdx === 0 || dblQuoteIdx === 0) {
|
||||
/* The argument has a quote at the start i.e, 'id=0,streams=0 id=1,streams=1' */
|
||||
const delimiter = arg[0];
|
||||
const endDelimiter = cmd.indexOf(delimiter, prevDelimiter + 1);
|
||||
|
||||
if (endDelimiter < 0) {
|
||||
throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`);
|
||||
}
|
||||
|
||||
arg = cmd.substring(prevDelimiter + 1, endDelimiter);
|
||||
prevDelimiter = endDelimiter + 2;
|
||||
args.push(arg);
|
||||
} else if (quoteIdx > 0 || dblQuoteIdx > 0) {
|
||||
/* The argument has a quote in it, it must be ended correctly i,e. title='test' */
|
||||
if (quoteIdx === -1) quoteIdx = Infinity;
|
||||
if (dblQuoteIdx === -1) dblQuoteIdx = Infinity;
|
||||
const delimiter = (quoteIdx < dblQuoteIdx) ? '\'' : '"';
|
||||
const quoteOffset = Math.min(quoteIdx, dblQuoteIdx);
|
||||
const endDelimiter = cmd.indexOf(delimiter, prevDelimiter + quoteOffset + 1);
|
||||
|
||||
if (endDelimiter < 0) {
|
||||
throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`);
|
||||
}
|
||||
|
||||
arg = cmd.substring(prevDelimiter, endDelimiter + 1);
|
||||
prevDelimiter = endDelimiter + 2;
|
||||
args.push(arg);
|
||||
} else if (arg !== '') {
|
||||
args.push(arg);
|
||||
prevDelimiter = nextDelimiter + 1;
|
||||
} else {
|
||||
prevDelimiter = nextDelimiter + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevDelimiter !== cmd.length) {
|
||||
args.push(cmd.substring(prevDelimiter));
|
||||
}
|
||||
|
||||
return args;
|
||||
module.exports = (Core, args) => {
|
||||
const argsPtr = Core._malloc(args.length * Uint32Array.BYTES_PER_ELEMENT);
|
||||
args.forEach((s, idx) => {
|
||||
const buf = Core._malloc(s.length + 1);
|
||||
Core.writeAsciiToMemory(s, buf);
|
||||
Core.setValue(argsPtr + (Uint32Array.BYTES_PER_ELEMENT * idx), buf, 'i32');
|
||||
});
|
||||
return [args.length, argsPtr];
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ const ts2sec = (ts) => {
|
||||
return (parseFloat(h) * 60 * 60) + (parseFloat(m) * 60) + parseFloat(s);
|
||||
};
|
||||
|
||||
module.exports = ({ message }, progress) => {
|
||||
module.exports = (message, progress) => {
|
||||
if (typeof message === 'string') {
|
||||
if (message.startsWith(' Duration')) {
|
||||
const ts = message.split(', ')[0].split(': ')[1];
|
||||
@ -19,6 +19,7 @@ module.exports = ({ message }, progress) => {
|
||||
progress({ ratio: t / duration });
|
||||
} else if (message.startsWith('video:')) {
|
||||
progress({ ratio: 1 });
|
||||
duration = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,12 +0,0 @@
|
||||
const isBrowser = require('./getEnvironment')('type') === 'browser';
|
||||
const resolveURL = isBrowser ? require('resolve-url') : s => s; // eslint-disable-line
|
||||
|
||||
module.exports = (options) => {
|
||||
const opts = { ...options };
|
||||
['corePath'].forEach((key) => {
|
||||
if (typeof options[key] !== 'undefined') {
|
||||
opts[key] = resolveURL(opts[key]);
|
||||
}
|
||||
});
|
||||
return opts;
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
module.exports = (Module, s) => {
|
||||
const ptr = Module._malloc((s.length + 1) * Uint8Array.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < s.length; i += 1) {
|
||||
Module.setValue(ptr + i, s.charCodeAt(i), 'i8');
|
||||
}
|
||||
Module.setValue(ptr + s.length, 0, 'i8');
|
||||
return ptr;
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
const string2pointer = require('./string2pointer');
|
||||
|
||||
module.exports = (Module, strList) => {
|
||||
const listPtr = Module._malloc(strList.length * Uint32Array.BYTES_PER_ELEMENT);
|
||||
|
||||
strList.forEach((s, idx) => {
|
||||
const strPtr = string2pointer(Module, s);
|
||||
Module.setValue(listPtr + (4 * idx), strPtr, 'i32');
|
||||
});
|
||||
|
||||
return listPtr;
|
||||
};
|
Loading…
Reference in New Issue
Block a user