こちらの記事で Hugo で管理しているブログを GitHub Pages から Firebase Hosting に移行した話を書いたのですが、このタイミングで OGP 画像にも対応したのでやり方を書いておきます。
OGP 画像とは
OGP とは Open Graph Protocol の略称で、めちゃくちゃ雑に説明すると SNS 等でリッチコンテンツを生成するための HTML の meta タグの仕様です。
<meta property="og:site_name" content="IMDb" />
のような感じで、 property
に og:xxx
を付与して色々なメタ情報を宣言していくことができます。
Twitter だと OGP にも対応しつつ、Twitter Card という仕様でも Twitter で URL を展開する場合に引用される情報を規定しています。
Twitter Card を設定していると、以下のように Twitter 上で展開されます:
ImageMagick で任意のテキストを配置した画像を生成する
今回追加したい OGP 画像についてやりたいことは、
- 記事ごとに画像を生成したい
- 画像には記事のタイトルを入れたい
- 記事を公開したら自動的に OGP 画像が生成されるようにしたい
でした。
記事ごとの画像の生成については、ImageMagick を使ってブログ記事で使う共通の画像に記事のタイトルを追加する方法をとることにしました。 ImageMagick ではテキストを扱う機能も提供しており、ここのページにも例が沢山載っています1。
まずは記事で共通の画像を作らなければいけないのですが、 Adobe Creative Cloud Express というブラウザ上で画像編集できるサービスを使って作ってみました。 基本的に無料なのですが、フォントを自分で用意したい場合は有料プランにする必要があります。3ヶ月は無料で試せるようです。
こんな感じでアイコンの画像をアップロードしたり、テキストを配置したりしてイメージを固めました。
編集が終わったら、記事のタイトル部分のパーツは一旦削除して画像に書き出します。
この画像を使って、ImageMagick で任意のテキストを追加していきます。
LC_CTYPE="ja_JP.UTF-8" convert \
-fill '#333333' \
-gravity west \
-size 1000x320 \
-font NotoSansJP-Black.otf \
caption:'色即是空の教義は 2000 年の時を超えて Event Sourcing Model として受け入れられている' \
base.png \
+swap \
-geometry +80+50 \
-composite out.png
改行位置がイマイチですが…、これで任意のテキストを入れて画像を生成することはできました。
Hugo の記事ごとに OGP 画像を生成する
Hugo の記事ごとの画像は、以下のように配置していくことにしました。
public
└── images
└── meta
├── og
│ ├── blog-ja
│ │ ├── choco60
│ │ │ └── og.png
│ │ │
│ ... ...
└── twitter
├── blog-ja
│ ├── choco60
│ │ └── twitter-card.png
... ...
画像のURL としては {デプロイ先のベース URL}/images/meta/{og|twiter}/{ページの relational path}
となります。
Hugo のテーマファイルに meta タグを追加する
Hugo のテーマファイルの記事の HTML 部分に、 OGP 画像の meta タグを追加します。
前述した画像の配置場所を指すようにテンプレート変数を交えて書いていきます。
<meta name="twitter:image" content="{{ .Site.BaseURL }}images/meta/twitter{{ relURL .Permalink }}twitter-card.png" />
GitHub Actions で OGP を生成する step を追加する
- 記事ごとの画像の生成
- Hugo で生成される HTML の meta タグ設定
ができたので、CI で自動的にこの画像が追加されるようにしていきます。
今回はブログを管理しているリポジトリに、以下のように画像生成用のスクリプトや必要なファイルを置きました。
tools
├── ogp
│ ├── NotoSansJP-Black.otf
│ ├── base.png
│ └── generate.sh
...
画像生成のシェルスクリプトはこんな感じです。かなりやっつけですが…。 全部のコンテンツの画像を生成するのでかなり無駄がありますが、まあ後で直せばいいでしょう!
#!/bin/bash -xe
# $1 = caption text
# $2 = path to save an image
cnv() {
LC_CTYPE="ja_JP.UTF-8" \
convert -fill '#333333' \
-gravity west \
-size 1000x320 \
-font tools/ogp/NotoSansJP-Black.otf \
caption:"$1" \
tools/ogp/base.png \
+swap \
-geometry +80+50 \
-composite \
$2
}
export -f cnv
# $1 = target; format is {title},{permalink}
generate() {
TITLE=$(echo $1 | cut -d',' -f 1)
DIRPATH=$(echo $1 | cut -d',' -f 2 | awk '{gsub("https://blog.mookjp.io/", ""); print}')
TWITTER_DIRPATH=public/images/meta/twitter/${DIRPATH}
OG_DIRPATH=public/images/meta/og/${DIRPATH}
mkdir -p ${TWITTER_DIRPATH}
mkdir -p ${OG_DIRPATH}
cnv "${TITLE}" ${TWITTER_DIRPATH}twitter-card.png
cnv "${TITLE}" ${OG_DIRPATH}og.png
}
export -f generate
hugo list all | tail -n +2 | awk -F ',' 'BEGIN {OFS=","} { if ($7 == "false") print $3,$8 }' |\
xargs -P 12 -I {} bash -c 'generate "$@"' _ {}
これを Github Actions の Workflow で実行できるように yaml を編集します。
- ImageMagick のインストール
- 画像生成スクリプトの実行
という step を書いています:
name: Deploy to Firebase Hosting on main branch
'on':
push:
branches:
- main
jobs:
build_and_preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y imagemagick
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.91.2'
- name: Build pages
run: hugo --minify -t simple
- name: Build OGP images
run: ./tools/ogp/generate.sh
- name: Deploy
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_FOOBAR }}'
channelId: main
projectId: foobar
こんな感じで、Hugo で管理しているサイトで OGP 画像を用意することができました。
結構やっつけなので、
- 更新した記事のみ、画像を再生成したい
- GitHub Actions でキャッシュ使いたい
とか改良ポイントはあるのですが、また後々直していけばよいかなと思います。
-
サブドメインが legacy になっている…のですが、新しいバージョンの 7.1.0 でもこのページで紹介されている例は使えました。もっといいやり方はあるかもしれませんが深追いしていません。 ↩︎