browsertime 17.0.0-beta.4 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +22 -13
  2. package/bin/browsertime.js +4 -4
  3. package/bin/browsertimeWebPageReplay.js +2 -2
  4. package/index.js +2 -2
  5. package/lib/android/gnirehtet.js +1 -2
  6. package/lib/android/root.js +57 -16
  7. package/lib/chrome/chromeDevtoolsProtocol.js +2 -3
  8. package/lib/chrome/har.js +1 -1
  9. package/lib/chrome/longTaskMetrics.js +1 -1
  10. package/lib/chrome/parseCpuTrace.js +2 -2
  11. package/lib/chrome/settings/chromeAndroidOptions.js +1 -1
  12. package/lib/chrome/settings/chromeDesktopOptions.js +1 -1
  13. package/lib/chrome/settings/traceCategories.js +1 -1
  14. package/lib/chrome/traceCategoriesParser.js +3 -3
  15. package/lib/chrome/webdriver/builder.js +1 -1
  16. package/lib/chrome/webdriver/chromium.js +13 -17
  17. package/lib/chrome/webdriver/setupChromiumOptions.js +18 -13
  18. package/lib/connectivity/humble.js +10 -12
  19. package/lib/connectivity/index.js +1 -1
  20. package/lib/core/engine/collector.js +2 -4
  21. package/lib/core/engine/command/addText.js +1 -2
  22. package/lib/core/engine/command/android.js +1 -1
  23. package/lib/core/engine/command/cache.js +1 -2
  24. package/lib/core/engine/command/chromeDevToolsProtocol.js +1 -2
  25. package/lib/core/engine/command/click.js +1 -2
  26. package/lib/core/engine/command/debug.js +1 -3
  27. package/lib/core/engine/command/javaScript.js +1 -2
  28. package/lib/core/engine/command/measure.js +13 -15
  29. package/lib/core/engine/command/meta.js +1 -1
  30. package/lib/core/engine/command/navigation.js +1 -1
  31. package/lib/core/engine/command/screenshot.js +1 -1
  32. package/lib/core/engine/command/scroll.js +1 -1
  33. package/lib/core/engine/command/select.js +1 -1
  34. package/lib/core/engine/command/set.js +1 -1
  35. package/lib/core/engine/command/stopWatch.js +1 -1
  36. package/lib/core/engine/command/switch.js +44 -1
  37. package/lib/core/engine/command/util/lcpHighlightScript.js +1 -1
  38. package/lib/core/engine/command/util/lsHighlightScript.js +1 -1
  39. package/lib/core/engine/command/wait.js +1 -1
  40. package/lib/core/engine/index.js +12 -12
  41. package/lib/core/engine/iteration.js +27 -27
  42. package/lib/core/engine/run.js +1 -1
  43. package/lib/core/pageCompleteChecks/defaultPageCompleteCheck.js +1 -1
  44. package/lib/core/pageCompleteChecks/pageCompleteCheckByInactivity.js +1 -1
  45. package/lib/core/pageCompleteChecks/spaInactivity.js +1 -1
  46. package/lib/core/seleniumRunner.js +9 -11
  47. package/lib/edge/webdriver/builder.js +1 -1
  48. package/lib/extensionserver/index.js +2 -4
  49. package/lib/extensionserver/setup.js +1 -1
  50. package/lib/firefox/geckoProfiler.js +46 -16
  51. package/lib/firefox/getHAR.js +1 -1
  52. package/lib/firefox/memoryReport.js +1 -1
  53. package/lib/firefox/settings/disableSafeBrowsingPreferences.js +1 -1
  54. package/lib/firefox/settings/disableTrackingProtectionPreferences.js +1 -1
  55. package/lib/firefox/settings/firefoxPreferences.js +1 -1
  56. package/lib/firefox/webdriver/builder.js +9 -9
  57. package/lib/firefox/webdriver/firefox.js +24 -6
  58. package/lib/safari/webdriver/safari.js +1 -1
  59. package/lib/screenshot/defaults.js +1 -1
  60. package/lib/screenshot/index.js +3 -5
  61. package/lib/support/cli.js +5 -5
  62. package/lib/support/dns.js +1 -1
  63. package/lib/support/engineUtils.js +5 -13
  64. package/lib/support/getViewPort.js +1 -1
  65. package/lib/support/har/index.js +6 -8
  66. package/lib/support/images/index.js +1 -1
  67. package/lib/support/logging.js +1 -1
  68. package/lib/support/pathToFolder.js +4 -4
  69. package/lib/support/preURL.js +1 -1
  70. package/lib/support/processes.js +1 -1
  71. package/lib/support/setResourceTimingBufferSize.js +1 -1
  72. package/lib/support/stop.js +1 -1
  73. package/lib/support/storageManager.js +1 -3
  74. package/lib/support/tcpdump.js +2 -2
  75. package/lib/support/xvfb.js +2 -4
  76. package/lib/video/postprocessing/finetune/addTextToVideo.js +3 -3
  77. package/lib/video/postprocessing/finetune/convertFps.js +1 -1
  78. package/lib/video/postprocessing/finetune/getFont.js +1 -1
  79. package/lib/video/postprocessing/finetune/getTimingMetrics.js +2 -2
  80. package/lib/video/postprocessing/finetune/index.js +4 -4
  81. package/lib/video/postprocessing/finetune/removeOrange.js +1 -1
  82. package/lib/video/postprocessing/visualmetrics/extraMetrics.js +1 -1
  83. package/lib/video/postprocessing/visualmetrics/getVideoMetrics.js +2 -2
  84. package/lib/video/screenRecording/android/recorder.js +1 -1
  85. package/lib/video/screenRecording/desktop/convert.js +1 -1
  86. package/lib/video/screenRecording/desktop/desktopRecorder.js +3 -3
  87. package/lib/video/screenRecording/desktop/ffmpegRecorder.js +6 -6
  88. package/lib/video/screenRecording/desktop/osx/getSPDisplaysDataType.js +1 -1
  89. package/lib/video/screenRecording/desktop/osx/getScreen.js +1 -1
  90. package/lib/video/screenRecording/firefox/firefoxWindowRecorder.js +1 -1
  91. package/lib/video/screenRecording/ios/convertToMp4.js +1 -1
  92. package/lib/video/screenRecording/ios/iosRecorder.js +2 -2
  93. package/lib/video/screenRecording/iosSimulator/convertToMp4.js +1 -1
  94. package/lib/video/screenRecording/iosSimulator/recorder.js +2 -2
  95. package/lib/video/screenRecording/recorder.js +6 -6
  96. package/lib/video/screenRecording/setOrangeBackground.js +1 -1
  97. package/lib/video/video.js +9 -11
  98. package/package.json +17 -17
