記事タイトルを合成した OGP 画像を画像処理機能が充実した CDN、「imgix」で生成してみる

画像処理に特化した CDN である imgix の API を活用して、OGP 画像をわざわざ用意しなくても、記事タイトルなどのテキストとベース画像を合成することで自動的に OGP 画像を生成してみようというお話。

OGP(Open Graph Protocol) の記述は Web ページを作成する際にほぼ確実に行うと思いますが、その中で og:imageog:image:secure_url に指定する画像に関しては何らかの形で用意しなければなりません。

一部の Blog サービスなどでは特にユーザーが OGP 用の画像を用意しなくても、記事タイトルなどのテキスト情報から自動で OGP 用の画像を生成して設定してくれたりしますが、同じ事を自前のサーバで運用している Web サイトでもできないかなと思い立って、そういえば 「imgix」 ってテキストデータからの画像生成機能があるじゃんってことでやってみました。

「imgix」 は、画像処理機能に特化した CDN で、その基本的な使用方法については以前、記事を書いていますので詳しくは下記をご覧ください。

で、なぜ今回これをやろうと思ったかというとですね、自分の会社の Web サイトでお知らせや簡単なコラムなどを書いているとき、OGP 画像を用意するのが正直面倒くせぇなって思ったからなんです。

もともと、年末年始休暇や夏季休暇のお知らせなど、まぁ所謂どうでもよい記事については全記事共通の OGP 画像を作っておいて、CMS で OGP 画像の指定がなければその共通画像を使うっていう風にはしていたので、別に毎回、全ての記事用に OGP 画像の作成をしているわけではないのですが、できれば記事個別に、統一感はありながらも、手間をかけずに OGP 画像を用意したい...... ということでやってみたところ、楽だし、結構いい感じなので記事にまとめてみることに。

何がしたかったのか

下記のような背景となる画像を 1つ用意しておいて、

生成する OGP 画像で背景となるベース画像

この画像に記事のタイトルを合成して、下記のような OGP 画像を作りたかったと(下記の例だと 「記事のタイトルを自動的に合成してOGP画像を生成」 という部分が記事のタイトルですね)。

生成された OGP 画像の例

CMS から記事タイトルなど特定のデータを自動で取得して画像が生成できれば、何もしなくても OGP 画像が用意できるじゃんという。

imgix の Typesetting Endpoint

imgix には、ありがたいことに 「Typesetting Endpoint (日本語だと 「組版エンドポイント」 ですかね)」 という、テキストから画像を生成するための API が用意されています。こいつを利用すると、API に渡した文字列に、様々な効果 (例えば色やサイズ、フォントを指定したり)を加えつつ、画像を生成することができます。

例えば、下記のような各パラメータを付与した URL で API を呼び出すと、

<!-- 下記の URL はわかりやすいように改行してます -->

https://assets.imgix.net/~text?
txt-color=fff
&bg=111
&txt-pad=30
&txt64=[Base64 エンコードされたテキスト]
&txt-font=sans-serif%2CBold
&w=580
&txt-size=34

下記のように画像が返ってくるわけです。

Typesetting Endpoint で生成された画像の例

txt64 というパラメータは Base64 エンコード(URL セーフである必要があります) されたデータが使用できるため、上記のように日本語なども通りますし、下記のように絵文字でも問題なく画像が生成されます。

Typesetting Endpoint で生成された画像の例(絵文字)

この画像の実際のリクエスト URL は下記になります。

<!-- 下記の URL はわかりやすいように改行してます -->

https://assets.imgix.net/~text?
txt-color=fff
&bg=111
&txt-pad=30
&txt64=8J-YgPCfkY3inKg
&txt-font=sans-serif
&w=580
&txt-size=60
&txt-align=center

背景が単色の単純な画像で良ければこれでも十分なんですが、今回は背景画像を用意してテキストを合成したいので、もうひと手間かけました。

画像ファイルに Watermark API を使用してテキスト画像を合成

imgix には、画像に対してウォーターマーク (要するに透かしですね) を合成するための Watermark 関連 API が用意されています。

この中の、mark (Watermark Image URL) を使用し、さらにサイズや位置を指定することで、ベースとなる画像に、前述した Typesetting Endpoint で生成した画像を、ウォーターマークとして合成することができるというわけです。

具体的にどうするかというと、まず、mark パラメータ以外で、背景画像に対して基本的な画像のサイズやウォーターマークの位置などを指定します。

<!-- 下記の URL はわかりやすいように改行してます -->

https://example.imgix.net/image_path/base-ogp.png?
w=1200
&h=630
&fit=crop
&mark-align=center%2Cmiddle

w=1200&h=630 は生成される画像のサイズ (w = 幅 / h = 高さ) ですが、これは現時点で OGP 画像として推奨されているサイズに合わせています。

fit=crop (Resize Fit Mode) は画像をトリミングする際のモード指定ですが、wh と同時に指定することで、指定サイズ内で縦横比を変えず最大となるようにトリミングしてくれます。今回は背景用の画像が元々 1200px × 630px で用意しているので特に指定する必要はないのですが毎回背景になる画像が違いますよ、といった場合は OGP に適したサイズにトリミングしてくれるので便利です。

mark-align (Watermark Alignment Mode) はウォーターマークを画像のどの位置に合成するかを指定するもので、縦方向の位置を topmiddlebottom、横方向の位置を leftcenterright の中からそれぞれ 1つずつ、計 2つをカンマ(,)区切りで指定できます。

