const strtok3 = require('strtok3'); const { getOneRawFrame, encodeLiveRawStream } = require('./ffmpeg'); let aborters = []; async function command({ path, inWidth, inHeight, streamIndex, seekTo: commandedTime, onFrame, playing }) { let process; let aborted = false; function killProcess() { if (process) { process.kill(); process = undefined; } } function abort() { aborted = true; killProcess(); aborters = aborters.filter(((aborter) => aborter !== abort)); } aborters.push(abort); try { if (playing) { const { process: processIn, channels, width, height } = encodeLiveRawStream({ path, inWidth, inHeight, streamIndex, seekTo: commandedTime }); process = processIn; // process.stderr.on('data', data => console.log(data.toString('utf-8'))); const tokenizer = await strtok3.fromStream(process.stdout); if (aborted) return; const size = width * height * channels; const rgbaImage = Buffer.allocUnsafe(size); while (!aborted) { // eslint-disable-next-line no-await-in-loop await tokenizer.readBuffer(rgbaImage, { length: size }); if (aborted) return; onFrame(rgbaImage, width, height); } } else { const { process: processIn, width, height } = getOneRawFrame({ path, inWidth, inHeight, streamIndex, seekTo: commandedTime, outSize: 1000 }); process = processIn; const { stdout: rgbaImage } = await process; if (aborted) return; onFrame(rgbaImage, width, height); } } catch (err) { if (!err.killed) console.warn(err.message); } finally { killProcess(); } } function abortAll() { aborters.forEach((aborter) => aborter()); } module.exports = { command, abortAll, };