#8「夏の思い出を自動的にWebに上げ続ける話」tech.kayac.com Advent Calendar 2013

こんにちは、@doima_ です。 tech.kayac.com初投稿でございます。

クライアントワーク事業部で主にphpやrubyの案件をやったり、Arduinoをいじっていた経歴の持ち主なのでデバイス系案件をやったりもしています。

今回は、今年の夏に行った、GoProをフラフープに取り付け、それをまわしてもらった動画を次々にWebにアップするイベントのシステム周りの話をちょっとしようかと思います。 この企画では、機材選出から現場での設置、システムの構築などを行い、のべ12日間に渡るイベントをぶっ続けでやりました。

システムとしてはGoProで撮った動画をWifi経由で現地に置いたマシンに転送し、自動的にサーバにアップロードする感じです。アップロード対象サーバはバックアップ兼YouTubeへのアップロード用として活用しました。現地マシンのリソースは動画の編集のみに割いておきました。構成としてはこんな感じです。

hulaimage.png

動画ファイルはYouTubeから都度取ってきて、その他の生成された画像はS3に保管するというかたちになっております。 その他現地でも80インチディスプレイに編集済動画を表示しておりました。サーバとローカルマシンのデータをAPIを作成してやりとりなどしておりました。

ちなみにこのシステムのバックエンドは、動画の編集からYouTubeへのアップロード、Webアプリケーションに至るまでほぼrubyで作成しております。 そのため下記のようなgemが大活躍しました。

streamio-ffmpeg

streamio-ffmpegは、rubyのffmpegの高機能ラッパーです。 GoProで撮った動画のリサイズや、色味の編集などに大活躍しました。

ちなみにサイトにいくと大量に表示されるgifアニメもstreamio-ffmpegを利用しているのですが、ffmpegのgif変換をすると画質がイマイチだったり、細かいところに手が届かないので、ffmpegとimagemagick(rmagick)の合わせ技を使いました。

framerate = 5

movie = FFMPEG::Movie.new "hoge.mov"
movie.transcode "tmp/%3d.png", "-loglevel error -an -r #{framerate}  -s 140x140 -ss 00:00:10 -t 00:00:03" 
list = Magick::ImageList.new
Dir.glob "tmp/*.png" do |f|
    list.push Magick::Image.read(f).first
end
list.delay = (100/framerate).to_i
list.write "hoge.gif"

のように、一度連番のgifファイルとして書き出したものをがっちゃんこしてます。

youtube_it

今回撮影した動画は全てYouTubeにアップして、その動画をページで読み込み表示しました。 youtube_itはrubyでYouTube連携するのにちょうどいいgemです。 OAuth認証やDeveloperKey認証で一度認証すれば、YouTubeのアップロードやステータス変更なども容易にできます。 今回はイベントの特性上、危険な動画があがる可能性もあったので、YouTube側で見れなくしたり、削除したりも任意でできるようにしました。

guard

GoProで受け取った動画の処理のトリガーにはguardを利用しました。 最近のguardの用途としては、変更を受け取ってアプリケーションを再起動したり、テストを走らせるなどが主なのですが、今回はファイルの変更をトリガーとして動画編集のバッチを走らせる構造になっています。 動画がディレクトリに追加されたことをguardで受け取り、streamio-ffmpegでの動画処理をスタートさせています。

god

システムが万が一落ちた時のためにgodで永続化しておきました。

gemではないけど…

ちなみにちゃんとシステムが動いているかを確認するためにim.kayac.comを使っていました。(動画の受信時、アップロード時、エラー発生時) ローカルマシンからでも叩けるので非常に重宝しました。ありがとうございます。

自動的に動画をアップロードするシステムを作る時の参考になればいいかなと思います。 家に定点カメラを置いて、ひたすらyoutubeにあげまくる動画とかもこれでできちゃいますね!

さて、明日は弊社インフラチームのホープ、@tkuchikiが筆をとってくれるようなので、ご期待ください!