网页历史延时截图

PGFPlotsEdt 结尾的版本截图视频自动化制作方法。

2025-02-23

【腾讯云】2核2G云服务器新老同享 99元/年,续费同价,云服务器3年机/5年机限时抢购,低至 2.5折

PGFPlotsEdt 视频结尾 处通过一个延时影像序列展示了 PGFPlotsEdt 四年来的前端变迁,该段序列大概包含了 400 张图像(双语版本总共 800 张图像),如果一个一个版本去截图,不仅效率很慢,而且可能会导致截图区域前后不一致。此处展示了这段序列是如何通过自动化方法生成的。

包配置

首先安装 Node.js,然后在项目文件夹中写入下面的 package.json 配置文件:

{
"name": "git-screenshot-webpage",
"version": "1.0.0",
"description": "Get the screenshot sequence of a git repository.",
"main": "screenshot.js",
"scripts": {
"start": "node screenshot.js",
"git-txt": "node git-history.js"
},
"author": "Log Creative",
"license": "MIT",
"dependencies": {
"live-server": "^1.2.2",
"puppeteer": "^22.12.1"
}
}

然后通过 npm install 安装 live-severpuppeteer 包:

接着在该项目文件夹下克隆项目存储库备用,比如本文中的 PGFPlotsEdt,注意不能是从 Download ZIP 下载的文件夹,必须要包含 git 记录。

截图导出

建立下面的 screenshot.js,运行后主要进行下面的操作:

const puppeteer = require('puppeteer');
const fs = require('fs');
const { execSync } = require('child_process');
const liveServer = require('live-server');
const { error } = require('console');

// Your screenshot folder to save.
const screenFolder = 'screenshots';
if (fs.existsSync(screenFolder))
fs.rmSync(screenFolder, {recursive: true, force: true});
fs.mkdirSync(screenFolder);

// The port of live-server.
const PORT = 5500

// Start the live-server first
liveServer.start({
root: 'PGFPlotsEdt',
open: false,
logLevel: 0,
port: PORT,
});

function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
};

async function run() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({width: 1280, height: 720});

let version = 1000;
let filename;

execSync('git checkout master', { cwd: 'PGFPlotsEdt' });

while(version > 1) {
try{ execSync('python version_updater.py', { cwd: 'PGFPlotsEdt/res' }); } catch (error) {}
version = parseInt(execSync("git rev-list HEAD --count", { cwd: 'PGFPlotsEdt' }).toString().trim());
filename = "pgfplotsedt_" + version.toString().padStart(3, '0');
await page.goto(`http://127.0.0.1:${PORT}/`, {waitUntil: 'networkidle2'});
await timeout(1000); // Wait for 1 seconds to ensure the server is up and running
await page.screenshot({path: `${screenFolder}/${filename}.png`});
try {execSync('git checkout HEAD^', { cwd: 'PGFPlotsEdt' });} catch (error) {}
}

browser.close();
liveServer.shutdown(); // Shutdown live-server after taking the screenshot
}

run();

之后在命令行中通过 npm run start 运行该脚本。

历史信息导出

历史信息通过建立下面的 git-history.js 文件实现,实际上也可以通过命令行脚本,此处统一起见皆写为 JavaScript 脚本。

const { execSync } = require('child_process');
const fs = require('fs');

// The commit details
result = execSync('git log --oneline --reverse', { cwd: 'PGFPlotsEdt' });
fs.writeFileSync('git-history.txt', result.toString());

// the time of every commit
result = execSync('git log --pretty=format:"%ad" --date=short --reverse', { cwd: 'PGFPlotsEdt' });
fs.writeFileSync('git-time.txt', result.toString());

之后在命令行中通过 npm run git-txt 运行该脚本。

导入 After Effects

After Effects 可以通过 JavaScript API 来程式化地合成动画,此处使用了下面的步骤:

"v" + (timeToFrames()+1)/100
footage("git-time.txt").sourceText.split('\n')[timeToFrames()]
footage("git-history.txt").sourceText.split('\n')[timeToFrames()]

之后可以通过动态链接功能将 After Effects 合成导入 Premiere Pro 项目中。注意如果 Premiere Pro 没有正确显示文字内容,可以通过同时打开 After Effects 项目来解决这个问题。