Kalsarikannint

お問い合わせ

サイト内検索

記事タイトルが埋め込まれたOGP画像を作る

あけましておめでとうございます。Kalsarikannintのフロントエンド担当・daiです。

QiitaとかZennとかイマドキのサイトをSNSなどでシェアしたとき、表示されるOGP画像に記事のタイトルが埋め込まれてるのをよく見かけると思います。

Kalsarikannintもイマドキの技術ブログも目指したい(願望) ので、この年末年始休みを使って、以下の各ページを参考に、WordPressで構築されているこのブログでもそれを実装してみたので、その方法などを紹介していきます!

参考:

つくったもの

最終的には、 functions.php に以下のコードを追記することで、記事を保存したタイミングで /wp-content/uploads/ogp/ogp_{記事ID}.jpg として記事タイトルが埋め込まれた画像を生成することができるようになりました。

// functions.php への記載内容
/**
 * Create OPG Image
 * 
 * タイトルを利用したOGP画像を生成する
 */
function create_ogp_image($post_id, $post) {
    $file_name = 'ogp_'.$post_id.'.jpg';
    $title = $post->post_title;
    $base_image = get_template_directory().'/images/ogp_template.jpg';
    $image = imagecreatefromjpeg($base_image);
    $color = imagecolorallocate($image, 0, 0, 0);
    $fontfile = get_template_directory().'/fonts/ZenKakuGothicNew-Black.ttf';

    $size = 36;
    $breakpoint = 20;

    if (mb_strwidth($title, 'UTF-8') > 120) {
        // 全体が60文字(= 20文字 * 3行)以上ならフォントサイズ変更 + 改行位置も変更
        $size = 20;
        $breakpoint = 35;
    }

    if (mb_strwidth($title, 'UTF-8') > $breakpoint * 2) {
        $max_count = mb_strwidth($title, 'UTF-8') / $breakpoint * 2;

        // 禁則処理に該当する文字
        $specialChars = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'ー', 'ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ッ', 'ャ', 'ュ', 'ョ', 'ヮ', '、', '。', '(', ')', '「', '」', '【', '】', 'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ', 'っ', 'ゃ', 'ゅ', 'ょ', 'ゎ'];

        $last_pos = 0;
        for ($count = 0; $count < $max_count; $count++) {
            for ($pos = $breakpoint + $last_pos; $pos > $last_pos; $pos--) {
                $char = mb_substr($title, $pos + 1, 1, 'UTF-8');

                if (!in_array($char, $specialChars)) {
                    // 禁則処理に触れない = 改行OK
                    $title = mb_substr($title, 0, $pos + 1)."\\n".mb_substr($title, $pos + 1);
                    $last_pos = $pos - 1;
                    break;

                } else if ($pos === $last_pos) {
                    // 禁則処理だらけなら強制改行しちゃお!
                    $title = mb_substr($title, $last_pos, $last_pos + $breakpoint)."\\n".mb_substr($title, $last_pos + 1);
                    $last_pos = $pos;
                    break;
                }
            }
        }
    }

    $angle = 0;
    $x = 100;
    $y = 300 + $size;

    // 文字列挿入
    imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $title);

    // OGP画像の保存場所がなければ作る
    if (!file_exists('wp-content/uploads/ogp')) {
        mkdir('wp-content/uploads/ogp', 0777);
    }
    
    // ファイル名を指定して画像出力
    imagejpeg($image, 'wp-content/uploads/ogp/'.$file_name);
}
add_action('save_post', 'create_ogp_image', 10, 2);

加えて、 functions.php へ以下のようなコードも追記し、記事ページでは上記で生成されたOGP画像を og:image として指定するように設定しています。

// functions.php への記載内容
add_action('wp_head', function() {
    $og_image = get_template_directory_uri().'/images/ogp_image.jpg';

    if (is_single()) {
        // 個別記事ページ
        $og_image = get_site_url().'/wp-content/uploads/ogp/ogp_'.get_the_ID().'.jpg';
    }

    echo '<meta property="og:image" content="'.$og_image.'" />';
});

