Browse Source

add more logging (timing)

layer-manipulation
Mikael Finstad 6 years ago
parent
commit
75322d4aff
  1. 21
      index.js
  2. 11
      sources/frameSource.js

21
index.js

@ -26,6 +26,7 @@ module.exports = async (config = {}) => {
// Testing options: // Testing options:
enableFfmpegLog = false, enableFfmpegLog = false,
verbose = false, verbose = false,
logTimes = false,
fast, fast,
outPath, outPath,
@ -423,7 +424,7 @@ module.exports = async (config = {}) => {
const getTransitionFromClip = () => clips[transitionFromClipId]; const getTransitionFromClip = () => clips[transitionFromClipId];
const getTransitionToClip = () => clips[getTransitionToClipId()]; const getTransitionToClip = () => clips[getTransitionToClipId()];
const getSource = async (clip, clipIndex) => createFrameSource({ clip, clipIndex, width, height, channels, verbose, ffmpegPath, ffprobePath, enableFfmpegLog, framerateStr });
const getSource = async (clip, clipIndex) => createFrameSource({ clip, clipIndex, width, height, channels, verbose, logTimes, ffmpegPath, ffprobePath, enableFfmpegLog, framerateStr });
const getTransitionFromSource = async () => getSource(getTransitionFromClip(), transitionFromClipId); const getTransitionFromSource = async () => getSource(getTransitionFromClip(), transitionFromClipId);
const getTransitionToSource = async () => (getTransitionToClip() && getSource(getTransitionToClip(), getTransitionToClipId())); const getTransitionToSource = async () => (getTransitionToClip() && getSource(getTransitionToClip(), getTransitionToClipId()));
@ -497,7 +498,9 @@ module.exports = async (config = {}) => {
continue; continue;
} }
if (logTimes) console.time('Read frameSource1');
const newFrameSource1Data = await frameSource1.readNextFrame({ time: fromClipTime }); const newFrameSource1Data = await frameSource1.readNextFrame({ time: fromClipTime });
if (logTimes) console.timeEnd('Read frameSource1');
// If we got no data, use the old data // If we got no data, use the old data
// TODO maybe abort? // TODO maybe abort?
if (newFrameSource1Data) frameSource1Data = newFrameSource1Data; if (newFrameSource1Data) frameSource1Data = newFrameSource1Data;
@ -506,16 +509,19 @@ module.exports = async (config = {}) => {
const isInTransition = frameSource2 && transitionNumFramesSafe > 0 && transitionFrameAt >= 0; const isInTransition = frameSource2 && transitionNumFramesSafe > 0 && transitionFrameAt >= 0;
let outFrameData; let outFrameData;
if (isInTransition) { if (isInTransition) {
if (logTimes) console.time('Read frameSource2');
const frameSource2Data = await frameSource2.readNextFrame({ time: toClipTime }); const frameSource2Data = await frameSource2.readNextFrame({ time: toClipTime });
if (logTimes) console.timeEnd('Read frameSource2');
if (frameSource2Data) { if (frameSource2Data) {
const progress = transitionFrameAt / transitionNumFramesSafe; const progress = transitionFrameAt / transitionNumFramesSafe;
const easedProgress = currentTransition.easingFunction(progress); const easedProgress = currentTransition.easingFunction(progress);
// if (verbose) console.time('runTransitionOnFrame');
if (logTimes) console.time('runTransitionOnFrame');
outFrameData = runTransitionOnFrame({ fromFrame: frameSource1Data, toFrame: frameSource2Data, progress: easedProgress, transitionName: currentTransition.name, transitionParams: currentTransition.params }); outFrameData = runTransitionOnFrame({ fromFrame: frameSource1Data, toFrame: frameSource2Data, progress: easedProgress, transitionName: currentTransition.name, transitionParams: currentTransition.params });
// if (verbose) console.timeEnd('runTransitionOnFrame');
if (logTimes) console.timeEnd('runTransitionOnFrame');
} else { } else {
console.warn('Got no frame data from transitionToClip!'); console.warn('Got no frame data from transitionToClip!');
// We have probably reached end of clip2 but transition is not complete. Just pass thru clip1 // We have probably reached end of clip2 but transition is not complete. Just pass thru clip1
@ -529,10 +535,17 @@ module.exports = async (config = {}) => {
if (verbose) { if (verbose) {
if (isInTransition) console.log('Writing frame:', totalFramesWritten, 'from clip', transitionFromClipId, `(frame ${fromClipFrameAt})`, 'to clip', getTransitionToClipId(), `(frame ${toClipFrameAt} / ${transitionNumFramesSafe})`, currentTransition.name, `${currentTransition.duration}s`); if (isInTransition) console.log('Writing frame:', totalFramesWritten, 'from clip', transitionFromClipId, `(frame ${fromClipFrameAt})`, 'to clip', getTransitionToClipId(), `(frame ${toClipFrameAt} / ${transitionNumFramesSafe})`, currentTransition.name, `${currentTransition.duration}s`);
else console.log('Writing frame:', totalFramesWritten, 'from clip', transitionFromClipId, `(frame ${fromClipFrameAt})`); else console.log('Writing frame:', totalFramesWritten, 'from clip', transitionFromClipId, `(frame ${fromClipFrameAt})`);
// console.log(outFrameData.length / 1e6, 'MB');
} }
const nullOutput = false;
if (logTimes) console.time('outProcess.write');
// If we don't wait, then we get EINVAL when dealing with high resolution files (big writes) // If we don't wait, then we get EINVAL when dealing with high resolution files (big writes)
await new Promise((r) => outProcess.stdin.write(outFrameData, r));
if (!nullOutput) await new Promise((r) => outProcess.stdin.write(outFrameData, r));
if (logTimes) console.timeEnd('outProcess.write');
if (outProcessError) break; if (outProcessError) break;

11
sources/frameSource.js

@ -21,7 +21,7 @@ const fabricFrameSources = {
'slide-in-text': slideInTextFrameSource, 'slide-in-text': slideInTextFrameSource,
}; };
async function createFrameSource({ clip, clipIndex, width, height, channels, verbose, ffmpegPath, ffprobePath, enableFfmpegLog, framerateStr }) {
async function createFrameSource({ clip, clipIndex, width, height, channels, verbose, logTimes, ffmpegPath, ffprobePath, enableFfmpegLog, framerateStr }) {
const { layers, duration } = clip; const { layers, duration } = clip;
const visualLayers = layers.filter((layer) => layer.type !== 'audio'); const visualLayers = layers.filter((layer) => layer.type !== 'audio');
@ -58,14 +58,18 @@ async function createFrameSource({ clip, clipIndex, width, height, channels, ver
const shouldDrawLayer = offsetProgress >= 0 && offsetProgress <= 1; const shouldDrawLayer = offsetProgress >= 0 && offsetProgress <= 1;
if (shouldDrawLayer) { if (shouldDrawLayer) {
if (logTimes) console.time('frameSource.readNextFrame');
const rgba = await frameSource.readNextFrame(offsetProgress, canvas); const rgba = await frameSource.readNextFrame(offsetProgress, canvas);
if (logTimes) console.timeEnd('frameSource.readNextFrame');
// Frame sources can either render to the provided canvas and return nothing // Frame sources can either render to the provided canvas and return nothing
// OR return an raw RGBA blob which will be drawn onto the canvas // OR return an raw RGBA blob which will be drawn onto the canvas
if (rgba) { if (rgba) {
// Optimization: Don't need to draw to canvas if there's only one layer // Optimization: Don't need to draw to canvas if there's only one layer
if (layerFrameSources.length === 1) return rgba; if (layerFrameSources.length === 1) return rgba;
if (logTimes) console.time('rgbaToFabricImage');
const img = await rgbaToFabricImage({ width, height, rgba }); const img = await rgbaToFabricImage({ width, height, rgba });
if (logTimes) console.timeEnd('rgbaToFabricImage');
canvas.add(img); canvas.add(img);
} else { } else {
// Assume this frame source has drawn its content to the canvas // Assume this frame source has drawn its content to the canvas
@ -74,7 +78,10 @@ async function createFrameSource({ clip, clipIndex, width, height, channels, ver
} }
// if (verbose) console.time('Merge frames'); // if (verbose) console.time('Merge frames');
return renderFabricCanvas(canvas);
if (logTimes) console.time('renderFabricCanvas');
const rgba = await renderFabricCanvas(canvas);
if (logTimes) console.timeEnd('renderFabricCanvas');
return rgba;
} }
async function close() { async function close() {

Loading…
Cancel
Save