こんにちは。ペロリ 開発部の池袋です。
今回は Ruby on Rails における自動再生動画のアップロード周りの話をします。
MERY ではアプリ・Web どちらも動画に対応しており色々なところで動画を使っています。
動画に対応することでコンテンツをよりリッチにユーザに届けることを目指しています。
例)《読者プレゼント》スキマ時間でもっと可愛く!MERYのオススメ動画をチェック
MERY の自動再生動画の概要
アプリと Web(PC)では S3 に置いた動画をそのまま自動再生で流していますが、Web(スマホ) では動画を分割した画像を js でコマ送りにして表示しています。
Rails には video_tag
という video タグを生成してくれるメソッドがあり、一般的にはこのメソッドを使って動画を再生するのですが、
Web(スマホ)で再生しようとすると OS のプレイヤーが立ち上がってしまいインラインでの自動再生ができないため上のようなやり方をしています。
インラインでの自動再生には他にも GIF アニメーションや、video タグのシークバーを毎フレームずらしながら内容を canvas に描画するといった方法があります。
しかし、前者には適当な画質を保とうとするとファイルサイズが大きくなりすぎてしまう問題があり、後者には手元の Android で動かない(かつ CPU を大量に使う)という問題があったため上記のやり方を採用しました。
そのため動画登録は動画ファイルを S3 に置くだけではなく、動画を画像に分割して S3 にアップロードする処理も加わります。
さらに、動画が読み込まれるまでの間に表示しておく画像として動画のサムネイルも保存しておく必要があります。
以下、動画登録の流れに沿ってそれぞれどのように処理しているか説明していきます。
動画登録の流れ
Web(スマホ)用に動画を画像分割
アップロードされた動画はまず画像に分割されます。
画像の分割処理には jani-strip-maker を使っています。
動画の再生に使用する画像は動画を一コマずつではなく、複数のコマをくっつけて一枚の画像にしています。
複数コマで一枚にするのは画像の圧縮効率をあげるためとリクエスト数を減らすためです。
この gem では ffmpeg を使用して動画をコマごとの画像に変換し RMagick を使って複数のコマを一つの画像にしています。
使い方
以下のように書くだけで動画の画像分割とその合成まで行ってくれます。
options = Jani::StripMaker::TranscodeOptions.new options.fps = 15 options.width = 300 options.height = 200 Jani::StripMaker::Movie.new( movie_filepath: "#{動画ファイルへのパス}", transcode_options: options ).to_strips.each(&:write)
ただし、この gem は動画を画像に分割する際に利用する ffmpeg のコマンドのオプションが決め打ちになっています。
渡せるオプジョンは fps
, width
, height
の三つです。
これら三つのオプションは必ず渡す必要がありますし、これら以外のオプションを渡すことはできません。
さらに bitrate
のオプションは 50000k
で gem にハードコードされています。
メンテナンスがあまりされていないこともあり README の通りに書いても動かないといった問題などもあるのですが、全体のコード量が少ないためいざという時はパッチを当てればいいだろうということで導入しました。
ちなみに分割された画像をコマ送りに再生するのは mobile-videoplayer.js を使っています。
動画ファイルを S3 にアップロード
動画ファイルのアップロードには MERY で以前から画像のアップロードに使用している Paperclip を使っています。
画像のときと同じように Model に以下のように書くと動画とさらにサムネイルもアップロードすることができます。
class Movie < ActiveRecord::Base has_attached_file :video, styles: { thumb: { format: :jpg }, } validates_attachment_content_type :video, content_type: ['video/mp4'] end
ちなみにアップロードされた動画の URL は movie.video.url
のように書くと取得できます。サムネイルに関しては movide.video.url('thumb')
です。
また、動画の保存時にフォーマット変換を行っています。
iOS で動画を再生するために H264 のプロファイルを Baseline の Level 3.1 に指定し(参考:iOS Developer Library )、
プログレッシブダウンロード再生をするためにメタ情報をデータの前に持って行っています。
このフォーマットの変換には paperclip-av-transcoder を使っていて、
下のように styles
と並列に指定することで ffmpeg で動画フォーマットを変換する際にオプションとしてパラメータを渡すことができます。
class Movie < ActiveRecord::Base has_attached_file :video, styles: { thumb: { format: :jpg }, }, mobile: { format: 'mp4', convert_options: { output: { :'c:v' => 'libx264', :'profile:v' => 'baseline', :'level:v' => '3.1', :movflags => 'faststart', } } }, processors: [:transcoder],
ただし、paperclip-av-transcoder を使うとデフォルトでは 3s の1フレーム目を取得するようになってしまいます。(ソースのデフォルト値を設定している箇所)
そのため動画の最初の画像をサムネイルに使いたい場合は styles
の中で time
を 0
に指定してあげる必要があります。
styles: { thumb: { format: :jpg, time: 0 }, }
これで自動再生に必要な動画とそれを分割した画像を保存することができました。
まとめ
Rails で自動再生動画をアップロードする際の基本的なやり方や気をつけるべき点などを書きました。参考にしていただければと思います。
ペロリではエンジニアを募集しています。ご応募お待ちしております