上記の記述を追記するほかに、以下のファイルを用意する必要があります。

  • フォントファイル(テーマファイルディレクトリ配下の fonts ディレクトリを作成し保存)
  • テンプレートになる ogp_templete.jpg ファイル(テーマファイルディレクトリ配下の images ディレクトリへ保存)
  • 記事ページ以外のOGP画像となる ogp_image.jpg ファイル(同上)

OGP画像の生成方法

イマドキの環境を使っていれば、サーバーサイドでNode.jsを動かして、canvasを使って画像と文字の合成を行ったりするようですが、このサイトはCMSにWordPressを使っていることもあり、ごくごく一般的なレンタルサーバーで運用しているので、PHPのGDというライブラリを使って実装していきます。

GDライブラリがめちゃくちゃ優秀で、画像と文字の合成くらいなら、少ない記述であっという間に実装できてしまいました。

function createimage($title, $file_name) {
    $base_image = './images/ogp_templete.jpg';
    $image = imagecreatefromjpeg($base_image);
    $color = imagecolorallocate($image, 0, 0, 0);
    $fontfile = './fonts/ZenKakuGothicNew-Black.ttf';

    $fontsize = 36;
    $angle = 0;
    $x = 100;
    $y = 300 + $fontsize;
    
    // 合体っ!
    imagettftext($image, $fontsize, $angle, $x, $y,$color, $fontfile, $title);
    
    // 保存
    imagejpeg($image, './images/'.$file_name);
}

createimage("Hello World", "hw.jpg")

用意するのは、上記の関数が書かれたPHPファイルと、ベースとなる画像、それからフォントファイルです。フォントファイルはGoogleFontsから「Download」をクリックすると取得できます。

また、このままだと長いタイトルが来たときに画像の右端を突き抜けてしまうので、文字数に応じた改行処理を入れる必要があります。さらに、日本語には禁則処理といって改行してはいけない / しないほうがいい箇所があるので、それも力技で実装していきます。

禁則処理については、次のページを参考にしました:PHPで禁則処理を強引にやる | 無趣味の戯言

WordPressへの組み込み

とりあえずPHPだけでどうにかできることは分かったので、次はWordPressへの組み込みを考えていきます。

WordPressには、JavaScriptでいうところの「イベント」のような機能として「アクションフック」があり、記事を保存したタイミングで save_post フックが発火するようになっています。

ということで、 functions.phpsave_post フックをトリガーにしたOGP画像生成の関数を追記していきます。

function create_ogp_image($post_id, $post) {
    // 画像を生成する処理を記載
}

// save_post フックで create_ogp_image 関数をコールする
add_action('save_post', 'create_ogp_image', 10, 2);

add_action() 関数は、以下の引数を取ります。第三・第四引数は省略可能ですが、今回は第四引数で 2 を与えて投稿の内容も取得したかったので、第三・第四引数も指定しています。

  • 第一引数:トリガーとなるフック名
  • 第二引数:実行する関数名
  • 第三引数:プライオリティ(実行の優先順位)(初期値:10)
  • 第四引数:実行する関数が受け取る引数の数(利用するフックに応じて選択できる値が変わる)(初期値:1)

create_ogp_image() の中身は長くなるので、記事冒頭のコードからご覧ください…。

これで、記事を保存したタイミングで、 /wp-content/uploads/ogp/ogp_記事ID.jpg の画像ファイルが生成されるようになりました。

この記事でいうと、以下の画像が該当します。

headへのmetaタグの出力

画像が生成できるようになったので、次に、 <head> 内にOGP画像をお知らせするタグを埋め込んでいきます。

こちらも同じく functions.php に記述していきます。

add_action('wp_head', function() {
    $og_image = get_template_directory_uri().'/images/ogp_image.jpg';

    if (is_single()) {
        // 個別記事ページ
        $og_image = get_site_url().'/wp-content/uploads/ogp/ogp_'.get_the_ID().'.jpg';
    }

    echo '<meta property="og:image" content="'.$og_image.'" />';
});

