AWS上で動作するウェブアプリケーションで動画ファイルをアップロードする場合のテクニック
はじめに
最近の開発依頼には、単純なテキストや画像だけでなく、動画や音声を扱いたいという要求が増えています。これらを従来通りのアプリケーションで取り扱おうとすると、いくつかの問題に直面します。
例えば、ウェブサーバーが受け取れるリクエストサイズの上限を設定する必要があります。Nginxではclient_max_body_size ディレクティブを、PHPでは upload_max_filesize、post_max_size、max_execution_time、max_input_time、memory_limit などの設定値を適切に調整する必要が出てきます。
また、ウェブサーバーがアップロードされたファイルを処理するためのリソース(ディスクスペースやメモリ)を確保する必要があります。動画ファイルをアップロードすると、それらはサーバー上のディスクに保存されるため、十分なディスク容量を常に確保しておく必要があります。PHPを例に挙げると、基本的なファイルアップロードメカニズムではファイルがサーバーのメモリ上に一時的に保存されるため、大量のメモリが必要となります。これにより、不必要に高価なサーバーの準備が必要になることもあります。
さらに、CloudFrontを利用している場合、CloudFront経由での POST/PUT によるデータアップロードに対して課金が発生します。たとえば東京リージョンのサーバーにデータを送信する場合、0.60 USD/GB の料金が発生します。1ヶ月に1TBの動画ファイルをアップロードした場合、その料金は600 USDにもなります。
このような問題を回避するために、我々が巨大な動画ファイルを頻繁にアップロードする必要があるアプリケーションの実装時に利用しているテクニックを紹介します。
ウェブサーバーを経由せずにS3バケットに直接データをアップロードする
結論から言うと、ファイルをウェブサーバーにアップロードする代わりに、Amazon S3のバケットに直接ファイルをアップロードする仕組みを構築します。S3へのデータ転送は基本的に無料なので、CloudFrontを使用している場合でも、アップロード料金を心配する必要はありません。
S3バケットにファイルをアップロードする際は、S3が提供する「署名付きURL(Presigned URL)」を利用します。
Amazon S3 ユーザーガイド:署名付きURLを使用したオブジェクトのアップロード
具体的なアップロードの流れは以下のようになります。
ファイルのアップロードを開始する際には、ウェブアプリケーションのサーバーからアップロード用の署名付きURLを要求します(1), (2), (3)。このプロセスは、例えば type=”file” 属性を持つ input 要素の change イベント、すなわち、ファイルが選択された直後に呼び出されるようにします。 署名付きURLを取得した後、クライアント側のJavaScriptを使用してPUT操作を行うことで、ファイルを直接S3バケットにアップロードできます(4)。クライアント側のJavaScriptではアップロード進捗を管理し、アップロード完了後にはサーバーに対して完了通知リクエストを再度送信します(5)。 こちらの完了通知は管理 Form の POST 時に行っていますが、実装されるアプリケーションの種類に応じて適宜調整します。
このアプローチは、昔から知られているクラウドデザインパターン(CDP)に基づくものです。サーバーを経由せずにファイルアップロードを行うため、無駄なリソース使用を避けることができ、不必要なディスクやメモリの準備が不要になります。
AWS Cloud Design Pattern: 直接オブジェクトアップロードパターン
S3バケットを使用する際の注意点として、扱うことができる最大ファイルサイズを確認しておく必要があります。署名付きURLを使用した単一ファイルのアップロードの場合、最大ファイルサイズは5GBになります。これを超えるサイズのファイルをアップロードするケースがある場合は、S3のマルチパートアップロード機能を利用し、個別に署名付きURLを生成する必要があります。
Amazon S3 ユーザーガイド:マルチパートアップロードの概要
また、このアップロードするファイルを別のサービスで利用するために一時的に利用する場合もあります。 例えば、MediaConvert でユーザーに視聴しやすい形式に変換するための入力として利用したり、Amazon Transcribe によって動画ファイルの音声から文字起こしを行うなどのケースが該当します。
この様な場合はアップロード先の S3 バケット領域を S3 LifeCycle で自動削除するなどの仕組みを導入することで不要なファイルを間違えることなく削除でき、無駄なS3の利用料金を発生させないようにすることがができます。
まとめ
既存のフレームワーク、例えば WordPress の管理画面ではメディアライブラリにファイルを簡単にアップロードすることができます。 しかし、この機能はファイルサイズが十分に小さい場合には有効ですが、動画ファイルなどを取り扱い始めると最初に挙げたような問題が発生します。
そのため、動画ファイルをアップロードして取り扱うような場合、そのアプリケーションの性質によって「既存の仕組みだけで対処できるのか?」「S3バケットにファイルを直接アップロードするテクニックを使う必要があるのか」を考えることができれば、より健全な開発・運用を行うことが可能になります。
今回は AWS の上でウェブアプリケーションが動いている前提でしたが、AWS以外のクラウドサービスにも S3 と似たストレージサービスはありますので、それらを利用することで同様の問題が解決可能です。