ビデオアップロード&処理パイプラインの構築の究極ガイド
開発者向けの深掘りチュートリアルで、プロダクションレベルのビデオパイプラインをゼロから構築する方法について、再開可能なアップロード、FFmpegトランスコーディング、HLSパッケージ化、セキュアクラウドストレージまで網羅します。

エンジニアとして、“動画アップロードを追加する”と求められたときは、簡単そうに見えるかもしれません。 <input type="file">
と POST リクエストだけでは十分でしょうか?実際には、信頼性の高い、スケーラブルな、そしてユーザーに良い体験を提供するシステムを構築することは、巨大なタスクです。完全な製品です。
このガイドは、開発者向けにビデオパイプラインを最初から設計することの実際の意味を理解したい開発者向けに作成されています。ユーザーのブラウザからグローバル デリバリー ネットワークまで、すべてのステージで複雑さと隠れた課題を探索します。
ビデオ パイプラインのアーキテクチャ的概要: 4 つの柱
信頼性の高いビデオ インフラは 4 つの柱に支えられています。各柱を構築、管理、およびスケールする必要があります。
- インジェクション: ユーザーのデバイスから大きな動画ファイルをシステムに確実に送信します。
- 処理: 原始のビデオ ファイルをさまざまな形式で変換して、どのユーザーでもどのデバイスでも視聴できるようにします。
- ストレージ: オリジナルのファイルとプロセッシングされたバージョンを安全かつ持続可能に保存します。
- 配信: 世界中どこからでも低遅延で高パフォーマンスでビデオをユーザーに提供します。
それぞれの柱を地面から構築しましょう。
柱 1: リゾーバブル インジェクション レイヤーの構築
標準的な HTTP 要求では、1 GB の動画ファイルをアップロードしようとしてブラウザ タブがタイムアウトまたはクラッシュします。より高度なクライアント側のソリューションが必要です。
リゾーバブル アップローダー クライアント
目標は、ネットワーク障害やブラウザ リフレッシュを乗り越えるアップローダーを作成することです。これは チャンク化 を実行することで達成されます。
- ファイル チャンキング: JavaScript で
File.prototype.slice()
メソッドを使用して、大きなファイルを小さな、番号付きのチャンク (例: 5 MB) に分割します。 - チェックサム: 各チャンクにクライアント側でチェックサム (MD5 または SHA-1 ハッシュなど) を計算する必要があります。これにより、受信時に各チャンクの整合性を確認できるため、転送中のデータ損傷を防ぐことができます。
- 並行チャンク アップロード: 通過率を最大化するには、
Promise.all
またはワーカー プールを使用して、複数のチャンク (例: 3-4) を同時にアップロードします。 - 状態管理: クライアントは各チャンクのステータスを追跡する必要があります (
pending
、uploading
、failed
、completed
)。この状態をlocalStorage
に保存しておくと、ユーザーが意図しないタイミングでタブを閉じてもアップロードを再開できるようになります。 - 指数バックオフ リトライ: チャンク アップロードが失敗した場合、直ちにリトライせずに指数バックオフ戦略 (1 秒待機、次は 2 秒、次は 4 秒) を実行して、臨時的なサーバーまたはネットワーク障害を優雅に処理します。
柱 2: ビデオ プロセッシングの巨大なタスク
元のファイルが組み立てられたサーバー (EC2 インスタンスや似たような VM) で、最も計算量の多い作業が始まります。 トランスコーディング です。
なぜトランスコーディングをするのか?
元のファイルはストリーミングには使いません。大きすぎて、単一形式でしかありません。トランスコーディングにより、各ユーザーに最適なビデオを提供できるように、複数バージョン (レンダリング) を生成します。
最新の友人と最大の敵: FFmpeg
FFmpeg
はビデオのすべてで活躍するオープンソース パワーハウスです。プロセッシング サーバーにインストールし、その厳格なコマンド ライン シンタックスをマスターする必要があります。通常のワークフローでは、1 つのビデオに対して次のような作業が行われます。
-
入力プローブ: まず
ffprobe
を使用して、ソース ビデオのプロパティ (解像度、ビットレート、コーデック、およびフレーム レート) を調べます。これらの情報は、トランスコーディングに基づいて決定するのに役立ちます。 -
ビデオ レンダリング生成: 次に、FFmpeg コマンドを実行します。1080p ソースの場合、次のようなレンダリングが生成されます。
- 1080p レンダリング (5 Mbps)
- 720p レンダリング (2.5 Mbps)
- 480p レンダリング (1 Mbps)
- 360p レンダリング (600 Kbps)
例えば、次のようなコマンドが実行されます。
ffmpeg -i input.mp4 \
-c:v libx264 -preset slow -crf 22 \
-s 1280x720 -b:v 2500k \
-c:a aac -b:a 128k \
-profile:v high -level 4.1 \
output_720p.mp4
このようなコマンドを各品質レベルごとに実行する必要があります。
-
アダプティブ ビット レート ストリーミング (ABS) パッケージ: 個々の MP4 ファイルでは、本当のストリーミングには十分ではありません。個々の MP4 レンダリングを ABS にパッケージ化する必要があります。これはまた、FFmpeg コマンドで実行されます。このコマンドは、すべての MP4 レンダリングを小さなビデオ セグメント (例: 2-4 秒) に分割し、
.m3u8
マニフェスト ファイルを作成します。このマニフェストファイルは、ビデオ プレーヤーにどのセグメントを要求するかを示す “プレイリスト” です。 -
サムネールとプレビュー生成: ビジュアル プレビューが必要になります。
- 静的 サムネール: FFmpeg を使用して、ビデオの中間のフレームからサムネールを抽出します。
- アニメーション プレビュー (ストーリーボード/スクラブ): 5 秒ごとにフレームを抽出し、それらを単一の “スプライト シート” イメージに結合し、VTT ファイルを作成して、時間コードとスプライト シート上の座標をマッピングします。
プロセッシング サーバーはボトルネックです。 ビデオ トランスコーディングは非常に CPU 密度が高く、1 分間のビデオを複数コアサーバーで 5 分以上占有することがあります。100 個のビデオを並行して処理すると、複雑な自動スケーリングのワーカー サーバー フリート、ジョブ キュー (RabbitMQ または SQS)、強力なエラーハンドリング システムが必要になります。これは巨大なインフラ プロジェクトです。
柱 3 & 4: スケーラブルなストレージとグローバル デリバリー
プロセッシング後、各ソース ビデオに対して数十の新しいファイルが生成されます (MP4、TS セグメント、マニフェスト ファイル、VTT ファイル、およびイメージ)。
- 持続可能なストレージ (S3): この場合、唯一の合理的な選択肢はオブジェクト ストレージ サービスである Amazon S3 です。バケットを作成し、IAM 権限を管理してサーバーがファイルにアクセスできるようにし、古いデータを管理するライフサイクル ポリシーを設定します。
- コンテンツ デリバリー ネットワーク (CDN): S3 から直接配信すると遅くて高額になります。グローバル エッジ ロケーションでビデオ ファイルをキャッシュする CDN (Amazon CloudFront) を構成し、キャッシュ コントロール ヘッダーを設定し、ビデオ プレーヤーに CORS ポリシーを適用して、グローバル デリバリーを実現します。
CDN は、ビデオ ファイルのキャッシュと配信を管理するために使用されるサービスです。
これらの柱は、ビデオ パイプラインの基礎となります。各柱を構築して管理することで、信頼性の高いビデオ インフラストラクチャを構築できます。
例
ここでは、ビデオ パイプラインの例を示します。
- インジェクション: ユーザーがビデオ ファイルをアップロードします。
- 処理: FFmpeg を使用して、ビデオ ファイルをさまざまな形式で変換します。
- ストレージ: 変換されたビデオ ファイルは S3 に保存されます。
- 配信: ビデオ ファイルは CDN 経由でユーザーに配信されます。
この例では、各柱がビデオ パイプラインの重要な部分を果たしています。インジェクション柱により、ユーザーのビデオ ファイルがアップロードされ、処理柱によりビデオ ファイルがさまざまな形式で変換され、ストレージ柱により変換されたビデオ ファイルが S3 に保存され、配信柱によりビデオ ファイルがユーザーに配信されます。
このように、各柱はビデオ パイプラインの重要な部分を果たしており、信頼性の高いビデオ インフラストラクチャを構築するために不可欠です。