browsertime
Version:
Get performance metrics from your web page using Browsertime.
167 lines (149 loc) • 4.51 kB
JavaScript
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { execa } from 'execa';
import intel from 'intel';
import get from 'lodash.get';
import { readFile, removeFile, copyFile } from '../../../support/fileUtil.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const log = intel.getLogger('browsertime.video');
const SCRIPT_PATH = path.join(
__dirname,
'..',
'..',
'..',
'..',
'visualmetrics',
'visualmetrics.py'
);
const PORTABLE_SCRIPT_PATH = path.join(
__dirname,
'..',
'..',
'..',
'..',
'visualmetrics',
'visualmetrics-portable.py'
);
function getScript(options) {
if (options.visualMetricsPortable) {
log.info('Use the visual metrics portable script');
return PORTABLE_SCRIPT_PATH;
}
return SCRIPT_PATH;
}
export async function checkDependencies(options) {
return execa(process.env.PYTHON || 'python', [getScript(options), '--check']);
}
export async function run(
videoPath,
imageDirPath,
elementsFile,
videoDir,
index,
pageNumber,
visitedPageNumber,
options
) {
const filmstripQuality = get(options, 'videoParams.filmstripQuality', 75);
const createFilmstrip = get(options, 'videoParams.createFilmstrip', true);
const fullSizeFilmstrip = get(
options,
'videoParams.filmstripFullSize',
false
);
const thumbsize = get(options, 'videoParams.thumbsize', 400);
const scriptArguments = [
'--video',
videoPath,
'--orange',
'--force',
'--renderignore',
5,
'--json',
'--viewport',
'--viewportretries',
60,
'--viewportminheight',
100,
'--viewportminwidth',
100
];
if (options.visualMetricsPerceptual) {
scriptArguments.push('--perceptual');
}
if (options.visualMetricsContentful) {
scriptArguments.push('--contentful');
}
if (options.visualMetricsKeyColor) {
for (let i = 0; i < options.visualMetricsKeyColor.length; ++i) {
if (i % 8 == 0) {
scriptArguments.push('--keycolor');
}
scriptArguments.push(options.visualMetricsKeyColor[i]);
}
}
// There seems to be a bug with --startwhite that makes VM bail out
// 11:20:14.950 - Calculating image histograms
// 11:20:14.951 - No video frames found in /private/var/folders/27/xpnvcsbs0nlfbb4qq397z3rh0000gn/T/vis-cn_JMf
// 11:20:14.951 - Done calculating histograms
// Since we tuned the borders of the video, I hope it will just work fine
// without. If not, let us create a upstream issue
// If it is the first page and no preURL we can use
// start white, that gives us less variance in metrics in Chrome
/*
if (!options.preURL && visitedPageNumber === 0) {
scriptArgs.push('--startwhite');
}
*/
if (options.visualElements) {
scriptArguments.push('--herodata', elementsFile);
}
if (createFilmstrip) {
scriptArguments.push('-q', filmstripQuality);
scriptArguments.unshift('--dir', imageDirPath);
if (fullSizeFilmstrip) {
scriptArguments.push('--full');
} else if (thumbsize !== 400) {
scriptArguments.push('--thumbsize', thumbsize);
}
}
const visualMetricsLogFile = path.join(
videoDir,
index + '.visualmetrics.log'
);
scriptArguments.push('--logfile', visualMetricsLogFile);
if (options.verbose >= 1) {
scriptArguments.push('-vvvv');
} else {
// Full -vvvv is really chatty so keep this level for now.
scriptArguments.push('-vvv');
}
scriptArguments.unshift(getScript(options));
log.debug('Running visualmetrics.py ' + scriptArguments.join(' '));
log.info('Get visual metrics from the video');
try {
const result = await execa(process.env.PYTHON || 'python', scriptArguments);
log.debug('visualmetrics.py output:' + result.stdout);
if (options.verbose < 1) {
try {
await removeFile(visualMetricsLogFile);
} catch {
log.error(
'Could not remove the log file from VisualMetrics, does it exist?: %s',
visualMetricsLogFile
);
}
}
return JSON.parse(result.stdout);
} catch (error) {
log.error('VisualMetrics failed to run', error);
await copyFile(videoPath, videoPath + '.failed.mp4');
if (options.visualElements) {
await copyFile(elementsFile, elementsFile + '.failed.json');
}
// If something goes wrong, dump the visual metrics log to our log
const visualMetricLog = await readFile(visualMetricsLogFile);
log.error('Log from VisualMetrics: %s', visualMetricLog);
throw error;
}
}