@@ -11,9 +11,9 @@ import { pac, manual } from 'selenium-webdriver/proxy.js';
11
11
  import pick from 'lodash.pick';
12
12
  import isEmpty from 'lodash.isempty';
13
13
  import get from 'lodash.get';
14
- import defaultFirefoxPreferences from '../settings/firefoxPreferences.js';
15
- import disableSafeBrowsingPreferences from '../settings/disableSafeBrowsingPreferences.js';
16
- import disableTrackingProtectionPreferences from '../settings/disableTrackingProtectionPreferences.js';
14
+ import { defaultFirefoxPreferences } from '../settings/firefoxPreferences.js';
15
+ import { disableSafeBrowsingPreferences } from '../settings/disableSafeBrowsingPreferences.js';
16
+ import { disableTrackingProtectionPreferences } from '../settings/disableTrackingProtectionPreferences.js';
17
17
  import { toArray } from '../../support/util.js';
18
18
  import { Android, isAndroidConfigured } from '../../android/index.js';
19
19
  const log = intel.getLogger('browsertime.firefox');
@@ -90,12 +90,12 @@ export async function configureBuilder(builder, baseDir, options) {
90
90
  }
91
91
  }
92
92
 
93
- if (!firefoxConfig.noDefaultPrefs) {
93
+ if (firefoxConfig.noDefaultPrefs) {
94
+ log.info('Skip setting default preferences for Firefox');
95
+ } else {
94
96
  for (const pref of Object.keys(defaultFirefoxPreferences)) {
95
97
  ffOptions.setPreference(pref, defaultFirefoxPreferences[pref]);
96
98
  }
97
- } else {
98
- log.info('Skip setting default preferences for Firefox');
99
99
  }
100
100
 
101
101
  if (firefoxConfig.disableSafeBrowsing) {
@@ -144,9 +144,9 @@ export async function configureBuilder(builder, baseDir, options) {
144
144
  }
145
145
 
146
146
  if (options.extension) {
147
- const extensions = !Array.isArray(options.extension)
148
- ? [options.extension]
149
- : options.extension;
147
+ const extensions = Array.isArray(options.extension)
148
+ ? options.extension
149
+ : [options.extension];
150
150
  for (const extension of extensions) {
151
151
  ffOptions.addExtensions(extension);
152
152
  }
@@ -4,17 +4,17 @@ import { join } from 'node:path';
4
4
  import intel from 'intel';
5
5
  import get from 'lodash.get';
6
6
  import { getEmptyHAR, mergeHars } from '../../support/har/index.js';
7
- import pathToFolder from '../../support/pathToFolder.js';
7
+ import { pathToFolder } from '../../support/pathToFolder.js';
8
8
  import { isAndroidConfigured, Android } from '../../android/index.js';
9
9
  import { adjustVisualProgressTimestamps } from '../../support/util.js';
10
10
  import { findFiles } from '../../support/fileUtil.js';
11
- import getHAR from '../getHAR.js';
12
- import GeckoProfiler from '../geckoProfiler.js';
11
+ import { getHAR } from '../getHAR.js';
12
+ import { GeckoProfiler } from '../geckoProfiler.js';
13
13
  import { MemoryReport } from '../memoryReport.js';
14
14
  import { PerfStats } from '../perfStats.js';
15
15
  const log = intel.getLogger('browsertime.firefox');
16
16
  const rename = promisify(_rename);
17
- class Firefox {
17
+ export class Firefox {
18
18
  constructor(storageManager, options) {
19
19
  // Lets keep this and hope that we in the future will have HAR for FF again
20
20
  this.skipHar = options.skipHar;
@@ -73,6 +73,14 @@ class Firefox {
73
73
  * Before each URL/test runs.
74
74
  */
75
75
  async beforeEachURL(runner) {
76
+ await runner.runPrivilegedScript(`
77
+ new Promise(async function(resolve) {
78
+ await Services.fog.testFlushAllChildren(); // force any data that wasn't recorded yet to be immediately put in the buffers
79
+ Services.fog.testResetFOG(); // empty the buffers
80
+ resolve();
81
+ });
82
+ `);
83
+
76
84
  if (isAndroidConfigured(this.options) && this.options.androidPower) {
77
85
  await this.android.resetPowerUsage();
78
86
  }
@@ -146,6 +154,18 @@ class Firefox {
146
154
  );
147
155
  }
148
156
 
157
+ let powerusage = await runner.runPrivilegedScript(`
158
+ return new Promise(async function(resolve) {
159
+ Services.fog.initializeFOG(); // prevents timeout when collecting CPU metrics
160
+ await Services.fog.testFlushAllChildren(); // force data from child processes to be sent to the parent.
161
+ resolve(Glean.power.totalCpuTimeMs.testGetValue());
162
+ });
163
+ `);
164
+ if (powerusage) {
165
+ log.info('CPU / Power usage: ' + powerusage);
166
+ }
167
+ result.cpu = powerusage;
168
+
149
169
  if (this.skipHar || isAndroidConfigured(this.options)) {
150
170
  return result;
151
171
  } else {
@@ -274,5 +294,3 @@ class Firefox {
274
294
  */
275
295
  async afterBrowserStopped() {}
276
296
  }
277
-
278
- export default Firefox;
@@ -2,7 +2,7 @@
2
2
  import { execaCommand as command } from 'execa';
3
3
  const delay = ms => new Promise(res => setTimeout(res, ms));
4
4
 
5
- export default class Safari {
5
+ export class Safari {
6
6
  constructor(storageManager, options) {
7
7
  this.options = options;
8
8
  this.safariOptions = options.safari || {};
@@ -1,4 +1,4 @@
1
- export default {
1
+ export const screenshotDefaults = {
2
2
  type: 'jpg',
3
3
  png: {
4
4
  compressionLevel: 6
@@ -1,7 +1,7 @@
1
1
  import { join } from 'node:path';
2
2
  import merge from 'lodash.merge';
3
3
  import intel from 'intel';
4
- import defaultConfig from './defaults.js';
4
+ import { screenshotDefaults } from './defaults.js';
5
5
  import {
6
6
  savePngWithoutResize,
7
7
  savePng,
@@ -9,10 +9,10 @@ import {
9
9
  } from '../support/images/index.js';
10
10
  const SCREENSHOT_DIR = 'screenshots';
11
11
  const log = intel.getLogger('browsertime.screenshot');
12
- class ScreenshotManager {
12
+ export class ScreenshotManager {
13
13
  constructor(storageManager, options) {
14
14
  this.storageManager = storageManager;
15
- this.config = merge({}, defaultConfig, options.screenshotParams);
15
+ this.config = merge({}, screenshotDefaults, options.screenshotParams);
16
16
  this.options = options;
17
17
  this.savedScreenshots = [];
18
18
  }
@@ -76,5 +76,3 @@ class ScreenshotManager {
76
76
  return this.savedScreenshots;
77
77
  }
78
78
  }
79
-
80
- export default ScreenshotManager;
@@ -13,7 +13,7 @@ import {
13
13
  threads,
14
14
  xvfbDisplay
15
15
  } from '../video/defaults.js';
16
- import SCREENSHOT from '../screenshot/defaults.js';
16
+ import { screenshotDefaults } from '../screenshot/defaults.js';
17
17
  import {
18
18
  features,
19
19
  threads as _threads,
@@ -840,22 +840,22 @@ export function parseCommandLine() {
840
840
  .option('screenshotParams.type', {
841
841
  describe: 'Set the file type of the screenshot',
842
842
  choices: ['png', 'jpg'],
843
- default: SCREENSHOT.type,
843
+ default: screenshotDefaults.type,
844
844
  group: 'Screenshot'
845
845
  })
846
846
  .option('screenshotParams.png.compressionLevel', {
847
847
  describe: 'zlib compression level',
848
- default: SCREENSHOT.png.compressionLevel,
848
+ default: screenshotDefaults.png.compressionLevel,
849
849
  group: 'Screenshot'
850
850
  })
851
851
  .option('screenshotParams.jpg.quality', {
852
852
  describe: 'Quality of the JPEG screenshot. 1-100',
853
- default: SCREENSHOT.jpg.quality,
853
+ default: screenshotDefaults.jpg.quality,
854
854
  group: 'Screenshot'
855
855
  })
856
856
  .option('screenshotParams.maxSize', {
857
857
  describe: 'The max size of the screenshot (width and height).',
858
- default: SCREENSHOT.maxSize,
858
+ default: screenshotDefaults.maxSize,
859
859
  group: 'Screenshot'
860
860
  })
861
861
  .option('pageCompleteCheck', {
@@ -3,7 +3,7 @@ import intel from 'intel';
3
3
  import { isAndroidConfigured } from '../android/index.js';
4
4
  const log = intel.getLogger('browsertime.dns');
5
5
 
6
- export default async function (options) {
6
+ export async function flushDNS(options) {
7
7
  if (isAndroidConfigured(options)) {
8
8
  return;
9
9
  }
@@ -1,6 +1,6 @@
1
1
  import { resolve, dirname, join } from 'node:path';
2
2
  import { promisify } from 'node:util';
3
- import { writeFile as _writeFile, access, unlink as _unlink } from 'node:fs';
3
+ import { writeFile as _writeFile, unlink as _unlink } from 'node:fs';
4
4
  import { pathToFileURL } from 'node:url';
5
5
  import dayjs from 'dayjs';
6
6
  import intel from 'intel';
@@ -11,15 +11,6 @@ const unlink = promisify(_unlink);
11
11
 
12
12
  const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
13
13
 
14
- async function exists(path) {
15
- try {
16
- await access(path);
17
- return true;
18
- } catch {
19
- return false;
20
- }
21
- }
22
-
23
14
  async function loadFile(script, options, throwError) {
24
15
  // if the script is an AsyncFunction, return it.
25
16
  if (script instanceof AsyncFunction) {
@@ -42,15 +33,16 @@ async function loadFile(script, options, throwError) {
42
33
  // Hack a way! Try to add a package.json file in the same folder as the
43
34
  // script file. That way, the .js file will be treated as commonjs =
44
35
  // working as before we moved Browsertime to module
36
+
45
37
  let createdPackageJson = false;
46
38
  try {
47
39
  const packageJson = join(dirname(resolve(script)), 'package.json');
48
- if (!(await exists(packageJson))) {
40
+ try {
49
41
  await writeFile(packageJson, '{}');
50
42
  createdPackageJson = true;
51
- } else {
43
+ } catch {
52
44
  log.error(
53
- 'Could not create package.json file, the %S file will be treated as a esmodule',
45
+ 'Could not create package.json file, the %s file will be treated as a esmodule',
54
46
  script
55
47
  );
56
48
  }
@@ -29,7 +29,7 @@ const sizeMap = {
29
29
  'Samsung Galaxy S8+': '412x846'
30
30
  };
31
31
 
32
- export default function (options) {
32
+ export function getViewPort(options) {
33
33
  // you cannot set the width/height for phone so just keep the viewport undefined
34
34
  if (isAndroidConfigured(options)) {
35
35
  return;
@@ -4,7 +4,7 @@ import pick from 'lodash.pick';
4
4
  import isEmpty from 'lodash.isempty';
5
5
  import get from 'lodash.get';
6
6
  import dayjs from 'dayjs';
7
- import pathToFolder from '../pathToFolder.js';
7
+ import { pathToFolder } from '../pathToFolder.js';
8
8
  import intel from 'intel';
9
9
  const log = intel.getLogger('browsertime');
10
10
  const require = createRequire(import.meta.url);
@@ -22,7 +22,7 @@ function generateUniquePageId(baseId, existingIdMap) {
22
22
  function getDocumentRequests(entries, pageId) {
23
23
  let pageEntries = [...entries];
24
24
  if (pageId) {
25
- pageEntries = [...entries.filter(entry => entry.pageref === pageId)];
25
+ pageEntries = entries.filter(entry => entry.pageref === pageId);
26
26
  }
27
27
 
28
28
  const requests = [];
@@ -199,11 +199,9 @@ export function getMainDocumentTimings(har) {
199
199
  let pageEntries = [...entries];
200
200
  const finalURL = getFinalURL(pageEntries, pageId);
201
201
 
202
- pageEntries = [
203
- ...pageEntries.filter(
204
- entry => entry.pageref === pageId && entry.request.url === finalURL
205
- )
206
- ];
202
+ pageEntries = pageEntries.filter(
203
+ entry => entry.pageref === pageId && entry.request.url === finalURL
204
+ );
207
205
 
208
206
  timings.push({ url, timings: pageEntries[0].timings });
209
207
  }
@@ -219,7 +217,7 @@ export function getFullyLoaded(har) {
219
217
  const url = page._url;
220
218
 
221
219
  let pageEntries = [...entries];
222
- pageEntries = [...pageEntries.filter(entry => entry.pageref === pageId)];
220
+ pageEntries = pageEntries.filter(entry => entry.pageref === pageId);
223
221
 
224
222
  let pageEnd = 0;
225
223
  for (let entry of pageEntries) {
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import pathToFolder from '../pathToFolder.js';
2
+ import { pathToFolder } from '../pathToFolder.js';
3
3
 
4
4
  export async function savePngWithoutResize(
5
5
  name,
@@ -1,7 +1,7 @@
1
1
  import intel from 'intel';
2
2
  const { INFO, DEBUG, VERBOSE, TRACE, NONE, basicConfig } = intel;
3
3
 
4
- export default function configure(options) {
4
+ export function configure(options) {
5
5
  options = options || {};
6
6
 
7
7
  let level = INFO;
@@ -9,7 +9,7 @@ function toSafeKey(key) {
9
9
  return key.replace(/[ %&()+,./:?|~–]|%7C/g, '-');
10
10
  }
11
11
 
12
- export default function (url, options) {
12
+ export function pathToFolder(url, options) {
13
13
  if (options.useSameDir) {
14
14
  return '';
15
15
  } else {
@@ -40,9 +40,7 @@ export default function (url, options) {
40
40
  }
41
41
 
42
42
  // This is used from sitespeed.io to match URLs on Graphite
43
- if (!options.storeURLsAsFlatPageOnDisk) {
44
- pathSegments.push(...urlSegments);
45
- } else {
43
+ if (options.storeURLsAsFlatPageOnDisk) {
46
44
  const folder = toSafeKey(urlSegments.join('_').concat('_'));
47
45
  if (folder.length > 255) {
48
46
  log.info(
@@ -52,6 +50,8 @@ export default function (url, options) {
52
50
  } else {
53
51
  pathSegments.push(folder);
54
52
  }
53
+ } else {
54
+ pathSegments.push(...urlSegments);
55
55
  }
56
56
  }
57
57
 
@@ -2,7 +2,7 @@ import intel from 'intel';
2
2
  const log = intel.getLogger('browsertime');
3
3
  const delay = ms => new Promise(res => setTimeout(res, ms));
4
4
 
5
- export default async function (browser, options) {
5
+ export async function preURL(browser, options) {
6
6
  log.info('Accessing preURL %s', options.preURL);
7
7
  await browser.loadAndWait(options.preURL);
8
8
  if (!options.preURLDisableWhiteBackground) {
@@ -1,5 +1,5 @@
1
1
  import { execaCommand as command } from 'execa';
2
- export default async function () {
2
+ export async function getNumberOfRunningProcesses() {
3
3
  const { stdout } = await command('ps aux | wc -l', { shell: true });
4
4
  return stdout;
5
5
  }
@@ -1,4 +1,4 @@
1
- export default async function (startURL, driver, size) {
1
+ export async function setResourceTimingBufferSize(startURL, driver, size) {
2
2
  await driver.get(startURL);
3
3
  await driver.executeScript(
4
4
  `window.performance.setResourceTimingBufferSize(${size});`
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime');
4
4
 
5
- export default async function (processName) {
5
+ export async function stop(processName) {
6
6
  const scriptArguments = ['-9', processName];
7
7
 
8
8
  log.debug('Kill all processes ' + processName);
@@ -49,7 +49,7 @@ async function streamToString(stream) {
49
49
  });
50
50
  }
51
51
 
52
- class StorageManager {
52
+ export class StorageManager {
53
53
  constructor(url, { resultDir, prettyPrint = false } = {}) {
54
54
  this.baseDir = resultDir
55
55
  ? _resolve(resultDir)
@@ -134,5 +134,3 @@ class StorageManager {
134
134
  return this.baseDir;
135
135
  }
136
136
  }
137
-
138
- export default StorageManager;
@@ -1,9 +1,9 @@
1
1
  import { join } from 'node:path';
2
2
  import { execa } from 'execa';
3
- import pathToFolder from './pathToFolder.js';
3
+ import { pathToFolder } from './pathToFolder.js';
4
4
  import { rename } from './fileUtil.js';
5
5
 
6
- export default class TCPDump {
6
+ export class TCPDump {
7
7
  constructor(directory, options) {
8
8
  this.baseDir = directory;
9
9
  this.options = options;
@@ -2,7 +2,7 @@ import { promisify } from 'node:util';
2
2
  import get from 'lodash.get';
3
3
  import Xvfb from '@cypress/xvfb';
4
4
  import { xvfbDisplay } from '../video/defaults.js';
5
- import getViewPort from '../support/getViewPort.js';
5
+ import { getViewPort } from '../support/getViewPort.js';
6
6
  import { isAndroidConfigured } from '../android/index.js';
7
7
 
8
8
  function buildXvfbArguments({ display, screen = 0, size, silent }) {
@@ -41,7 +41,7 @@ async function stopXvfb(xvfb) {
41
41
  * Create a new XVFB instance
42
42
  * @class
43
43
  */
44
- class XVFB {
44
+ export class XVFB {
45
45
  constructor(options) {
46
46
  this.options = options;
47
47
  }
@@ -67,5 +67,3 @@ class XVFB {
67
67
  }
68
68
  }
69
69
  }
70
-
71
- export default XVFB;
@@ -1,7 +1,7 @@
1
1
  import { execa } from 'execa';
2
2
  import intel from 'intel';
3
- import getTimingMetrics from './getTimingMetrics.js';
4
- import getFont from './getFont.js';
3
+ import { getTimingMetrics } from './getTimingMetrics.js';
4
+ import { getFont } from './getFont.js';
5
5
  import { isAndroidConfigured } from '../../../android/index.js';
6
6
  const log = intel.getLogger('browsertime.video');
7
7
 
@@ -14,7 +14,7 @@ function isSmallish(options) {
14
14
  );
15
15
  }
16
16
 
17
- export default async function (
17
+ export async function addTextToVideo(
18
18
  inputFile,
19
19
  outputFile,
20
20
  videoMetrics,
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime.video');
4
4
 
5
- export default async function (source, destination, framerate) {
5
+ export async function convert(source, destination, framerate) {
6
6
  const scriptArguments = [
7
7
  '-nostdin',
8
8
  '-i',
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from 'node:fs';
2
- export default function (options) {
2
+ export function getFont(options) {
3
3
  // If the font is not part of the params and we're on macOS
4
4
  // we check that SFNSMono.ttf is available
5
5
  if (!options.videoParams.fontPath && process.platform === 'darwin') {
@@ -1,5 +1,5 @@
1
1
  import { isAndroidConfigured } from '../../../android/index.js';
2
- import getFont from './getFont.js';
2
+ import { getFont } from './getFont.js';
3
3
 
4
4
  function isSmallish(options) {
5
5
  return (
@@ -30,7 +30,7 @@ function get(metric, metricName, pos, options) {
30
30
  },30)':x=(w-tw)/2: y=H-${pos}-h/${x}:fontcolor=white:fontsize=h/${fontSize}:box=1:boxcolor=0x000000AA:boxborderw=2:text='${metricName} ${metric}'`;
31
31
  }
32
32
 
33
- export default function (videoMetrics, timingMetrics, options) {
33
+ export function getTimingMetrics(videoMetrics, timingMetrics, options) {
34
34
  let text = '';
35
35
  const vm = videoMetrics.visualMetrics;
36
36
  const startPosition = 'h/10';
@@ -7,9 +7,9 @@ import {
7
7
  import { promisify } from 'node:util';
8
8
  import intel from 'intel';
9
9
  import get from 'lodash.get';
10
- import addTextToVideo from './addTextToVideo.js';
11
- import removeOrange from './removeOrange.js';
12
- import convert from './convertFps.js';
10
+ import { addTextToVideo } from './addTextToVideo.js';
11
+ import { removeOrange } from './removeOrange.js';
12
+ import { convert } from './convertFps.js';
13
13
  import { convert as _convert } from '../../defaults.js';
14
14
  import { isAndroidConfigured } from '../../../android/index.js';
15
15
  const rename = promisify(_rename);
@@ -17,7 +17,7 @@ const copyFile = promisify(_copyFile);
17
17
  const unlink = promisify(_unlink);
18
18
  const log = intel.getLogger('browsertime.video');
19
19
 
20
- export default async function (
20
+ export async function finetuneVideo(
21
21
  videoDir,
22
22
  videoPath,
23
23
  index,
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime.video');
4
4
 
5
- export default async function (
5
+ export async function removeOrange(
6
6
  inputFile,
7
7
  outputFile,
8
8
  newStart,
@@ -1,4 +1,4 @@
1
- export default function (metrics) {
1
+ export function extraMetrics(metrics) {
2
2
  const videoMetrics = {};
3
3
  if (!metrics.VisualReadiness) {
4
4
  metrics.VisualReadiness =
@@ -1,10 +1,10 @@
1
1
  import { join } from 'node:path';
2
2
  import intel from 'intel';
3
3
  import { run } from './visualMetrics.js';
4
- import extraMetrics from './extraMetrics.js';
4
+ import { extraMetrics } from './extraMetrics.js';
5
5
  const log = intel.getLogger('browsertime.video');
6
6
 
7
- export default async function (
7
+ export async function getVideoMetrics(
8
8
  videoDir,
9
9
  filmstripDir,
10
10
  videoPath,
@@ -8,7 +8,7 @@ const unlink = promisify(_unlink);
8
8
  const log = intel.getLogger('browsertime.video');
9
9
  const delay = ms => new Promise(res => setTimeout(res, ms));
10
10
 
11
- export default class AndroidRecorder {
11
+ export class AndroidRecorder {
12
12
  constructor(options) {
13
13
  this.waitTime = get(options, 'videoParams.androidVideoWaitTime', 5000);
14
14
  this.framerate = get(options, 'videoParams.framerate', framerate);
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime.video');
4
4
 
5
- export default async function convert(source, destination, crf, threads) {
5
+ export async function convert(source, destination, crf, threads) {
6
6
  const scriptArguments = [
7
7
  '-nostdin',
8
8
  '-i',
@@ -3,7 +3,7 @@ import { unlink as _unlink, rename as _rename } from 'node:fs';
3
3
  import intel from 'intel';
4
4
  import get from 'lodash.get';
5
5
  import { start as _start, stop as _stop } from './ffmpegRecorder.js';
6
- import convert from './convert.js';
6
+ import { convert } from './convert.js';
7
7
  import {
8
8
  xvfbDisplay,
9
9
  framerate as _framerate,
@@ -11,12 +11,12 @@ import {
11
11
  convert as _convert,
12
12
  threads as _threads
13
13
  } from '../../defaults.js';
14
- import getViewPort from '../../../support/getViewPort.js';
14
+ import { getViewPort } from '../../../support/getViewPort.js';
15
15
  const unlink = promisify(_unlink);
16
16
  const rename = promisify(_rename);
17
17
  const log = intel.getLogger('browsertime.video');
18
18
 
19
- export default class DesktopRecorder {
19
+ export class DesktopRecorder {
20
20
  constructor(options) {
21
21
  this.display = get(options, 'xvfbParams.display', xvfbDisplay);
22
22
  this.framerate = get(options, 'videoParams.framerate', _framerate);
@@ -1,7 +1,7 @@
1
1
  import { execa } from 'execa';
2
2
  import intel from 'intel';
3
- import getScreenOnOSX from './osx/getScreen.js';
4
- import getSPDisplaysDataType from './osx/getSPDisplaysDataType.js';
3
+ import { getScreenOnOSX } from './osx/getScreen.js';
4
+ import { getSPDisplaysDataType } from './osx/getSPDisplaysDataType.js';
5
5
  const log = intel.getLogger('browsertime.video');
6
6
 
7
7
  async function buildX11FfmpegArguments({
@@ -98,15 +98,15 @@ async function startRecording(ffmpegArguments, nice, filePath) {
98
98
  });
99
99
  }
100
100
  let ffmpegProcess;
101
- if (nice !== 0) {
101
+ if (nice === 0) {
102
+ log.debug('Start FFMPEG with %j', ffmpegArguments);
103
+ ffmpegProcess = execa('ffmpeg', ffmpegArguments);
104
+ } else {
102
105
  ffmpegArguments.unshift('ffmpeg');
103
106
  ffmpegArguments.unshift(`${nice}`);
104
107
  ffmpegArguments.unshift('-n');
105
108
  log.debug('Start FFMPEG with %j', ffmpegArguments);
106
109
  ffmpegProcess = execa('nice', ffmpegArguments);
107
- } else {
108
- log.debug('Start FFMPEG with %j', ffmpegArguments);
109
- ffmpegProcess = execa('ffmpeg', ffmpegArguments);
110
110
  }
111
111
 
112
112
  // Race to catch if ffmpeg exists early, or if recording has started
@@ -1,6 +1,6 @@
1
1
  import { execaCommand as command } from 'execa';
2
2
 
3
- export default async function () {
3
+ export async function getSPDisplaysDataType() {
4
4
  const output = await command('system_profiler SPDisplaysDataType', {
5
5
  shell: true
6
6
  });
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime.video');
4
4
 
5
- export default async function () {
5
+ export async function getScreenOnOSX() {
6
6
  const scriptArguments = [
7
7
  '-hide_banner',
8
8
  '-f',
@@ -147,7 +147,7 @@ async function generateVideo(destination, recordingDirectoryName) {
147
147
  return removeDirAndFiles(recordingDirectoryName);
148
148
  }
149
149
 
150
- export default class FirefoxWindowRecorder {
150
+ export class FirefoxWindowRecorder {
151
151
  constructor(options, browser, baseDir) {
152
152
  this.options = options;
153
153
  this.browser = browser;
@@ -2,7 +2,7 @@ import { execa } from 'execa';
2
2
  import intel from 'intel';
3
3
  const log = intel.getLogger('browsertime.video');
4
4
 
5
- export default async function convert(source, destination) {
5
+ export async function convert(source, destination) {
6
6
  const scriptArguments = [
7
7
  '-framerate',
8
8
  60,