例えば 右上なら mark-align=top,right と指定しますし、画像の真ん中にウォーターマークを合成したければ mark-align=center,middle ですね。

実際にはカンマ(,)は URL エンコードしないといけないので、mark-align=top%2Cright だったり、mark-align=center%2Cmiddle となります。

最後に、mark パラメータを使用して、テキストを合成しますが、どうやるかというと、先ほど紹介したテキストから画像を生成する URL がありますよね(下記)。

<!-- 下記の URL はわかりやすいように改行してます -->

https://assets.imgix.net/~text?
txt-color=fff
&bg=111
&txt-pad=30
&txt64=[Base64 エンコードされたテキスト]
&txt-font=sans-serif%2CBold
&w=580
&txt-size=34

このうち、txt64=[Base64 エンコードされたテキスト]txt=[テキスト] に変更した下記のような URL を作成します。

<!-- 下記の URL はわかりやすいように改行してます -->

https://assets.imgix.net/~text?
txt-color=fff
&bg=111
&txt-pad=30
&txt=記事タイトル
&txt-font=sans-serif%2CBold
&w=580
&txt-size=34

こいつを丸ごと Base64 エンコード (URL セーフ) した上で、mark64 パラメータ (mark で Base64 エンコードされたデータを扱うためのパラメータ) にぶっ込みます(txt64 を使用せず、txt パラメータにそのままテキストを指定するのは 2重に Base64 エンコードされてしまわないようにです)。

例えば下記のような感じになりますね。

mark64=aHR0cHM6Ly9hc3NldHMuaW1naXgubmV0L350ZXh0P3c9ODYwJnR4dC1jb2xvcj1mZmYmdHh0LXNpemU9MzUmdHh0LWxlYWQ9MSZ0eHQtcGFkPTIwJmJnPTgwMDAyMjI4JnR4dC1mb250PXNhbnMtc2VyaWYmdHh0LWFsaWduPWNlbnRlciZ0eHQ96KiY5LqL44Gu44K_44Kk44OI44Or44KS6Ieq5YuV55qE44Gr5ZCI5oiQ44GX44GmT0dQ55S75YOP44KS55Sf5oiQ

これを先ほどの URL と組み合わせると下記のように URL が完成します。こいつを OGP 画像の URL として設定してあげればよいということになります。

<!-- 下記の URL はわかりやすいように改行してます -->

https://example.imgix.net/image_path/base-ogp.png?
w=1200
&h=630
&fit=crop
&mark-align=center%2Cmiddle
&mark64=aHR0cHM6Ly9hc3NldHMuaW1naXgubmV0L350ZXh0P3c9ODYwJnR4dC1jb2xvcj1mZmYmdHh0LXNpemU9MzUmdHh0LWxlYWQ9MSZ0eHQtcGFkPTIwJmJnPTgwMDAyMjI4JnR4dC1mb250PXNhbnMtc2VyaWYmdHh0LWFsaWduPWNlbnRlciZ0eHQ96KiY5LqL44Gu44K_44Kk44OI44Or44KS6Ieq5YuV55qE44Gr5ZCI5oiQ44GX44GmT0dQ55S75YOP44KS55Sf5oiQ

(URL セーフな) Base64 エンコードの方法

CMS を使用しているなら、記事のタイトルなどを取得して、まずはウォーターマーク画像の生成用 URL を生成 (例えば Movable Type なら下記のようにテンプレートタグと組み合わせる) します。

<!-- Movable Type テンプレートタグと組み合わせた例
     下記の URL はわかりやすいように改行してます -->

https://assets.imgix.net/~text?
txt-color=fff
&bg=111
&txt-pad=30
&txt=<$mt:EntryTitle$>
&txt-font=sans-serif%2CBold
&w=580
&txt-size=34

これを Base64 エンコードした上で、残りの URL と組み合わせて、テンプレート上に書き出すといったことができれば、OGP 画像が自動的に生成されますね。

URL セーフな Base64 エンコードとは、Base64 エンコードした上で、「+」を「-」に、「/」を「_」に変換した上で「=」を取り除いたものです。

PHP をテンプレートなどに直接書ける状況であれば、例えば下記のような関数を使用することで URL セーフな Base64 エンコードができると思います。

function base64_encode_url($string) {
  return str_replace(['+','/','='], ['-','_',''], base64_encode($string));
}

Movable Type の場合、ダイナミックパブリッシングを使用しておらず、テンプレートも HTML で書きだしている場合はファイル生成時にエンコード処理を行わないといけません。グローバル・モディファイアに Base64 エンコードを処理してくれるようなものがあればよいのですが、残念ながらないので、プラグインを書くしかないですね......

ということで簡単にですが Movable Type に base64_encode グローバル・モディファイアを追加するプラグインを書きました。

ちゃちゃっと書いたのでコードは雑かもしれませんが、ご興味ある方はご利用ください。

imgix Sandbox

imgix には、実際の画像を使用しながら、ブラウザ上でパラメータの調整などを行える Sandbox が用意されています。下記リンク先で、画像の URL を指定し、Sandbox を開くと、そこでパラメータを足したり値を調整したりして、実際にどういう風に画像が生成されるかを確認することができます。

事前にどんな感じの画像になるのか確認したいなんていう場合には便利ですね。

imgix Sandbox の例

関連エントリー

Social Share