Skip to content

Instantly share code, notes, and snippets.

@abigpotostew
Last active November 16, 2021 18:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save abigpotostew/858ed102690f492d5800ea4e61a25900 to your computer and use it in GitHub Desktop.
Save abigpotostew/858ed102690f492d5800ea4e61a25900 to your computer and use it in GitHub Desktop.
Gradis to GIF script
/**
* Gradis Token to GIF
* Install:
* * npm i puppeteer gifencoder png-js
* Run:
* * node index.js 102402010402011602011606
* * node index.js 10360308020202100302110304,10350503030202000202140003,10160116030200020302040506
* tested on node v14.17.6
* For best results close all other apps and do not use your computer while this script loads.
* Make sure you have a couple GB of free memory and no other CPU intensive processes running.
*/
const fs = require('fs');
const puppeteer = require('puppeteer');
const GIFEncoder = require('gifencoder');
const PNG = require('png-js');
// Configuration:
// size can be 400 or 800
const size = 800;
const factor = size === 400 ? 1 : 1.5;
function decode(png) {
return new Promise(r => {
png.decode(pixels => r(pixels))
});
}
async function gifAddFrame(page, encoder) {
let viewportOffset = 0;
if (size === 800) {
viewportOffset = 130; // center the gradis in the screenshot
}
const pngBuffer = await page.screenshot({
clip: {
width: size / factor,
height: size / factor,
x: viewportOffset,
y: 0,
}
});
const png = new PNG(pngBuffer);
await decode(png).then(pixels => encoder.addFrame(pixels));
}
const run = async (tokenId) => {
const browser = await puppeteer.launch({
headless: true, slowMo: 0,
});
const page = await browser.newPage();
await page.setViewport({
width: size,
height: size,
deviceScaleFactor: factor
});
await page.goto('https://nft.gradis.art/index2.html?tokenid=' + tokenId, {
waitUntil: ['domcontentloaded', 'networkidle0']
});
// Pause the animation before it starts
const anim = '#toggle-play'
const sleep = m => new Promise(r => setTimeout(r, m));
const button = await page.waitForSelector(anim);
await sleep(2500) // extra wait for gradis to load. Should be increased on a slow network.
// record gif
var encoder = new GIFEncoder(size, size);
encoder.createWriteStream()
.pipe(fs.createWriteStream(tokenId + '.gif'));
// setting gif encoder
encoder.start();
encoder.setRepeat(0); // loop forever
encoder.setDelay(17); // 17 ms per frame for 60 fps
encoder.setQuality(10); // default
// capture frames at 60fps for 0.5 seconds == 30 frames.
const fpsMs = 1 / 60 * 1000;
for (let i = 0; i < 30; i++) {
await gifAddFrame(page, encoder);
await page.evaluate(frameTime => players.forEach((p) => p.getLottie().goToAndStop(frameTime, false)), fpsMs * (i + 1))
}
encoder.finish();
await browser.close();
}
(async () => {
const args = process.argv.slice(2)
if (args.length !== 1) {
console.log("Usage: node index.js <tokenIds>")
process.exit(1)
}
const tokenIds = args[0].split(',')
for (let tokenId of tokenIds) {
await run(tokenId.trim())
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment