diff --git a/.gitignore b/.gitignore index b7b5d21..064213f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist /.nyc_output +.DS_Store \ No newline at end of file diff --git a/src/worker-script/index.js b/src/worker-script/index.js index b94eb59..e195c39 100644 --- a/src/worker-script/index.js +++ b/src/worker-script/index.js @@ -46,38 +46,54 @@ const FS = ({ }; const parseArgs = (command) => { - let args = []; + const args = []; let nextDelimiter = 0; let prevDelimiter = 0; - while((nextDelimiter = command.indexOf(' ', prevDelimiter)) >= 0) { - let arg = command.substring(prevDelimiter, nextDelimiter) + while ((nextDelimiter = command.indexOf(' ', prevDelimiter)) >= 0) { + let arg = command.substring(prevDelimiter, nextDelimiter); + let quoteIndex = arg.indexOf('\''); + let doubleQuoteIndex = arg.indexOf('"'); - if (arg[0] === '\'' || arg[0] === '\"') { + if (quoteIndex === 0 || doubleQuoteIndex === 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 = command.indexOf(delimeter, prevDelimiter + 1); + const endDelimiter = command.indexOf(delimiter, prevDelimiter + 1); - if (endDelimiter < 0) throw `Bad command espcape sequence ${delimeter} near ${nextDelimiter}` - - arg = command.substring(prevDelimiter+1, endDelimiter); - prevDelimiter = endDelimiter + 2; - } - else { - prevDelimiter = nextDelimiter + 1; - - if (arg === "") { - continue; + if (endDelimiter < 0) { + throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`); } - } - args.push(arg) + arg = command.substring(prevDelimiter + 1, endDelimiter); + prevDelimiter = endDelimiter + 2; + args.push(arg); + } else if (quoteIndex > 0 || doubleQuoteIndex > 0) { + /* The argument has a quote in it, it must be ended correctly i,e. title='test' */ + if (quoteIndex === -1) quoteIndex = Infinity; + if (doubleQuoteIndex === -1) doubleQuoteIndex = Infinity; + const delimiter = (quoteIndex < doubleQuoteIndex) ? '\'' : '"'; + const endDelimiter = command.indexOf(delimiter, prevDelimiter + Math.min(quoteIndex, doubleQuoteIndex) + 1); + + if (endDelimiter < 0) { + throw new Error(`Bad command escape sequence ${delimiter} near ${nextDelimiter}`); + } + + arg = command.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 != command.length) { - args.push(command.substring(prevDelimiter)) + if (prevDelimiter !== command.length) { + args.push(command.substring(prevDelimiter)); } return args; -} +}; const run = ({ payload: { diff --git a/tests/constants.js b/tests/constants.js index af74d63..5d3eb39 100644 --- a/tests/constants.js +++ b/tests/constants.js @@ -4,8 +4,10 @@ const IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== ' const OPTIONS = { corePath: '../node_modules/@ffmpeg/core/ffmpeg-core.js', ...(IS_BROWSER ? { workerPath: '../dist/worker.dev.js' } : {}), + logger: ({ message }) => console.log(message), }; const FLAME_MP4_LENGTH = 100374; +const META_FLAME_MP4_LENGTH = 100408; if (typeof module !== 'undefined') { module.exports = { @@ -14,5 +16,6 @@ if (typeof module !== 'undefined') { IS_BROWSER, OPTIONS, FLAME_MP4_LENGTH, + META_FLAME_MP4_LENGTH, }; } diff --git a/tests/ffmpeg.test.js b/tests/ffmpeg.test.js index 56258e9..ce33ea9 100644 --- a/tests/ffmpeg.test.js +++ b/tests/ffmpeg.test.js @@ -18,3 +18,27 @@ describe('transcode()', () => { )); }); }); + +describe('run()', () => { + describe('should run a command with quoted parameters at start and a space in between', () => { + ['flame.avi'].forEach((name) => ( + it(`run ${name}`, async () => { + await worker.write(name, `${BASE_URL}/${name}`); + await worker.run(`-y -i ${name} -metadata 'title="my title"' output.mp4`); + const { data } = await worker.read('output.mp4'); + expect(data.length).to.be(META_FLAME_MP4_LENGTH); + }).timeout(TIMEOUT) + )); + }); + + describe('should run a command with name quoted parameters and a space in between', () => { + ['flame.avi'].forEach((name) => ( + it(`run ${name}`, async () => { + await worker.write(name, `${BASE_URL}/${name}`); + await worker.run(`-y -i ${name} -metadata title="my title" output.mp4`); + const { data } = await worker.read('output.mp4'); + expect(data.length).to.be(META_FLAME_MP4_LENGTH); + }).timeout(TIMEOUT) + )); + }); +});