Cloud Functions for Firebaseで動的OGP画像を作成する
こんにちは、皆さんいかがお過ごしでしょうか。
今回はCloud Functions for Firebase(以降firebase functions)で動的OGP画像を生成、返却するAPIを作ります。実装だけ見たい!という方は背景は読み飛ばしてください。
背景
最近仕事で動的にOGP画像を作る必要があり、以下の方法を検討しました。
- 画像変換サービスcloudinaryを使う
- vercelでog-imageを使う
- firebase functionsで独自実装をする
まず一番楽なのはcloudinaryを使うことだと思います。cloudinaryはクラウドの画像変換サービスで、あらかじめcloudinaryにアップロードした画像をベースに、サイズ、文字、レイアウトなどなどをURLで指定することで、加工された画像をレスポンスで受け取ることができます。CDNを内蔵しており、一度作成した画像は素早く返却されるというところも魅力の一つです。軽く触ってみるには以下の記事がわかりやすいです。
ただ今回の要件にOGP画像内にユーザ画像を動的に挿入するというものがありました。cloudinaryで画像を複合するにはあらかじめ複合する画像をサービスにアップロードしておく必要があり、管理工数の観点から今回は採用を見送りました。(※この記事で画像の埋め込みまでは紹介しません。が、拡張は簡単です。)
また、cloudinaryは基本的にgoogle fontsに対応していると言っているものの、対応していないものも多々あります。お気をつけください。
続いてvercelでog-imageを使う方法です。
こちらのリポジトリはvercel公式から提供されているもので、serverless functionsによる実行を想定しています。テンプレートのようなもので、フォークしてカスタマイズして使ってね!と言った感じです。
中身はHTMLをpuppeteerで描画し、スクリーンショットを撮って画像を作成するという処理になっており、HTMLを自分の表示したい画像に合わせて書き換えることで、簡単にオリジナルのものが作れます。
これ見つけたとき、めっちゃ便利やん!!と興奮したのですが、コストの面から見送りました。
vercelは商用だと開発者1人あたり20ドルからとなっており、少々お高いです。また本プロジェクトはfirebaseをメインに使っており、管理プラットフォームを増やしたくないという背景もありました。
そして最終的にfirebase functionsで自前実装ちゃえ!という結論になりました。実際、上述のog-imageは複雑な処理をしているわけではないので、簡単に転用できます。(verselのserver lessfunctions実行部分をfirebase functions実行用に置き換えるだけ)
実装
先述の通り、og-imageのコードを参考に実装します。
HTMLで画面を作成し、puppeteerで作った仮想ブラウザにHTMLを表示、スクリーンショットを撮る、という内容です。
他の方法ではcanvasを使うものなどがあります。
まず puppeteer-coreとchrome-aws-lambdaをインポートします。
npm i puppeteer-core chrome-aws-lambda
chrome-aws-lambdaを使わずにpuppetterのみでもできますが、使うと速度が速くなるという報告があり、こちらを使用します。名前的にlambda専用感がありますが、firebase functionsでも使えます。
続いてコードです。
コードの通りなのですが、軽く補足です。
puppeteerでブラウザを作成する際にオプションを指定しますが、cloud functionsで実行する場合とローカル(firebase emulator)で実行する場合でオプションの中身を変えています。
また、HTMLを変更することで好きな画像を作成することができます。動的要素(上記コードではタイトル)はパスやURLパラメータで指定します。
そんな感じで作成されたのが以下の画像です。
お疲れ様でした。