目的
私が実装した動画配信の仕組みを見ながら、動画配信に必要な基本知識を理解することが目的です。
インフラ構成
- 以下に今回使用したリソースを挙げます
- CloudFront
- S3
- SNS
- EventBridge
- Lambda
- Cognito
- Mediaconvert
- EKS
- Aurora
- terraform における具体的なリソース名は、私の CI/CD の結論 v2 を参照してください。
流れ
アップロード
- ユーザは cognito にログイン
- ユーザはアプリ(EKS)にアクセスし、アプリは SDK を通じて cognito からトークンをもらって、ユーザに返します
- ユーザは、先ほどもらったアクセストークンを使って、S3 にアクセスするための identityId, STS トークンを Cognito から取得します
- 先ほどと同様に、アプリを介して Cognito にアクセスします
- ユーザはアプリに動画作成のリクエストを送ります
- もちろん、ここでは動画のメタ情報をアプリDB(Aurora)に登録するだけです
- ステータスは started とかにします
- 同時に、S3 のアップロードのエンドポイントをもらいます
- フロントで S3 のアップロードのエンドポイントを構築してもいいです
- ユーザは、STSトークンを使って、S3に直接動画をアップロードします
- IAM Policy の設定により、自分のフォルダ(identityId によって判別)以外へのアップロードは禁止されています
- 本プロジェクトのフロントは、簡易的な C++ デスクトップアプリで実装したので、SDK For C++ を使いました
- TransferManager クラスを使うことで、進捗を把握するためのプログレスバーを実装することができます
- S3 へのアップロードが完了したら、ラムダが発火します
- ラムダが Mediaconvert にジョブを積みます
- Mediaconvert はアップロードされた mp4 や mov を、ストリーミング再生可能な HLS に変換して、S3 に配置します
- HLS は、各セグメントのメタデータを保持する m3u8 ファイルと、実際の動画データを持つ ts ファイルから構成されます
- EventBridge は、Mediaconvert の状態を60秒ごと(適宜変更可能)に監視しており、SNS に伝えます
- Mediaconvert のステータスは、
["SUBMITTED", "INPUT_INFORMATION", "PROGRESSING", "STATUS_UPDATE", "COMPLETE", "ERROR", "CANCELED"]
のいずれかです
- Mediaconvert のステータスは、
- SNS はラムダを発火します
- ラムダは internal api を通じて、アプリ(EKS) に、動画(Mediaconvert)のステータスとMediaConvert がアップロードした S3 のエンドポイントを送ります
- アプリの動画のステータスが complete とかになっていれば、ユーザがその動画にアクセスできます
動画再生
- ユーザはアプリから動画のメタデータを取得します
- アプリは S3 のエンドポイントから cloudfront のエンドポイントに変換して、ユーザに返します
- 必要に応じて、cloudfront のエンドポイントに署名します
- 署名付きURLと署名付きクッキーが選択肢としてありますが、HLSは複数ファイルにアクセスするため、署名付きクッキーが推奨されています
- ユーザは、取得した cloudfront のエンドポイントを使って、動画をストリーミング再生します
Youtube
署名付きURL or 署名付きクッキー
上述したように、ストリーミング再生では、複数のセグメントファイルへのアクセスが必要なので、署名付きURLではなくて署名付きクッキーが一般的に推奨されている。
しかし、Youtube のネットワークタブを見ると、署名付きクッキーではなくて、署名付きURLが使われていた。おそらく、m3u8 ファイルだけではなくて、全ての ts ファイルのエンドポイントに対しても署名しているのだと思う。m3u8 ファイル上の全ての ts ファイルのエンドポイントを署名付きURLに変更するのは、かなり技術的に難しそう。
ただ、署名付きクッキーが使えない場合は、このように実装するしかないのかもしれない。例えば、C++ の Qt ライブラリや、Unreal Engine の Media Player は、ヘッダーを持たせることができないので、どうしてもアクセスを制限したい場合は、署名付きURLを採用するしかない。
(そもそも、HLS じゃなくて DASH 使っているとか、細かい部分は違うかもしれないが、大まかなイメージはこんな感じだと思う)
アクセス制限
詳しくはわからないが、署名以外にも、正規の方法以外から動画にアクセスできないように工夫しているはず。
例えば、Youtube のネットワークタブからURLを引っ張ってきて、デスクトップアプリで再生しようとしたら、CDN の CORS で弾かれた。
あとは、IPとか...