LoginSignup
6
3

More than 1 year has passed since last update.

ブラウザのスクショを繋げてGIF画像を作ろう【Puppeteerを使って爆速】

Last updated at Posted at 2019-03-19

ユーザーが入力した俳句からGIF画像を生成しています。
これはサーバーでブラウザ(Chrome)を立ち上げ、そのスクリーンショットを繋げることで生成されています。

###################################################
gifjs (22).gif
###################################################
↑こんな感じのGIFが作れます。ぜひ実際にやってみて下さい。

どうやってGIF画像を作るのか、コード付きで解説

今回使用する言語はNodejsです。
まずは適当な空ディレクトリに移動して、以下のコマンドを実行して下さい。

$ npm init -f
$ npm install puppeteer  png-js gifencoder

使用する3つのライブラリを簡単に説明します。
まずPuppeteerは、GUIを操作することなく、プログラムからAPIでブラウザ(Chrome)を制御できるNode.jsで作られたライブラリ です。今回はPuppeteerのスクリーンショット機能を利用します。
png-jsはPuppteerで撮ったスクショのPNGデータをNodeで扱うためのライブラリで、gifencoderはpngからGIFを作るためのライブラリです。

次に、index.jsを作成し、次のようにして下さい。一回コピペして頂き、動作を確認するのが良いと思います。

index.js
const fs = require('fs');
const puppeteer = require('puppeteer');

const GIFEncoder = require('gifencoder');
const PNG = require('png-js');
function decode(png) {
  return new Promise(r => {
    png.decode(pixels => r(pixels))
  });
}

async function gifAddFrame(page, encoder) {
  const pngBuffer = await page.screenshot({clip: {width: 1024, height: 200, x: 0, y: 0}});
  const png = new PNG(pngBuffer);
  await decode(png).then(pixels => encoder.addFrame(pixels));
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false, slowMo: 0,
  });
  const page = await browser.newPage();
  page.setViewport({width: 1024, height: 200});
  const text = '私は猫になりたい';
  const html = `<div id="main" style="font-size: 100px;">${text[0]}</div>`;
  await page.setContent(html, {
    waitUntil: ['networkidle0']
  });

  // record gif
  var encoder = new GIFEncoder(1024, 200);
  encoder.createWriteStream()
    .pipe(fs.createWriteStream('test.gif'));

  // setting gif encoder
  encoder.start();
  encoder.setRepeat(0);
  encoder.setDelay(150);
  encoder.setQuality(10); // default

  for (let i = 0; i < 10; i++) {
    await gifAddFrame(page, encoder);
    await page.evaluate(`document.getElementById("main").innerHTML = '${text.slice(0, i + 1)}'`)
  }

  // finish encoder, test.gif saved
  encoder.finish();

  await browser.close();
})();

そして実行します。

$ node index.js

動作が終了すると、test.gifというファイルが出来ているはずです。
それを開くと、次のような画像が出来ています!
gifjs (22).gif

詳しく解説

先ほどのコードを読み解くための解説をします。

全体の流れは
PuppeteerでHTMLをレンダリングさせる(この時、「私は猫になりたい」の、「私」だけをレンダリングします。)
以下ループ
→スクショを撮る
→gifencoderにスクショのデータを読ませる
⇨Puppeteerに、ブラウザでJSを実行するように指示する。

です。最後のJSを実行というのは、

await page.evaluate(`document.getElementById("main").innerHTML = '${text.slice(0, i + 1)}'`)

の部分です。ブラウザが表示するHTMLを変えるようなJSを実行することで、アニメーションを作ることが出来るのです。
あとはコードを読んでもらえると、理解できると思います。

まとめ

五七五メーカー」を作るにあたり、どうすれば良いか試行錯誤したところ、この形になりました。
GIF生成が出来るようになると、面白いサービスがたくさん出来そうでワクワクしますね。
最後まで読んでいただきありがとうございます。いいね、ストック、コメントをお待ちしております。
それでは、最後に一句。
gifjs (24).gif

終わりに

私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3