How I extracted HTML slide decks into videos with Puppeteer and a small python script.
Recently I took a course on how to improve product UX. The course was interesting as it actually showed real examples from the real world with products like Lyft, DoorDash, Airbnb, and more. The course content was mostly in some cool slide deck, the slide was moving HTML elements as you go on. I wanted to save this deck so I could refer to it when needed. Export wasn’t available. My next option was to record the screen and go through all the decks manually, workable but annoying. I decided I’ll create a script that will automate the extraction for me. I planned the script to do this:
import puppeteer from 'puppeteer';
function delay(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time)
});
}
(async () => {
const browser = await puppeteer.launch({
headless: false,
executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
});
const generate = async function(destPath, uri) {
const page = await browser.newPage();
await page.setViewport({
width: 3000,
height: 2000,
});
const cookies = ['session-cookies-here'];
await page.setCookie(...cookies);
await page.goto(uri, {
waitUntil: 'networkidle2',
});
const selector = '.deck iframe';
await page.waitForSelector(selector);
const element = await page.$(selector);
let count = 1;
const frame = page.frames().find(frame => frame.url().startsWith('https://example.com/slides'));
while (count <= 200) {
await delay(2000);
await element.screenshot({path: `${destPath}/p${count}.png`});
await frame.click('.navigate-right');
count++;
}
}
await generate(folder, uri)
await browser.close();
})();
import cv2
import functools
import numpy as np
import os
def genVideo(image_folder, video_file):
image_size = (960, 540)
each_image_duration = 2
def cut(x):
return x[1:][0:-4]
def compare(x, y):
return 1 if int(cut(x)) > int(cut(y)) else -1
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
images.sort(key=functools.cmp_to_key(compare))
out = cv2.VideoWriter(video_file, cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), 1.0, image_size)
for filename in images:
img = cv2.imread(os.path.join(image_folder, filename))
for _ in range(each_image_duration):
out.write(img)
out.release()