wp_head フックが呼ばれたときに、上記処理を実行しています。今回はコールバック関数を直接記述するパターンでやってみました。関数名考えたくないときにはこのパターンもおすすめです。(どっちかで統一しろ

実際には、 og:titleog:url などもページの種類ごとに吐き出させているのですが、上記のコードでは og:image に焦点を当てて、それ以外は消しています。OGPの詳細は以下のページを参照してください。

https://ogp.me/#metadata


以上が、WordPressで記事のタイトル入りOGP画像を自動生成する一連の流れになります。

サーバーサイドでNode.jsを動かすことなく、PHPのGDライブラリだけでもここまで柔軟に合成処理が行えるのはなかなか魅力的だと思います。実際に実装してみると意外とシンプルなので、テーマやプラグインのカスタマイズに慣れている方であれば、すぐに組み込むことができるかと思います。ぜひ、自分好みに拡張・応用しながら、技術ブログやWordPressサイトでイマドキなOGP画像を作ってみてください!

Author dai

地方に住みながら、フルリモート情シスおじさんしてます。
フロントエンド開発とkintoneアプリのカスタマイズやプラグイン開発が得意分野です。
好きなビールは一番搾り。

実務で身についたAIとコーディングするコツ

こんにちは。Kalsarikannintのフロントエンド担当・daiです。 仕事を楽にするために、プログラムによる自動化・効率化を日々実践しているのですが、最近ではもっぱらAIを使ったコーディングが中心になっています。想像以上に実用的で、正直なところ「もう戻れないかも」と感じているくらいです。 以前は、ブログ記事を書くときのAIの使い方をまとめましたが、今回は僕が本業で培った経験をお伝えできればと思います。 https://kalsari.net/tool/128 本記事では、AIツールを使った実際のコーディング経験から得た知見や、効果的な活用方法について共有します。「AIでプログラミングができるらしいけど、実際どうなの?」と気になっている方の参考になれば幸いです。 使っているAIツール 現在、メインで使用しているのはChatGPTです。特に理由があるわけではなく、最初に触れたのがこれだったからという、わりと適当な理由だったりします。 GitHub CopilotやCursorなどの有料ツールも試してみたんですが、現時点では自分の用途にお
develop

【Parsec】Mac→WindowsでIME切り替えを快適にする方法

こんにちは。Kalsarikannintのフロントエンド担当・daiです。 MacからParsecを使ってWindowsにリモートアクセスして作業する機会が増えてきたのですが、地味にストレスだったのが日本語入力の切り替えなんですよね。 Macには「全角/半角」キーが存在しないので、リモート先のWindowsでIMEのON/OFFを一発で切り替えることができません。ドキュメント作成やコーディングなど、日本語と英語を頻繁に切り替える作業では、この小さな不便が積み重なって大きなストレスになっていました。 そこで今回は、Karabiner-ElementsとGoogle日本語入力を組み合わせて、Mac側の「英数」「かな」キーでリモート先WindowsのIMEを快適に操作できるようにする方法を紹介します。同じ悩みを抱えている方の参考になれば幸いです。 解決方針の全体像 今回の設定は、以下の流れでキー入力を変換していきます: Mac: 英数/かなキー → Karabiner-Elementsで変換 → F15/F16キー ↓ Parse
tool

AIでブログ執筆を効率化してみた ― 30分で“読まれる記事”を作るまでの流れ

こんにちは。Kalsarikannintのフロントエンド担当・daiです。 今日は「AIを使って記事執筆をどう効率化しているか」という話を書いてみようと思います。 「AIで記事を量産する!」というよりは、あくまでAIを“書く力を補助してくれる相棒”として使う感じです。 いろいろ試してみた中で、今のところしっくりきているやり方を紹介します。 事前準備:AIに“自分の文体”を覚えさせる まず最初にやっておくことが、AIに自分の文体を学習させておくことです。これは一度やっておけば、以降の執筆で毎回使い回せます。 やり方はシンプルで、過去に自分が書いた記事を3本ほどAIに渡して、こんな感じで聞くだけです👇 次の3つは私が執筆したブログ記事です。私の文章のクセ、文体などの特徴をまとめてください。 --- # タイトル ## 見出し 本文 (◯◯の画像) ## 見出し 本文 (◯◯のコード) --- # タイトル 本文... --- AIが分析してくれた「文体の特徴」をメモして保存しておきます。これが、後半の“清書フェーズ”で重要になっ
tool