Heroku上のRailsアプリケーションで、OGP画像を動的に生成するための方法をまとめました。
準備
ImageMagick
以前はherokuに別途buildpackを追加する必要があったようですが、現在は必要なくなったようです。
Imagemagick buildpack for Heroku-18 stack
そのため、herokuの最新stackを使えば特に何もする必要は有りません。
MiniMagick
RubyからImageMagickを使うためのgemです。
CarrierWave
ファイルをアップロードするためのgemです。
日本語フォントファイル
今回は画像にテキストを合成して画像生成するので、フォントファイルを使います。
実装
今回はUserモデルが存在するアプリケーションに対して、UserのOGP画像を生成する処理を追加してみようと思います。
やること
- gem追加
Gemfileに以下を追加
gem 'carrierwave' gem 'mini_magick' gem 'fog-aws' # S3にアップロードするために追加
その後
$ bundle install
- ogpカラム追加
migrationファイルを追加します。
class AddOgpToUser < ActiveRecord::Migration[5.2] def change add_column :users, :ogp, :string, default: "" end end
- ogpカラムをCarrierWaveにマウント
Uploaderを追加します。
rails g uploader UserOgp
UploaderをUser.ogpに紐付けます。
# model/User.rb mount_uploader :ogp, UserOgpUploader
- OGP画像生成処理
OGPはベースの画像にUserの名前を合成して画像にする仕様とします。
OGP画像生成処理はRubyのClassとして実装します。 ほとんど↓を参考にしました。
【10分でできる】Railsに画像の動的生成機能をサクッと追加する
require 'mini_magick' class OgpCreator BASE_IMAGE_PATH = '/path/to/ogp' GRAVITY = 'center' TEXT_POSITION = '0,0' FONT = '/path/to/font-file' FONT_SIZE = 65 INDENTION_COUNT = 16 ROW_LIMIT = 8 def self.build(text) text = prepare_text(text) image = MiniMagick::Image.open(BASE_IMAGE_PATH) image.combine_options do |config| config.font FONT config.fill 'white' config.gravity GRAVITY config.pointsize FONT_SIZE config.draw "text #{TEXT_POSITION} '#{text}'" end end private def self.prepare_text(text) text.to_s.scan(/.{1,#{INDENTION_COUNT}}/)[0...ROW_LIMIT].join("\n") end end
- OGP画像生成呼び出し
今回はプロフィールを変更したときにOGPを生成したいので、UsersControllerに処理を追加します。
# UsersController def update # 略 if current_user.update(user_params) # プロフィール更新したらogpを生成 # 生成した画像をアップロード # アップロード先のパスをogpに登録 ogp_image = OgpCreator.build(current_end_user.name) current_end_user.update!(ogp: ogp_image) else # 略 end end
まとめ
以上の方法で動的に生成することができました。
minimagickをさらに調べれば画像操作で色々なことができそうです。
今回のサンプル実装ではとりあえず画像生成するところまでをゴールとしましたが、改善はできそうです。
OgpCreator
もConcernにすると良いかもしれません- OGP生成処理Workerに任せたほうがパフォーマンスの観点から良いかもしれません
以上です。