#0. はじめに
##0.1. 目的
- DRM動画配信サービス的なシステムをAWSを使って安価に作ってみる。
- このシステムのDRM的なこと
- 動画ファイルを AES-128 で暗号化/復号する
- ストリーミング動画と鍵を署名付きCookieで配信する
##0.3 構築ステップ
- 動画アップロード用とCloudFrontオリジン用のS3バケット作成 と MediaConvert の動作確認
- 動画配信用CloudFront作成、ACM作成、S3バケットOAI設定
- CloudFront 署名付きURL/Cookie 設定
- AES-128鍵用のS3バケットとCloudFrontを作成
- Webサーバ(Apache+PHP)を作成、 CORS設定、 Video.js で Web Player 作成
- アップロードした動画ファイルをHLS+AES動画へ自動変換するLambdaを作成
##0.4. AWS
- AWSリージョン
- ACM以外はすべて「アジアパシフィック (東京)ap-northeast-1」
- ACMはCloudFrontで使用するため「米国東部 (バージニア北部)us-east-1」
##0.5. ローカル作業環境
####ローカル作業PC
- Mac
####Terraform
- terraform バージョン
- v0.12.9
- aws provider バージョン
- 2.48.0
- terraform 用 IAM ユーザーのポリシー
- AdministratorAccess
- IAMFullAccess
- terraform 作業ディレクトリ (システム完成形時のツリー)
$ tree terraform/
terraform/
├── cloudfront_cdn-ni4-6ra-net.tf
├── cloudfront_drm-aeskey-ni4-6ra-net.tf
├── cloudfront_key
│ ├── policy.json
│ ├── private_key.pem
│ └── public_key.pem
├── cloudfront_public-key.tf
├── credentials
├── ec2_web.tf
├── iam-role_lambda_mediaconvert_ni4-6ra-net.tf
├── iam-role_mediaconvert_ni4-6ra-net.tf
├── provider.tf
├── s3-bucket_drm-ni4-6ra-net-aeskey.tf
├── s3-bucket_drm-ni4-6ra-net-cloudfront-origin.tf
├── s3-bucket_drm-ni4-6ra-net-upload-origin.tf
├── sg_ec2_web.tf
└── terraform.tfstate
provider "aws" {
version = "2.48.0"
shared_credentials_file = "credentials"
profile = "terraform"
region = "ap-northeast-1"
}
[terraform]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#1. ステップ1 - 動画アップロード用とCloudFrontオリジン用のS3バケット作成 と MediaConvert の動作確認
##1.1. ステップ1 のゴール
- 動画アップロード用S3バケットに動画ファイルをアップロードして、MediaConvertでHLS動画に変換してCloudFrontオリジン用S3バケットへ出力する。
- 出力された HLS動画ファイルをローカルPCにダウンロードして、ffmpeg を使って mp4 ファイルに変換して QuickTime Player で再生する。
- 完成図
##1.2. ステップ1 構築
###1.2.1. オリジナル動画ファイルアップロード用 S3 バケット作成して、movie フォルダを作成
####S3バケット: drm-ni4-6ra-net-upload-origin
resource "aws_s3_bucket" "drm-ni4-6ra-net-upload-origin" {
bucket = "drm-ni4-6ra-net-upload-origin"
acl = "private"
force_destroy = "false"
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-upload-origin" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-upload-origin]
bucket = "drm-ni4-6ra-net-upload-origin"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_object" "drm-ni4-6ra-net-upload-origin-movie" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-upload-origin]
bucket = aws_s3_bucket.drm-ni4-6ra-net-upload-origin.id
acl = "private"
key = "movie/"
server_side_encryption = "AES256"
}
###1.2.2. CloudFrontオリジン用 S3 バケット作成して、movie フォルダを作成
####S3バケット: drm-ni4-6ra-net-cloudfront-origin
resource "aws_s3_bucket" "drm-ni4-6ra-net-cloudfront-origin" {
bucket = "drm-ni4-6ra-net-cloudfront-origin"
acl = "private"
force_destroy = "false"
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-cloudfront-origin" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = "drm-ni4-6ra-net-cloudfront-origin"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_object" "drm-ni4-6ra-net-cloudfront-origin-movie" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.id
acl = "private"
key = "movie/"
server_side_encryption = "AES256"
}
###1.2.3. MediaConvert で使用する IAMロールを作成
####IAMロール: mediaconvert_ni4-6ra-net
data "aws_iam_policy_document" "mediaconvert-assume-role-policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["mediaconvert.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "iam_drm-ni4-6ra-net-upload-origin" {
statement {
effect = "Allow"
actions = [
"s3:GetObject"
]
resources = [
"arn:aws:s3:::drm-ni4-6ra-net-upload-origin/*",
"arn:aws:s3:::drm-ni4-6ra-net-upload-origin"
]
}
}
resource "aws_iam_policy" "iam_drm-ni4-6ra-net-upload-origin" {
name = "s3_drm-ni4-6ra-net-upload-origin"
policy = data.aws_iam_policy_document.iam_drm-ni4-6ra-net-upload-origin.json
}
data "aws_iam_policy_document" "iam_drm-ni4-6ra-net-cloudfront-origin" {
statement {
effect = "Allow"
actions = [
"s3:PutObject"
]
resources = [
"arn:aws:s3:::drm-ni4-6ra-net-cloudfront-origin/*",
"arn:aws:s3:::drm-ni4-6ra-net-cloudfront-origin"
]
}
}
resource "aws_iam_policy" "iam_drm-ni4-6ra-net-cloudfront-origin" {
name = "s3_drm-ni4-6ra-net-cloudfront-origin"
policy = data.aws_iam_policy_document.iam_drm-ni4-6ra-net-cloudfront-origin.json
}
resource "aws_iam_role" "mediaconvert_ni4-6ra-net" {
name = "mediaconvert_ni4-6ra-net"
assume_role_policy = data.aws_iam_policy_document.mediaconvert-assume-role-policy.json
}
resource "aws_iam_role_policy_attachment" "mediaconvet_ni4-6ra-net_drm-ni4-6ra-net-upload-origin" {
role = aws_iam_role.mediaconvert_ni4-6ra-net.name
policy_arn = aws_iam_policy.iam_drm-ni4-6ra-net-upload-origin.arn
}
resource "aws_iam_role_policy_attachment" "mediaconvert_ni4-6ra-net_drm-ni4-6ra-net-cloudfront-origin" {
role = aws_iam_role.mediaconvert_ni4-6ra-net.name
policy_arn = aws_iam_policy.iam_drm-ni4-6ra-net-cloudfront-origin.arn
}
###1.2.4. デモ用動画を S3バケット drm-ni4-6ra-net-upload-origin にアップロード
####デモ用動画
-
今回はここの無料サイトの動画を使用する
https://pixabay.com/ja/videos/%E8%8A%B1%E7%81%AB-%E7%A5%9D%E8%B3%80-%E6%96%B0%E3%81%97%E3%81%84%E5%B9%B4-10863/ -
ファイル名を demo01.mp4 に変える
####S3バケット drm-ni4-6ra-net-upload-origin の movie フォルダにアップロード
###1.2.5. MediaConvert で MP4 ⇒ HLS へ変換
####MediaConvertでジョブを作成
-
AWS マネジメントコンソールから直接
ジョブ
ジョブ作成
入力ファイルURL ⇒ S3://drm-ni4-6ra-net-upload-origin/movie/demo01.mp4 を選択
出力グループ追加
Apple HLS を選択
出力 Output 1
名前修飾子 必須項目 適当な名前を入れておく(ここでは _non-aes)
送信先 ⇒ S3://drm-ni4-6ra-net-cloudfront-origin/movie/ を選択
解像度 ⇒ 空にしておく(空にするとパススルー設定となり、オリジナルと同じ解像度になる)
ビットレート ⇒ 必須項目 適当に 2000kbps にしておく
ジョブの設定 ⇒ AWS の統合
IAMロール ⇒ MediaConvert で使う IAMロールを指定する
以上、設定が終わったら 作成
###1.2.6. 再生確認
####次のファイルをローカル作業PCにダウンロードする
demo01_non-aes.m3u8
demo01_non-aes_00001.ts
demo01_non-aes_00002.ts
demo01_non-aes.m3u8 はテキストファイル
中身はこんな感じ
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:11,
demo01_non-aes_00001.ts
#EXTINF:9,
demo01_non-aes_00002.ts
#EXT-X-ENDLIST
####ffmpeg で HLS ⇒ MP4 に変換
- ffmepg インストール
$ brew install ffmpeg
- ダウンロードしたファイルのあるフォルダで下記コマンドを実行
$ ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i demo01_non-aes.m3u8 -c copy demo01_non-aes.mp4
- 生成された demo01_non-aes.mp4 を QuickTime Player で再生してみる
$ open demo01_non-aes.mp4
#2. ステップ2 - 動画配信用CloudFront作成、ACM作成、S3バケットOAI設定
##2.1. ステップ2 のゴール
##2.2. ステップ2 構築
###2.2.1. ACM作成
- 「米国東部 (バージニア北部)us-east-1」に作成する
- 手順は割愛
- 作成したACM (ワイルドカード)
###2.2.2. CloudFront作成
- S3バケット s3-bucket_drm-ni4-6ra-net-cloudfront-origin で「パブリックアクセスをすべてブロックする」設定を入れているので、OAI 設定がないと CloudFront から S3バケットにアクセスしたときに AccessDenied となる。
####CloudFront: E2L8V7QYSFINZX
resource "aws_cloudfront_origin_access_identity" "drm-ni4-6ra-net-cloudfront-origin" {
comment = "S3 drm-ni4-6ra-net-cloudfront-origin"
}
resource "aws_cloudfront_distribution" "cdn-ni4-6ra-net" {
aliases = [
"cdn.ni4-6ra.net"
]
enabled = true
is_ipv6_enabled = true
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
default_ttl = "0"
max_ttl = "0"
min_ttl = "0"
target_origin_id = "drm-ni4-6ra-net-cloudfront-origin"
viewer_protocol_policy = "https-only"
forwarded_values {
headers = [
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Origin"
]
query_string = true
query_string_cache_keys = []
cookies {
forward = "none"
whitelisted_names = []
}
}
}
origin {
domain_name = "drm-ni4-6ra-net-cloudfront-origin.s3.amazonaws.com"
origin_id = "drm-ni4-6ra-net-cloudfront-origin"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-cloudfront-origin.cloudfront_access_identity_path
}
}
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000"
cloudfront_default_certificate = false
minimum_protocol_version = "TLSv1.2_2019"
ssl_support_method = "sni-only"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
####作成した CloudFront の設定抜粋
OAI (Origin Access Identity) 設定
動作確認中に変なキャッシュをしないようにキャッシュしない設定にしておく
###2.2.3. Route 53 設定
CloudFront の Domain Name と Alternate Domain Names の CNAME 設定
※この時点で https://cdn.ni4-6ra.net にアクセスしてみると 「Access Denied」 となる
###2.2.4. S3バケット drm-ni4-6ra-net-cloudfront-origin に OAI ポリシーを追加
####S3バケット: drm-ni4-6ra-net-cloudfront-origin
※さきほどの s3-bucket_drm-ni4-6ra-net-cloudfront-origin.tf に追記する
resource "aws_s3_bucket" "drm-ni4-6ra-net-cloudfront-origin" {
bucket = "drm-ni4-6ra-net-cloudfront-origin"
acl = "private"
force_destroy = "false"
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-cloudfront-origin" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = "drm-ni4-6ra-net-cloudfront-origin"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_object" "drm-ni4-6ra-net-cloudfront-origin-movie" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.id
acl = "private"
key = "movie/"
server_side_encryption = "AES256"
}
## 下記を追記
data "aws_iam_policy_document" "s3bucket_drm-ni4-6ra-net-cloudfront-origin" {
version = "2012-10-17"
statement {
sid = "Grant a CloudFront Origin Identity access"
effect = "Allow"
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-cloudfront-origin.iam_arn]
}
actions = [
"s3:GetObject",
"s3:List*"
]
resources = [
aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.arn,
"${aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.arn}/*"
]
}
}
resource "aws_s3_bucket_policy" "drm-ni4-6ra-net-cloudfront-origin" {
bucket = aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.bucket
policy = data.aws_iam_policy_document.s3bucket_drm-ni4-6ra-net-cloudfront-origin.json
}
###2.2.5. OAIアクセス確認
https://cdn.ni4-6ra.net にアクセス
#3. ステップ3 - CloudFront 署名付きURL/Cookie 設定
##3.1. ステップ3 のゴール
##3.3. ステップ3 構築
###3.2.1. CloudFront署名付き URL/Cookie 向け公開鍵を作成して、Key Groups を設定
(参考)
root ユーザー作業が不要に!Amazon CloudFront で署名付き URL/Cookie 向け公開鍵を IAM ユーザー権限で管理できるようになりました。
####キーペアを作成
ローカル作業PCのterraform作業ディレクトリで
$ mkdir cloudfront_key
$ cd cloudfront_key
$ openssl genrsa -out private_key.pem 2048
$ openssl rsa -pubout -in private_key.pem -out public_key.pem
秘密鍵 ・・・ private_key.pem
公開鍵 ・・・ public_key.pem
####公開鍵をCloudFrontにアップロードする
resource "aws_cloudfront_public_key" "cloudfront-public-key" {
comment = "cloudfront public key"
encoded_key = file("./cloudfront_key/public_key.pem")
name = "cloudfront-public-key"
}
####アップロードした公開鍵
ID 「K1A3BSF7L9SNGX」 は後で必要になるのでメモっておく
####Key Groups 設定
key group を作成する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
###3.2.2. CloudFront署名付き URL/Cookie を設定
CloudFront trusted key groups を設定する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
Yes, Edit
###3.2.3. 署名付きCookieリクエストを作成して動作確認
(参考)
署名付き Cookie を使用して HLS コンテンツを取得してみた
カスタムポリシーを使用する署名付き Cookie の設定
Linux コマンドおよび OpenSSL を使用した Base64 エンコードおよび暗号化
####カスタムポリシーを使用する署名付き Cookie のポリシーステートメントの作成
ローカル作業PCのさきほどキーペアを作成したディレクトリにpolicy.jsonファイルを作成する
EpochTime は下記のサイトで求める(今回は検証用なので1年後の日付にしている)
https://www.epochconverter.com/
{
"Statement": [
{
"Resource": "https://*.ni4-6ra.net/*",
"Condition": {
"DateLessThan": {
"AWS:EpochTime": 1640698309
}
}
}
]
}
####ポリシーステートメントを base64 でエンコード・・・①
$ cat policy.json | tr -d "\n" | tr -d " \t\n\r" | openssl base64 | tr -- '+=/' '-_~' | tr -d "\n" | tr -d " \t\n\r"
↓
eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__
####ポリシーステートメントをハッシュ化して署名・・・②
$ cat policy.json | tr -d "\n" | tr -d " \t\n\r" | openssl sha1 -sign private_key.pem | openssl base64 | tr -- '+=/' '-_~' | tr -d "\n" | tr -d " \t\n\r"
↓
jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__
####①と②を次のリクエストに置き換え、③はPublic key ID 「K1A3BSF7L9SNGX」に置き換える
$ curl https://cdn.ni4-6ra.net/movie/demo01_non-aes.m3u8 -b 'CloudFront-Policy=①; CloudFront-Signature=②; CloudFront-Key-Pair-Id=③'
↓
$ curl https://cdn.ni4-6ra.net/movie/demo01_non-aes.m3u8 -b 'CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__; CloudFront-Signature=jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__; CloudFront-Key-Pair-Id=K1A3BSF7L9SNGX'
成功すれば、下記のレスポンスが返る
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:11,
demo01_non-aes_00001.ts
#EXTINF:9,
demo01_non-aes_00002.ts
#EXT-X-ENDLIST
#4. ステップ4 - AES-128鍵用のS3バケットとCloudFrontを作成
##4.1. ステップ4 のゴール
- MediaConvertでHLS動画をAES暗号化する。
- HLS+AES動画ファイルをローカルPCにダウンロードして、ffmpeg を使って復号して mp4 ファイルに変換して QuickTime Player で再生する。
- 完成図
##4.2. ステップ4 構築
###4.2.1. AES鍵用S3バケットを作成
####S3バケット: drm-ni4-6ra-net-aeskey
resource "aws_s3_bucket" "drm-ni4-6ra-net-aeskey" {
bucket = "drm-ni4-6ra-net-aeskey"
acl = "private"
force_destroy = false
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-aeskey" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-aeskey]
bucket = "${aws_s3_bucket.drm-ni4-6ra-net-aeskey.id}"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
###4.2.2. AES鍵用CloudFrontを作成
####CloudFront: E28HDM2W6KJHQ2
resource "aws_cloudfront_origin_access_identity" "drm-ni4-6ra-net-aeskey" {
comment = "S3 drm-ni4-6ra-net-aeskey"
}
resource "aws_cloudfront_distribution" "drm-aeskey-ni4-6ra-net" {
aliases = [
"drm-aeskey.ni4-6ra.net"
]
enabled = true
is_ipv6_enabled = true
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
default_ttl = "0"
max_ttl = "0"
min_ttl = "0"
target_origin_id = "drm-ni4-6ra-net-aeskey"
viewer_protocol_policy = "https-only"
forwarded_values {
headers = [
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Origin"
]
query_string = true
query_string_cache_keys = []
cookies {
forward = "none"
whitelisted_names = []
}
}
}
origin {
domain_name = "drm-ni4-6ra-net-aeskey.s3.amazonaws.com"
origin_id = "drm-ni4-6ra-net-aeskey"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-aeskey.cloudfront_access_identity_path
}
}
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:000000000000:certificate/00000000-0000-0000-0000-000000000000"
cloudfront_default_certificate = false
minimum_protocol_version = "TLSv1.2_2019"
ssl_support_method = "sni-only"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
####作成した CloudFront の設定抜粋
OAI (Origin Access Identity) 設定
動作確認中に変なキャッシュをしないようにキャッシュしない設定にしておく
###4.2.3. Route 53 設定
CloudFront の Domain Name と Alternate Domain Names の CNAME 設定
###4.2.4. S3バケット drm-ni4-6ra-net-aeskey に OAI ポリシーを追加
####S3バケット drm-ni4-6ra-net-aeskey
※さきほどの s3-bucket_drm-ni4-6ra-net-aeskey.tf に追記する
resource "aws_s3_bucket" "drm-ni4-6ra-net-aeskey" {
bucket = "drm-ni4-6ra-net-aeskey"
acl = "private"
force_destroy = false
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-aeskey" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-aeskey]
bucket = "${aws_s3_bucket.drm-ni4-6ra-net-aeskey.id}"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
##下記を追記
data "aws_iam_policy_document" "s3bucket_drm-ni4-6ra-net-aeskey" {
version = "2012-10-17"
statement {
sid = "Grant a CloudFront Origin Identity access"
effect = "Allow"
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-aeskey.iam_arn]
}
actions = [
"s3:GetObject",
"s3:List*"
]
resources = [
aws_s3_bucket.drm-ni4-6ra-net-aeskey.arn,
"${aws_s3_bucket.drm-ni4-6ra-net-aeskey.arn}/*"
]
}
}
resource "aws_s3_bucket_policy" "drm-ni4-6ra-net-aeskey" {
bucket = aws_s3_bucket.drm-ni4-6ra-net-aeskey.bucket
policy = data.aws_iam_policy_document.s3bucket_drm-ni4-6ra-net-aeskey.json
}
###4.2.5. CloudFront署名付き URL/Cookie を設定
CloudFront trusted key groups を設定する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
Yes, Edit
※この時点で https://drm-aeskey.ni4-6ra.net/ にアクセスしてみると 「Missing Key-Pair-Id query parameter or cookie value」 となる
###4.2.6. AES鍵を作成して、S3バケット drm-ni4-6ra-net-aeskey へアップロードする
ローカル作業PCで
####静的キーを作成する
$ openssl rand 16 > aes.key
####作成した静的キーから「静的キーの値」を生成 (MediaConverrt DRM暗号化設定に必要な値)
$ xxd -ps aes.key
54a65de338c972d3f1dafe95ac936ad2
####「定数初期化ベクトル」を生成 (MediaConverrt DRM暗号化設定に必要な値)
$ openssl rand -hex 16
d190b98ad29394fd6883a5dbd062a205
####aes.keyファイルをS3バケット drm-ni4-6ra-net-aeskey へアップロード
###4.2.7. 署名付きCookieリクエストで動作確認
署名付きCookieリクエストで https://drm-aeskey.ni4-6ra.net/aes.key を取得
$ curl https://drm-aeskey.ni4-6ra.net/aes.key -b 'CloudFront-Policy=①; CloudFront-Signature=②; CloudFront-Key-Pair-Id=③'
「3.2.3. 署名付きCookieリクエストを作成して動作確認」で作成した①と②をそのまま使う。
③もPublic key ID 「K1A3BSF7L9SNGX」を使う。
$ curl https://drm-aeskey.ni4-6ra.net/aes.key -b 'CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__; CloudFront-Signature=jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__; CloudFront-Key-Pair-Id=K1A3BSF7L9SNGX'
↓
aes.key はバイナリファイルなので、次のようなレスポンスが返る
T�]�8�r�������j�
###4.2.8. MediaConvertで MP4 ⇒ HLS+AES動画へ変換
####MediaConvertでジョブを作成
ジョブ
ジョブ作成
入力ファイルURL ⇒ S3://drm-ni4-6ra-net-upload-origin/movie/demo01.mp4 を選択
出力グループ 追加
Apple HLS を選択
送信先 ⇒ S3://drm-ni4-6ra-net-cloudfront-origin/movie/ を選択
DRM 暗号化
・定数初期化ベクトル: d190b98ad29394fd6883a5dbd062a205
・静的キーの値: 54a65de338c972d3f1dafe95ac936ad2
・URL: https://drm-aeskey.ni4-6ra.net/aes.key
出力 Output 1
名前修飾子 ⇒ 必須項目 適当な名前を入れておく (ここでは _aes)
解像度 ⇒ 空にしておく(空にするとパススルー設定となり、オリジナルと同じ解像度になる)
ビットレート ⇒ 必須項目 適当に 2000kbps にしておく
ジョブの設定 ⇒ AWS の統合
IAMロール ⇒ MediaConvert で使う IAMロールを指定する
以上、設定が終わったら 作成
-
ジョブのステータス確認
ステータス SUBMITTED ⇒ PROGRESSING ⇒ COMPLETE
###4.2.9. 再生確認
####次のファイルをローカル作業PCの aes.key があるフォルダにダウンロードする
demo01_aes.m3u8
demo01_aes_00001.ts
demo01_aes_00002.ts
demo01_aes.m3u8 の中身はこんな感じ
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="https://drm-aeskey.ni4-6ra.net/aes.key",IV=0xD190B98AD29394FD6883A5DBD062A205
#EXTINF:11,
demo01_aes_00001.ts
#EXTINF:9,
demo01_aes_00002.ts
#EXT-X-ENDLIST
####ffmpeg で HLS ⇒ MP4 に変換
今回は、AES鍵はローカルにある鍵を使うので、demo01_aes.m3u8 ファイルの EXT-X-KEY 行を次のように編集する
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="aes.key",IV=0xD190B98AD29394FD6883A5DBD062A205
#EXTINF:11,
demo01_aes_00001.ts
#EXTINF:9,
demo01_aes_00002.ts
#EXT-X-ENDLIST
下記のffmpegコマンドを実行
$ ffmpeg -allowed_extensions ALL -i "demo01_aes.m3u8" -c copy "demo01_aes.mp4"
- 生成された demo01_aes.mp4 を QuickTime Player で再生してみる
$ open demo01_aes.mp4
#5. ステップ5 - Webサーバ(Apache+PHP)を作成、 CORS設定、 Video.js で Web Player 作成
##5.1. ステップ5 のゴール
##5.2. ステップ5 構築
###5.2.1. Webサーバ作成
EC2 AmazonLinux2 で適当に作成
今回 AMI は ami-01748a72bed07727c を使った
Apache と PHP をインストール
# amazon-linux-extras enable php7.4
# amazon-linux-extras install php7.4
# yum install httpd
# systemctl httpd start
###5.2.2. Route 53 設定
EC2 の パブリック IPv4 アドレス と Webサーバのドメイン の Aレコード設定
###5.2.3. CORS設定
- CORS設定がうまくいかない場合は、ブラウザの開発スールの Webコンソールなのでエラーを確認する
CloudFront の E28HDM2W6KJHQ2 と E2L8V7QYSFINZX のCORS用設定
S3バケット drm-ni4-6ra-net-aeskey のCORS設定
s3-bucket_drm-ni4-6ra-net-aeskey.tf に cors_rule を追記
resource "aws_s3_bucket" "drm-ni4-6ra-net-aeskey" {
bucket = "drm-ni4-6ra-net-aeskey"
acl = "private"
force_destroy = false
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
## 下記を追記
cors_rule {
allowed_headers = [
"*",
]
allowed_methods = [
"GET"
]
allowed_origins = [
"http://drm.ni4-6ra.net"
]
expose_headers = []
max_age_seconds = 3000
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-aeskey" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-aeskey]
bucket = "${aws_s3_bucket.drm-ni4-6ra-net-aeskey.id}"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
data "aws_iam_policy_document" "s3bucket_drm-ni4-6ra-net-aeskey" {
version = "2012-10-17"
statement {
sid = "Grant a CloudFront Origin Identity access"
effect = "Allow"
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-aeskey.iam_arn]
}
actions = [
"s3:GetObject",
"s3:List*"
]
resources = [
aws_s3_bucket.drm-ni4-6ra-net-aeskey.arn,
"${aws_s3_bucket.drm-ni4-6ra-net-aeskey.arn}/*"
]
}
}
resource "aws_s3_bucket_policy" "drm-ni4-6ra-net-aeskey" {
bucket = aws_s3_bucket.drm-ni4-6ra-net-aeskey.bucket
policy = data.aws_iam_policy_document.s3bucket_drm-ni4-6ra-net-aeskey.json
}
S3バケット drm-ni4-6ra-net-cloudfront-origin のCORS設定
s3-bucket_drm-ni4-6ra-net-aeskey.tf に cors_rule を追記
resource "aws_s3_bucket" "drm-ni4-6ra-net-cloudfront-origin" {
bucket = "drm-ni4-6ra-net-cloudfront-origin"
acl = "private"
force_destroy = "false"
region = "ap-northeast-1"
versioning {
enabled = false
}
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
## 下記を追記
cors_rule {
allowed_headers = [
"*",
]
allowed_methods = [
"GET"
]
allowed_origins = [
"http://drm.ni4-6ra.net"
]
expose_headers = []
max_age_seconds = 3000
}
}
resource "aws_s3_bucket_public_access_block" "drm-ni4-6ra-net-cloudfront-origin" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = "drm-ni4-6ra-net-cloudfront-origin"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_object" "drm-ni4-6ra-net-cloudfront-origin-movie" {
depends_on = [aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin]
bucket = aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.id
acl = "private"
key = "movie/"
server_side_encryption = "AES256"
}
data "aws_iam_policy_document" "s3bucket_drm-ni4-6ra-net-cloudfront-origin" {
version = "2012-10-17"
statement {
sid = "Grant a CloudFront Origin Identity access"
effect = "Allow"
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.drm-ni4-6ra-net-cloudfront-origin.iam_arn]
}
actions = [
"s3:GetObject",
"s3:List*"
]
resources = [
aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.arn,
"${aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.arn}/*"
]
}
}
resource "aws_s3_bucket_policy" "drm-ni4-6ra-net-cloudfront-origin" {
bucket = aws_s3_bucket.drm-ni4-6ra-net-cloudfront-origin.bucket
policy = data.aws_iam_policy_document.s3bucket_drm-ni4-6ra-net-cloudfront-origin.json
}
###5.2.4. Video.js で Webプレーヤー作成 - サンプル
(参考)
Video.jsのvideojs-http-streaming(VHS)を使ってHLS形式のストリーミング配信を再生する最低限度の設定
<?php
setcookie("CloudFront-Policy", "①", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Signature", "②", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Key-Pair-Id", "③", time() + 300, "/" , ".ni4-6ra.net", 0);
?>
<html>
<head>
<title>Demo</title>
<link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
</head>
<body>
<video-js id=example-video width=1280 height=720 class="vjs-default-skin" controls>
</video-js>
<script src="https://vjs.zencdn.net/7.4.1/video.js"></script>
<script>
var player = videojs('example-video');
player.src({
src: 'm3u8のURL',
type: 'application/x-mpegURL',
});
</script>
</body>
</html>
-
setcookieで署名付きCookieをセット
-
「3.2.3. 署名付きCookieリクエストを作成して動作確認」で作成した①と②をそのまま使う
-
③もPublic key ID 「K1A3BSF7L9SNGX」を使う
-
src に m3u8ファイル の URL を指定
###5.2.5. Video.js で Webプレーヤー作成 - AES暗号化されていない HLS動画を再生
src に 暗号化されていない HLS動画の m3u8 ファイル の URL https://cdn.ni4-6ra.net/movie/demo01_non-aes.m3u8 を指定
<?php
setcookie("CloudFront-Policy", "eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Signature", "jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__
", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Key-Pair-Id", "K1A3BSF7L9SNGX", time() + 300, "/" , ".ni4-6ra.net", 0);
?>
<html>
<head>
<title>Demo</title>
<link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
</head>
<body>
<video-js id=example-video width=1280 height=720 class="vjs-default-skin" controls>
</video-js>
<script src="https://vjs.zencdn.net/7.4.1/video.js"></script>
<script>
var player = videojs('example-video');
player.src({
src: 'https://cdn.ni4-6ra.net/movie/demo01_non-aes.m3u8',
type: 'application/x-mpegURL',
withCredentials: true
});
</script>
</body>
</html>
Mac Firefox で http://drm.ni4-6ra.net/player_non-aes.php にアクセス
###5.2.6. Video.js で Webプレーヤー作成 - AES暗号化された HLS動画を再生
src に AES暗号化されたHLS動画の m3u8 ファイル の URL https://cdn.ni4-6ra.net/movie/demo01_aes.m3u8 を指定
<?php
setcookie("CloudFront-Policy", "eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Signature", "jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__
", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Key-Pair-Id", "K1A3BSF7L9SNGX", time() + 300, "/" , ".ni4-6ra.net", 0);
?>
<html>
<head>
<title>Demo</title>
<link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
</head>
<body>
<video-js id=example-video width=1280 height=720 class="vjs-default-skin" controls>
</video-js>
<script src="https://vjs.zencdn.net/7.4.1/video.js"></script>
<script>
var player = videojs('example-video');
player.src({
src: 'https://cdn.ni4-6ra.net/movie/demo01_aes.m3u8',
type: 'application/x-mpegURL',
withCredentials: true
});
</script>
</body>
</html>
Mac Firefox で http://drm.ni4-6ra.net/player_aes.php にアクセス
#6. ステップ6 - アップロードした動画ファイルをHLS+AES動画へ自動変換するLambdaを作成
##6.1. ステップ6 のゴール
-
アップロードした動画ファイルをHLS+AES動画へ自動変換
-
S3バケット drm-ni4-6ra-net-upload-origin/movie/ に動画ファイルをアップロード
* demo01.mp4 -
Lambda が起動して、MediaConvert ジョブテンプレートが実行される
* テンプレート demo-lambda-autoconvert -
変換された動画ファイルが S3バケット drm-ni4-6ra-net-cloudfront-origin/movie/ に出力される
* demo01_auto.m3u8
* demo01_auto_00001.ts
* demo01_auto_00002.ts
##6.2. ステップ6 構築
###6.2.1. MediaConvert ジョブテンプレート作成
- 今回は 自動回転、サーバー側の暗号化 なども設定する
- ジョブテンプレートでは、次のものは設定しない
- 入力ファイルURL
- 送信先
- IAMロール
ジョブテンプレート ⇒ テンプレートの作成
一般設定 ⇒ 名前を適当に付ける
入力 追加
回転させる ⇒ 自動
出力グループ 追加
Apple HLS を選択
サーバー側の暗号化設定
DRM 暗号化設定
・定数初期化ベクトル: d190b98ad29394fd6883a5dbd062a205
・静的キーの値: 54a65de338c972d3f1dafe95ac936ad2
・URL: https://drm-aeskey.ni4-6ra.net/aes.key
出力 Output 1
名前修飾子 ⇒ 必須項目 適当な名前を入れておく (ここでは _auto)
解像度 ⇒ 空にしておく(空にするとパススルー設定となり、オリジナルと同じ解像度になる)
ビットレート ⇒ 必須項目 適当に 2000kbps にしておく
以上、設定が終わったら 作成
###6.2.2. Lambdaで使用するIAMロールを作成
####IAMロール名: lambda_mediaconvert_ni4-6ra-net
data "aws_iam_policy_document" "lambda-assume-role-policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "mediaconvert-createjob" {
version = "2012-10-17"
statement {
effect = "Allow"
actions = [
"iam:PassRole",
"mediaconvert:CreateJob"
]
resources = [
"*"
]
}
}
resource "aws_iam_policy" "mediaconvert-createjob" {
name = "mediaconvert-createjob"
policy = data.aws_iam_policy_document.mediaconvert-createjob.json
}
resource "aws_iam_role" "lambda_mediaconvert_ni4-6ra-net" {
name = "lambda_mediaconvert_ni4-6ra-net"
assume_role_policy = data.aws_iam_policy_document.lambda-assume-role-policy.json
path = "/service-role/"
}
resource "aws_iam_role_policy_attachment" "lambda_mediaconvert_AWSLambdaBasicExecutionRole" {
role = aws_iam_role.lambda_mediaconvert_ni4-6ra-net.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_iam_role_policy_attachment" "lambda_mediaconvert_mediaconvert" {
role = aws_iam_role.lambda_mediaconvert_ni4-6ra-net.name
policy_arn = aws_iam_policy.mediaconvert-createjob.arn
}
###6.2.3. Lambda関数作成
- ランタイムは Python3.7
基本的な情報
・関数名は適当に(ここでは mediaconvert_ni4-6ra-net)
・ランタイムは Python 3.7
・既存のロール lambda_mediaconvert_ni4-6ra-net
関数の作成
Lambda環境変数設定
・AWS_ACCOUNT_ID ・・・ このシステムを構築している AWS アカウントのID(12桁)
・S3_BUCKET_UPLOAD ・・・ オリジナル動画ファイルをアップロードするS3バケット名(drm-ni4-6ra-net-upload-origin)
・S3_BUCKET_OUTPUT ・・・ MediaConvertで変換した動画ファイルを出力するS3バケット名(drm-ni4-6ra-net-cloudfront-origin)
・IAM_ROLE_MEDIACONVERT ・・・ MediaConvertで使用するIAMロール名(mediaconvert_ni4-6ra-net)
・MEDIACONVERT_ENDPOINT ・・・ MediaConvertのエンドポイント
・MEDIACONVERT_JOB_TEMPLATE ・・・ MediaConvertのジョブテンプレート名(demo-lambda-autoconvert)
(補足)
MediaConvertのエンドポイントは、MediaConvertのダッシュボードで確認できる
関数コード
{
"OutputGroups": [
{
"Name": "Apple HLS",
"OutputGroupSettings": {
"Type": "HLS_GROUP_SETTINGS",
"HlsGroupSettings": {
"Destination": ""
}
}
}
],
"Inputs": [
{
"FileInput": ""
}
]
}
import os
import json
import boto3
import urllib.parse
import logging
aws_account_id = os.environ['AWS_ACCOUNT_ID']
mediaconvert_endpoint = os.environ['MEDIACONVERT_ENDPOINT']
mediaconvert_job_template = os.environ['MEDIACONVERT_JOB_TEMPLATE']
s3_bucket_upload = os.environ['S3_BUCKET_UPLOAD']
s3_bucket_output = os.environ['S3_BUCKET_OUTPUT']
iam_role_mediaconvert = os.environ['IAM_ROLE_MEDIACONVERT']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
s3 = boto3.client('s3')
mediaconvert = boto3.client('mediaconvert', region_name='ap-northeast-1', endpoint_url=mediaconvert_endpoint)
def lambda_handler(event, context):
print(aws_account_id)
print(mediaconvert_endpoint)
print(mediaconvert_job_template)
print(s3_bucket_upload)
print(s3_bucket_output)
print(iam_role_mediaconvert)
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
filename = (key.split('/')[1])
print("filename: " + filename)
input_file = "s3://" + s3_bucket_upload + "/" + key
print("input_file: " + input_file)
destination = "s3://" + s3_bucket_output + "/movie/"
print("destination: " + destination)
job_template = 'arn:aws:mediaconvert:ap-northeast-1:' + aws_account_id + ':jobTemplates/' + mediaconvert_job_template
print("job_template: " + job_template)
job_queue = 'arn:aws:mediaconvert:ap-northeast-1:' + aws_account_id + ':queues/Default'
print("job_queue: " + job_queue)
role = 'arn:aws:iam::' + aws_account_id + ':role/' + iam_role_mediaconvert
print("role: " + role)
with open("job.json", "r") as jsonfile:
job_object = json.load(jsonfile)
job_object["Inputs"][0]["FileInput"] = input_file
job_object["OutputGroups"][0]["OutputGroupSettings"]["HlsGroupSettings"]["Destination"] = destination
response = mediaconvert.create_job(
JobTemplate=job_template,
Queue=job_queue,
Role=role,
Settings=job_object
)
logger.info(response)
テストイベントの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/5f278703-6177-c912-2a13-5be4133d17fb.png)
{
"Records":[
{
"eventVersion":"2.1",
"eventSource":"aws:s3",
"awsRegion":"ap-northeast-1",
"eventTime":"2020-12-29T00:00:0.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AWS:000000000000000000000"
},
"requestParameters":{
"sourceIPAddress":"1.1.1.1"
},
"responseElements":{
"x-amz-request-id":"0000000000000000",
"x-amz-id-2":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"00000000-0000-0000-00000000000000000",
"bucket":{
"name":"drm-ni4-6ra-net-upload-origin",
"ownerIdentity":{
"principalId":"00000000000000"
},
"arn":"arn:aws:s3:::drm-ni4-6ra-net-upload-origin"
},
"object":{
"key":"/movie/demo01.mp4",
"size":4,
"eTag":"00000000000000000000000000000000",
"versionId":"00000000000000000000000000000000",
"sequencer":"000000000000000000"
}
}
}
]
}
###6.2.4. Lambda関数テスト
MediaConvertで変換した動画ファイルを出力するS3バケットを空にしておく
Lambda テストを実行
- テストイベントJSON の object key で変換する動画ファイルが設定されていることを確認する (今回は /movie/demo01.mp4)
###6.2.5. Web Player で再生確認
src に https://cdn.ni4-6ra.net/movie/demo01_auto.m3u8 を指定
<?php
setcookie("CloudFront-Policy", "eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Signature", "jTZDJUJBwV7qvim-baunYIZbkrQzVCu0Y8581PuStrYyjcki-5evNlpHqat1gTFSIGB8BcvhDyBRcBse~l6VKCoRw12HYNYpjYm1mAZjjmYjF0a7h4DrANDhAw~6B4VS5tNHntQ9zKr3xDZbzqwQEK-8D8xfMVWSHgdFn0OUef-zGeYp4mmty37tHWmXILHedrjjgLceXIkwIX-FPPMPwGMoPdV-Bu7cLckFZoXVxstHb64im-yp5yq0lzCjqK~VGMlD7Kh-qu9g2KKe15vIFZfDlpDc2y~E1uYmSVfwtbo6WaddaU26O02FCX0kKmu6CDcsR9XFvTwPru~L8PnKow__
", time() + 300, "/" , ".ni4-6ra.net", 0);
setcookie("CloudFront-Key-Pair-Id", "K1A3BSF7L9SNGX", time() + 300, "/" , ".ni4-6ra.net", 0);
?>
<html>
<head>
<title>Demo</title>
<link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
</head>
<body>
<video-js id=example-video width=1280 height=720 class="vjs-default-skin" controls>
</video-js>
<script src="https://vjs.zencdn.net/7.4.1/video.js"></script>
<script>
var player = videojs('example-video');
player.src({
src: 'https://cdn.ni4-6ra.net/movie/demo01_auto.m3u8',
type: 'application/x-mpegURL',
withCredentials: true
});
</script>
</body>
</html>
Mac Firefox で http://drm.ni4-6ra.net/player_auto.php にアクセス
###実際に動画ファイルをS3バケットにアップロードして動作確認
- S3 バケット drm-ni4-6ra-net-upload-origin の movie フォルダ内を空にする
- S3 バケット drm-ni4-6ra-net-cloudfront-origin の moview フォルダ内を空にする
- AWSマネジメントコンソールで S3 バケット drm-ni4-6ra-net-upload-origin の moive フォルダに demo01.mp4 をアップロードする
- Lambdaの実行ログ確認(CloudWatch ロググループの /aws/lambda/mediaconvert_ni4-6ra-net
- MediaConvert のステータス確認
- S3 バケット drm-ni4-6ra-net-cloudfront-origin の確認
- Web Player で確認
#7. 実際の運用での注意点
##7.1 CloudFrontキャッシュ設定
- ここでは動作検証のためキャッシュしない設定にしているので、検証が終わったら適切なキャッシュ設定を行う。
##7.2. 解像度と動画サイズ
-
HD (ハイビジョン画質)
-
解像度:720 × 1280
-
フルHD(フルハイビジョン画質)
-
解像度:1080 × 1920
-
スマホで録画した動画ファイルはフルHD
-
MediaConvertの解像度パススルー設定でコンバートすると、変換後の動画の解像度も 1080 × 1920 になる
-
4K
-
解像度:2160 x 3840
##7.2. 動画ファイル アップロードサイズ制限
- CMSサーバ経由で動画ファイルをS3へアップロードする場合、CMSサーバのメモリサイズが十分か確認したり、M/Wのファイルアップロード制限のチューニングを行う必要がある。
- 例えば php.ini
memory_limit = 2048M
post_max_size = 2048M
upload_max_filesize = 2048M
- 動画ファイルサイズを2GBで制限をかける場合は、許可する動画の再生時間を予め決めておく。