LoginSignup
17
14

More than 5 years have passed since last update.

Paperclip で S3 に動画アップロードしたけど FFMpeg使うことにいろいろ絶望。。。からのAmazon Elastic Transcoder利用

Posted at

プロローグ

凄い頑張ってRails + Paperclip with S3 + FFMpeg 環境な動画アップロード&配信サービス作ってみたものの、EC2のスペックあげなきゃどうにもFFMpegのエンコード
処理待ちに耐えられなくなった。ライブラリ地獄でFFMpeg稼働してるサーバのメンテも半端ない。でいろいろ調べてみたらAmazon使ってるならElastic Transcoderだろ?と言われてハッとなった

Amazon Elastic Transcoder 利用環境を整える

Amazon S3 入出力バケット作成

開発者ガイドサンプルではin/out別に作成するようになってますが、別記事では「バケットの節約をしましょう(上限100なので)」とうたっているのでひとつだけ作成して上手に利用しましょう

Amazon SNS トピック作成

Amazon SQS キュー作成

作成したら「Queue Action」->「Subscribe Queue to Amazon SNS Topic」からさっきのトピックと関連付けておきます

Amazon Elestic Transcoder パイプライン作成

ここでの注意は「Configure Amazon S3 Bucket for Transcoded Files and Playlists」「Configuration for Amazon S3 Bucket for Thumbnails」の出力バケット設定が入力バケットと同じですよと

Amazon CloudFront ディストリビューション作成

Create Origin Access IdentityしたらAmazon S3 Canonical User ID を控えておいてください
Create Distributionしますが、出力バケットは例によって入力と同じで

Amazon S3 バケットポリシー追加

{
"Version":"2012-10-17",
"Id":"PolicyForCloudFrontPrivateContent",
"Statement":[{
"Sid":" Granting CloudFront OAI access to private content",
"Effect":"Allow",
"Principal":{ "CanonicalUser":"さっき控えた値" },
"Action":"s3:GetObject",
"Resource":"arn:aws:s3:::出力バケット/*"
}]
}

さてRuby書きましょう

基本的にはサンプルコードを流用してください。
Railsならlib下にrbファイル作ってclass定義して、transcodeするメソッド切ったらサンプルを貼り付ける感じ。require 'aws-sdk'は忘れずに

バケット内がファイルのIN/OUTでごっちゃになっちゃうじゃん!

おっと忘れてた。今回Paperclip使ったので、オリジナルファイルだけS3に保存したら、Elastic Transcoderにジョブを追加します

Paperclip使う設定はまあこんな感じ。Elastic Transcoder使うのでstylesとかは不要です。

has_attached_file :file,
:url => "#{Rails.env}/:id/:style.:extension",
:path => "#{Rails.env}/:class/:id/:attachment/:style.:extension",
storage: :s3,
s3_credentials: "#{Rails.root}/config/aws.yml",
s3_permissions: :private

あれ?カスタムProcessor書いてやるんじゃないのかよ!というツッコミがありそうですが、それはチャレンジしてくださいませ。
delayed_jobをかませる関係からやってはみましたが、大変だったので別出しにしました。FFMpeg使ってたリファクタリング前のコードではいろいろやってたんですけど、自分が完全に把握出来ない部分が多すぎたので保守性を鑑み断念

さて本題に戻すとS3のバケット統一があるので、肝はサンプルコードにあるAWS::ElasticTranscoder::Clientのcreate_jobメソッドに渡すパラメータ「output_key_prefix」をしっかり決めておくこと

lib/transcoder.rb
        transcoder_client = AWS::ElasticTranscoder::Client.new(region: 'ap-northeast-1') # 東京リージョン対応
        job = transcoder_client.create_job(
                pipeline_id: pipeline_id,
                input: input,
                output_key_prefix: "#{Rails.env}/:class/:id/trans/",
                outputs: outputs
              ).data[:job]

「:class/:id/」のところはこんな書き方では動かないので、ちゃんとinitializeで設定しておきます。要するにバケット内の整理整頓をしっかりハンドルしておきましょうということです

inputはオリジナルファイルのS3URLを指定します。outpusは配信に必要なだけフォーマット定義をするのですが、システムプリセットを使えば大抵足りるでしょう。この辺の話は割愛。

後はdelayed_job導入してジョブ追加の上記処理を含むメソッドは非同期で呼ぶといいと思います

※PaperclipのオリジナルファイルをS3に置くところもdeleyed_jobしたかったのですが、分からず。。。

ここから先、SQSからジョブステータス見てゴニョゴニョも結構面倒臭いのですが、時間とれたら続き書きます

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14