Skip to content

Instantly share code, notes, and snippets.

@krisselden
Last active July 4, 2022 23:26
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save krisselden/bf98fb0c192fcb73ed32e79c0a7972d2 to your computer and use it in GitHub Desktop.
Save krisselden/bf98fb0c192fcb73ed32e79c0a7972d2 to your computer and use it in GitHub Desktop.
Make an mp4 out of a Chrome DevTools trace with screenshots.
const fs = require('fs');
const path = require('path');
const spawn = require('child_process').spawn;
const FPS = 60;
const MICROSEC_PER_FRAME = Math.round(1000000 / FPS);
if (process.argv.length < 3) {
console.log(`node ${path.relative('.', process.argv[1])} [DevToolsProfile]`);
process.exit(1);
}
let traceFile = path.resolve(process.argv[2]);
let trace = JSON.parse(fs.readFileSync(traceFile, 'utf8')).traceEvents;
trace = trace.filter(event => event.name === "Screenshot").sort((a, b) => a.ts - b.ts);
if (trace.length === 0) {
console.log('Trace was not recorded with Screenshots. Ensure Screenshots is checked before recording.')
process.exit(1);
}
let { name } = path.parse(traceFile);
let ffmpeg = spawn("ffmpeg", [
"-f", "image2pipe",
"-r", `${FPS}`,
"-vcodec", "mjpeg",
"-i", "pipe:",
"-vcodec", "libx264",
"-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
`${name}.mp4`
], {
stdio: ['pipe', 'inherit', 'inherit']
});
let buffer;
let target = trace[0].ts;
for (let i = 0; i < trace.length; i++) {
let event = trace[i];
// repeat last frame until caught up
while (target < event.ts) {
ffmpeg.stdin.write(buffer);
target += MICROSEC_PER_FRAME;
}
buffer = Buffer.from(event.args.snapshot, "base64");
ffmpeg.stdin.write(buffer);
target += MICROSEC_PER_FRAME;
}
ffmpeg.stdin.end();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment