AWS MediaConvert と CloudFront 署名付きCookie で HLS+AES動画配信システムを作る

#0. はじめに
##0.1. 目的
* DRM動画配信サービス的なシステムをAWSを使って安価に作ってみる。
* このシステムのDRM的なこと
 * 動画ファイルを AES-128 で暗号化/復号する
 * ストリーミング動画と鍵を署名付きCookieで配信する

##0.2. 完成形
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/191aeada-e913-e58c-9cb0-30a8a663263a.png)


##0.3 構築ステップ
1. 動画アップロード用とCloudFrontオリジン用のS3バケット作成 と MediaConvert の動作確認
2. 動画配信用CloudFront作成、ACM作成、S3バケットOAI設定
3. CloudFront 署名付きURL/Cookie 設定
4. AES-128鍵用のS3バケットとCloudFrontを作成
5. Webサーバ(Apache+PHP)を作成、 CORS設定、 Video.js で Web Player 作成
6. アップロードした動画ファイルを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 作業ディレクトリ （システム完成形時のツリー）

```terminal
$ 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
```

```terraform:provider.tf
provider "aws" {
  version                 = "2.48.0"
  shared_credentials_file = "credentials"
  profile                 = "terraform"
  region                  = "ap-northeast-1"
}
```

```text:credentials
[terraform]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

#1. ステップ１ - 動画アップロード用とCloudFrontオリジン用のS3バケット作成 と MediaConvert の動作確認
##1.1. ステップ１ のゴール
* 動画アップロード用S3バケットに動画ファイルをアップロードして、MediaConvertでHLS動画に変換してCloudFrontオリジン用S3バケットへ出力する。
* 出力された HLS動画ファイルをローカルPCにダウンロードして、ffmpeg を使って mp4 ファイルに変換して QuickTime Player で再生する。
* 完成図
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9a6a1dcb-069e-4b89-752e-32ef828d8f4d.png)

##1.2. ステップ１ 構築
###1.2.1. オリジナル動画ファイルアップロード用 S3 バケット作成して、movie フォルダを作成

####S3バケット: drm-ni4-6ra-net-upload-origin

```terraform:s3-bucket_drm-ni4-6ra-net-upload-origin.tf
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"
}
```

####作成したS3バケット
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/46533f90-11c8-9c4b-5d01-614f684758e9.png)
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/b59ec2ee-1f0c-84f4-36c6-f844bf36efa1.png)

###1.2.2. CloudFrontオリジン用 S3 バケット作成して、movie フォルダを作成
####S3バケット: drm-ni4-6ra-net-cloudfront-origin

```terraform: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"
}
```

####作成したS3バケット
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/1d24c62d-9484-8f63-43be-03a429bfe6da.png)
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/318206d9-51a3-2756-c551-39007da74449.png)

###1.2.3. MediaConvert で使用する IAMロールを作成
####IAMロール: mediaconvert_ni4-6ra-net

```terraform:iam-role_mediaconvert_ni4-6ra-net.tf
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
}
```

####作成したIAMロール
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/8a67f9e1-12dc-1a93-5ee5-495b8b0dc00a.png)
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/050e519b-28a6-ac68-d7f0-f5eeefeef16f.png)
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/5a134cf4-27f3-a1e7-03e0-07b23442fc7b.png)
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0d669acc-f110-bff0-c956-a3e116e76c56.png)

###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/

* ダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/c7847058-c0e1-2e1c-2c9f-2fc8b5f1596f.png)

* ファイル名を demo01.mp4 に変える

####S3バケット drm-ni4-6ra-net-upload-origin の movie フォルダにアップロード
* AWS マネジメントコンソールから直接
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/bf5792da-b1d4-31fa-c68b-258dd04e33dd.png)

###1.2.5. MediaConvert で MP4 ⇒ HLS へ変換
####MediaConvertでジョブを作成
* AWS マネジメントコンソールから直接
**ジョブ**
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cba9a26c-c6ba-b953-6162-4ca88dc74971.png)
**ジョブ作成**
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cd9a2f97-82b7-6a5b-8dbb-68fc04d1a784.png)
**入力ファイルURL** ⇒ S3://drm-ni4-6ra-net-upload-origin/movie/demo01.mp4 を選択
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/11be1181-5d28-cd0d-e7d2-b583cf923637.png)
**出力グループ追加**
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9ee54ad6-6356-d8ce-d193-4c1f3896b6d5.png)
**Apple HLS を選択**
![014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ed0b6528-08a8-9667-c4a9-ae2e47ae9f75.png)
**出力 Output 1**
![015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0956c3c6-b143-e85a-9154-77fc8e24173d.png)
**名前修飾子** 必須項目 適当な名前を入れておく（ここでは _non-aes）
![016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/d01e3a57-31ad-8b44-b18b-1b9bcb9e957c.png)
**送信先** ⇒ S3://drm-ni4-6ra-net-cloudfront-origin/movie/ を選択
![022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/a722bfe1-cdbd-28e8-5a61-59735fd05fe0.png)
**解像度** ⇒ 空にしておく（空にするとパススルー設定となり、オリジナルと同じ解像度になる）
![017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0aabefb4-abb9-582e-8559-e50d72afc9d6.png)
**ビットレート** ⇒ 必須項目 適当に 2000kbps にしておく
![018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4a409478-e7a8-5ecb-0d1b-4c6db495e5de.png)
**ジョブの設定** ⇒ AWS の統合
![019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0bbcffcb-c905-9cd4-8222-34bcca2dfe35.png)
**IAMロール** ⇒ MediaConvert で使う IAMロールを指定する
![020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/96ab13db-b5c6-0be5-ebb2-3f0a9f796872.png)
以上、設定が終わったら **作成**

* ジョブのステータス確認
ステータス SUBMITTED ⇒ PROGRESSING ⇒ COMPLETE
![023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/a3c35081-5aaa-a5e1-7ada-c06d536d29ac.png)

* S3 バケット drm-ni4-6ra-net-cloudfront-origin/movie/ 確認
![024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/08b84bd7-02dd-d071-3b99-170e733bd7a9.png)

###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 インストール

```terminal
$ brew install ffmpeg
```

* ダウンロードしたファイルのあるフォルダで下記コマンドを実行

```terminal
$ 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 で再生してみる

```terminal
$ open demo01_non-aes.mp4
```

#2. ステップ２ - 動画配信用CloudFront作成、ACM作成、S3バケットOAI設定
##2.1. ステップ２ のゴール
* CloudFront経由で S3バケット drm-ni4-6ra-net-cloudfront-origin 内のオブジェクトにアクセスする。
* 完成図
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cfa4c5d7-7d8e-cf75-71f6-a153d93df443.png)


##2.2. ステップ２ 構築
###2.2.1. ACM作成
* 「米国東部 (バージニア北部)us-east-1」に作成する
* 手順は割愛
* 作成したACM （ワイルドカード）
* 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/dc669bb3-9b60-41c1-0800-67d3311e95aa.png)

###2.2.2. CloudFront作成
* S3バケット s3-bucket_drm-ni4-6ra-net-cloudfront-origin で「パブリックアクセスをすべてブロックする」設定を入れているので、OAI 設定がないと CloudFront から S3バケットにアクセスしたときに AccessDenied となる。

####CloudFront: E2L8V7QYSFINZX 

```terraform:cloudfront_cdn-ni4-6ra-net.tf
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 の設定抜粋

![025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/e2bf3bc5-ef6b-bd93-11d2-a573885f9c43.png)
![026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/6eb95627-a129-0993-6a5e-d1e8a08ac6ac.png)
OAI (Origin Access Identity) 設定
![027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ae8be357-41e0-df75-b870-fbb0101ff95c.png)
動作確認中に変なキャッシュをしないようにキャッシュしない設定にしておく
![028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/62ebaa2c-f3ac-15d0-c6b6-265a71b073e5.png)


###2.2.3. Route 53 設定
CloudFront の Domain Name と Alternate Domain Names の CNAME 設定
![029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/908c6cb9-51b3-c6f4-e58d-4402e63f1c97.png)
![030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/2ad868bb-d475-2f3e-2d02-54168f136e3d.png)

※この時点で https://cdn.ni4-6ra.net にアクセスしてみると 「Access Denied」 となる
![031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ea614a45-df7c-3f7e-b271-203b83542a58.png)

###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 に追記する

```terraform: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
}
```

####追加した設定
![032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/d2bacd06-da05-c997-23f9-1e0ab04ab0ed.png)
![033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4393cabd-d559-8fad-75e9-5a6a4fec3606.png)

###2.2.5. OAIアクセス確認

https://cdn.ni4-6ra.net にアクセス
![034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/49658b40-94d5-848e-4e8e-14f20666ae93.png)




#3. ステップ３ - CloudFront 署名付きURL/Cookie 設定
##3.1. ステップ３ のゴール
* 署名付きCookieリクエストでストリーミング動画ファイルにアクセスする
* 完成図
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/e15466db-9907-2aee-e56a-1229824a7420.png)


##3.3. ステップ３ 構築
###3.2.1. CloudFront署名付き URL/Cookie 向け公開鍵を作成して、Key Groups を設定
(参考)
[root ユーザー作業が不要に！Amazon CloudFront で署名付き URL/Cookie 向け公開鍵を IAM ユーザー権限で管理できるようになりました。](https://dev.classmethod.jp/articles/cloudfront-iam-signed-url/)

####キーペアを作成
ローカル作業PCのterraform作業ディレクトリで

```terminal
$ 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にアップロードする
```terraform:cloudfront_public-key.tf
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」 は後で必要になるのでメモっておく
![035.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/6ddc3f13-c31f-76d8-b62a-06a35f8ae026.png)


####Key Groups 設定
key group を作成する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
![036.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/28e900bb-b89c-17bc-7d52-143995cbeade.png)
![037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/48ca70ed-a390-2ec2-cd05-c61bd5271eff.png)
![038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/b1851c79-8b3e-d274-64d8-540a60b03d2b.png)

###3.2.2. CloudFront署名付き URL/Cookie を設定
CloudFront trusted key groups を設定する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
![039.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/c8cc4d3a-117d-2f74-c23f-a90da789d119.png)
![040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/20013e6b-f0b1-9c2c-2e42-9624ccd477b2.png)
Yes, Edit
![041.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/48cd00fb-69f4-22fa-7d34-8b73d4560fed.png)

###3.2.3. 署名付きCookieリクエストを作成して動作確認

(参考)
[署名付き Cookie を使用して HLS コンテンツを取得してみた](https://dev.classmethod.jp/articles/get-hls-using-signedcookie/)
[カスタムポリシーを使用する署名付き Cookie の設定](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html)
[Linux コマンドおよび OpenSSL を使用した Base64 エンコードおよび暗号化](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-linux-openssl.html)

####カスタムポリシーを使用する署名付き Cookie のポリシーステートメントの作成
ローカル作業PCのさきほどキーペアを作成したディレクトリにpolicy.jsonファイルを作成する
EpochTime は下記のサイトで求める（今回は検証用なので１年後の日付にしている）
https://www.epochconverter.com/

```json:policy.json
{
    "Statement": [
        {
            "Resource": "https://*.ni4-6ra.net/*",
            "Condition": {
                "DateLessThan": {
                    "AWS:EpochTime": 1640698309
                }
            }
        }
    ]
}
```

####ポリシーステートメントを base64 でエンコード・・・①
```terminal
$ cat policy.json | tr -d "\n" | tr -d " \t\n\r" | openssl base64 | tr -- '+=/' '-_~' | tr -d "\n" | tr -d " \t\n\r"
```
↓

```
eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly8qLm5pNC02cmEubmV0LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NDA2OTgzMDl9fX1dfQ__
```

####ポリシーステートメントをハッシュ化して署名・・・②
```terminal
$ 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」に置き換える
```terminal
$ curl https://cdn.ni4-6ra.net/movie/demo01_non-aes.m3u8 -b 'CloudFront-Policy=①; CloudFront-Signature=②; CloudFront-Key-Pair-Id=③' 
```

↓

```terminal
$ 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. ステップ４ - AES-128鍵用のS3バケットとCloudFrontを作成
##4.1. ステップ４ のゴール
* MediaConvertでHLS動画をAES暗号化する。
* HLS+AES動画ファイルをローカルPCにダウンロードして、ffmpeg を使って復号して mp4 ファイルに変換して QuickTime Player で再生する。
* 完成図
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/1392a950-7fd2-3573-0f92-51a20e1f8c20.png)


##4.2. ステップ４ 構築
###4.2.1. AES鍵用S3バケットを作成
####S3バケット: drm-ni4-6ra-net-aeskey
```terraform: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
}
```

####作成したS3バケット
![042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/2613b561-c50a-d38a-3c34-a8d51a47b6f3.png)


###4.2.2. AES鍵用CloudFrontを作成
####CloudFront: E28HDM2W6KJHQ2
````terraform:cloudfront_drm-aeskey-ni4-6ra-net.tf
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 の設定抜粋
![043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/8eff7079-48bd-0b82-3e38-ef719052b894.png)
![044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/271050ab-cb83-f2da-434e-87d4338c433e.png)
OAI (Origin Access Identity) 設定
![045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/b678eaa8-8d06-d9b0-c317-effb6bff7085.png)
動作確認中に変なキャッシュをしないようにキャッシュしない設定にしておく
![046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4d15ca68-0e00-5776-be53-39f8d95d8867.png)

###4.2.3. Route 53 設定
CloudFront の Domain Name と Alternate Domain Names の CNAME 設定
![047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0247286b-2aee-898d-c648-cfab74cf20ff.png)
![048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/fc94737b-7b1e-376b-624b-323391b03cb5.png)

###4.2.4. S3バケット drm-ni4-6ra-net-aeskey に OAI ポリシーを追加
####S3バケット drm-ni4-6ra-net-aeskey
※さきほどの s3-bucket_drm-ni4-6ra-net-aeskey.tf に追記する

```terraform: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
}
```
####追加した設定
![049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/3b19ba52-2aca-bfaf-f2a3-0988e947b129.png)
![050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/7144c1e0-189d-056c-dff5-297f75f28204.png)

###4.2.5. CloudFront署名付き URL/Cookie を設定
CloudFront trusted key groups を設定する terraform リソースがまだないので、マネジメントコンソールから手動で設定する
![051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/abf26328-d203-9a08-a30b-66da2d26f826.png)
![040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/20013e6b-f0b1-9c2c-2e42-9624ccd477b2.png)
Yes, Edit
![052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/d1175e07-ba55-2afa-8cdc-c64cd250ab82.png)


※この時点で https://drm-aeskey.ni4-6ra.net/ にアクセスしてみると 「Missing Key-Pair-Id query parameter or cookie value」 となる
![053.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/baa65521-536b-a4ee-53f8-a787e95cf7ce.png)


###4.2.6. AES鍵を作成して、S3バケット drm-ni4-6ra-net-aeskey へアップロードする
ローカル作業PCで

####静的キーを作成する
```terminal
$ openssl rand 16 > aes.key
```

####作成した静的キーから「静的キーの値」を生成 (MediaConverrt DRM暗号化設定に必要な値）
```terminal
$ xxd -ps aes.key
54a65de338c972d3f1dafe95ac936ad2
```

####「定数初期化ベクトル」を生成 (MediaConverrt DRM暗号化設定に必要な値）
```terminal
$ openssl rand -hex 16
d190b98ad29394fd6883a5dbd062a205
```

####aes.keyファイルをS3バケット drm-ni4-6ra-net-aeskey へアップロード
![054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/35846709-839a-2742-ce3c-17906059da66.png)


###4.2.7. 署名付きCookieリクエストで動作確認

署名付きCookieリクエストで https://drm-aeskey.ni4-6ra.net/aes.key を取得

```terminal
$ 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」を使う。

```terminal
$ 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.８. MediaConvertで MP4 ⇒ HLS+AES動画へ変換
####MediaConvertでジョブを作成
**ジョブ**
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cba9a26c-c6ba-b953-6162-4ca88dc74971.png)
**ジョブ作成**
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cd9a2f97-82b7-6a5b-8dbb-68fc04d1a784.png)
**入力ファイルURL** ⇒ S3://drm-ni4-6ra-net-upload-origin/movie/demo01.mp4 を選択
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/11be1181-5d28-cd0d-e7d2-b583cf923637.png)
**出力グループ 追加**
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9ee54ad6-6356-d8ce-d193-4c1f3896b6d5.png)
**Apple HLS を選択**
![014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ed0b6528-08a8-9667-c4a9-ae2e47ae9f75.png)
**送信先** ⇒ S3://drm-ni4-6ra-net-cloudfront-origin/movie/ を選択
![022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/a722bfe1-cdbd-28e8-5a61-59735fd05fe0.png)
**DRM 暗号化**
・定数初期化ベクトル: d190b98ad29394fd6883a5dbd062a205
・静的キーの値: 54a65de338c972d3f1dafe95ac936ad2
・URL: https://drm-aeskey.ni4-6ra.net/aes.key
![055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/60dc237d-4ef2-095e-5ed2-f05f3ac83212.png)
**出力 Output 1**
![015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/5f89195d-cf94-9162-c6da-ac9360705829.png)
**名前修飾子** ⇒ 必須項目 適当な名前を入れておく （ここでは _aes）
![056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/a634fe6c-4dae-eeab-886e-ebf499d045e1.png)
**解像度** ⇒ 空にしておく（空にするとパススルー設定となり、オリジナルと同じ解像度になる）
![017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0aabefb4-abb9-582e-8559-e50d72afc9d6.png)
**ビットレート** ⇒ 必須項目 適当に 2000kbps にしておく
![018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4a409478-e7a8-5ecb-0d1b-4c6db495e5de.png)
**ジョブの設定** ⇒ AWS の統合
![019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0bbcffcb-c905-9cd4-8222-34bcca2dfe35.png)
**IAMロール** ⇒ MediaConvert で使う IAMロールを指定する
![020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/96ab13db-b5c6-0be5-ebb2-3f0a9f796872.png)
以上、設定が終わったら **作成**


* ジョブのステータス確認
ステータス SUBMITTED ⇒ PROGRESSING ⇒ COMPLETE

* S3 バケット drm-ni4-6ra-net-cloudfront-origin/movie/ 確認
![057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f64f5651-e1c7-1f68-62f6-eb30d6be11eb.png)

###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コマンドを実行

```terminal
$ ffmpeg -allowed_extensions ALL -i "demo01_aes.m3u8" -c copy "demo01_aes.mp4"
```

* 生成された demo01_aes.mp4 を QuickTime Player で再生してみる

```terminal
$ open demo01_aes.mp4
```


#5. ステップ５ - Webサーバ(Apache+PHP)を作成、 CORS設定、 Video.js で Web Player 作成
##5.1. ステップ５ のゴール
* Video.js を使って HLS+AES動画をストリーミング配信で再生
* 完成図
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ee8ef0c3-fb2c-bd78-6d80-296744b943c7.png)


##5.2. ステップ５ 構築
###5.2.1. Webサーバ作成
#### EC2 AmazonLinux2 で適当に作成
今回 AMI は ami-01748a72bed07727c を使った
![058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/47aa4f92-5c32-e3d9-7683-727b74e16648.png)

#### Apache と PHP をインストール
```terminal
# 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レコード設定
![059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/43fdabfe-3752-2ea7-6240-78b35d4aa576.png)
![060.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f9b585fb-7e2f-c1f6-5ac4-1cbe4981834a.png)


###5.2.3. CORS設定
* CORS設定がうまくいかない場合は、ブラウザの開発スールの Webコンソールなのでエラーを確認する

#### CloudFront の E28HDM2W6KJHQ2 と E2L8V7QYSFINZX のCORS用設定
* それぞれの CloudFront 作成時に次の設定を入れているので、ここでは特に何もすることない
![061.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/5b3d3146-5b49-34e0-efce-c4010a64ffb3.png)

#### S3バケット drm-ni4-6ra-net-aeskey のCORS設定
s3-bucket_drm-ni4-6ra-net-aeskey.tf に cors_rule を追記

```terraform: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"
      }
    }
  }
  ## 下記を追記
  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
}
```

![062.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/2611c632-8dd3-1857-2384-fc119f6c2209.png)
![063.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/962a7ce8-cd72-0d9d-120e-2f9c8fe7218a.png)


#### S3バケット drm-ni4-6ra-net-cloudfront-origin のCORS設定
s3-bucket_drm-ni4-6ra-net-aeskey.tf に cors_rule を追記

```terraform: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"
      }
    }
  }
  ## 下記を追記
  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
}
```

![064.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/8c155927-de30-52fc-13af-e6f105daf28a.png)
![063.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/962a7ce8-cd72-0d9d-120e-2f9c8fe7218a.png)


###5.2.4. Video.js で Webプレーヤー作成 - サンプル
(参考)
[Video.jsのvideojs-http-streaming(VHS)を使ってHLS形式のストリーミング配信を再生する最低限度の設定](https://dev.classmethod.jp/articles/videojs-http-streaming-vhs-hls-streaming-minimum-setting/)

```php:playler_sample.php
<?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:player_non-aes.php
<?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 にアクセス
![065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/b906426d-f241-9a22-03c5-41f2d18b7e92.png)


###5.2.6. Video.js で Webプレーヤー作成 - AES暗号化された HLS動画を再生

src に AES暗号化されたHLS動画の m3u8 ファイル の URL https://cdn.ni4-6ra.net/movie/demo01_aes.m3u8 を指定

```php:player_aes.php
<?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 にアクセス
![066.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/8eb94358-2bd0-d520-24ae-aaed4c0aa529.png)


#6. ステップ６ - アップロードした動画ファイルをHLS+AES動画へ自動変換するLambdaを作成
##6.1. ステップ６ のゴール
* アップロードした動画ファイルを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

* 完成図
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0828a2d0-2904-c1cb-5a88-fa33a72c4874.png)


##6.2. ステップ６ 構築
###6.2.1. MediaConvert ジョブテンプレート作成
* 今回は 自動回転、サーバー側の暗号化 なども設定する
* ジョブテンプレートでは、次のものは設定しない
 * 入力ファイルURL
 * 送信先
 * IAMロール

**ジョブテンプレート** ⇒ テンプレートの作成
![067.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9069797d-f698-8892-a109-d6ac9ae623d8.png)
**一般設定** ⇒ 名前を適当に付ける
![068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/e15e2f53-982c-bafc-d0bd-d10297950c0f.png)
**入力 追加**
![069.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/edeb6a4a-fb41-22a2-050e-1af2fe03ead2.png)
**回転させる** ⇒ 自動
![070.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/03906022-47ab-3516-9c97-e5715c1f776e.png)
**出力グループ 追加**
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9ee54ad6-6356-d8ce-d193-4c1f3896b6d5.png)
**Apple HLS を選択**
![014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/ed0b6528-08a8-9667-c4a9-ae2e47ae9f75.png)
**サーバー側の暗号化設定**
![071.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9cfbd18f-8d10-b7ea-2b0f-13f9b0816988.png)
**DRM 暗号化設定**
・定数初期化ベクトル: d190b98ad29394fd6883a5dbd062a205
・静的キーの値: 54a65de338c972d3f1dafe95ac936ad2
・URL: https://drm-aeskey.ni4-6ra.net/aes.key
![055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/60dc237d-4ef2-095e-5ed2-f05f3ac83212.png)
**出力 Output 1**
![015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/5f89195d-cf94-9162-c6da-ac9360705829.png)
**名前修飾子** ⇒ 必須項目 適当な名前を入れておく （ここでは _auto）
![072.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/6d34284b-cf09-b2a8-df6f-87b37d1fad47.png)
**解像度** ⇒ 空にしておく（空にするとパススルー設定となり、オリジナルと同じ解像度になる）
![017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/0aabefb4-abb9-582e-8559-e50d72afc9d6.png)
**ビットレート** ⇒ 必須項目 適当に 2000kbps にしておく
![018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4a409478-e7a8-5ecb-0d1b-4c6db495e5de.png)
以上、設定が終わったら **作成**


###6.2.2. Lambdaで使用するIAMロールを作成

####IAMロール名: lambda_mediaconvert_ni4-6ra-net

```terraform:iam-role_lambda_mediaconvert_ni4-6ra-net.tf
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
}
```

####作成したIAMロール
![073.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/33fdad94-ebd3-5102-9959-cc8f7ee82caf.png)
![074.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/d4877269-9025-e943-8488-3157444e3fb6.png)
![075.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/9d1e7bae-5104-03c1-2a58-c7eb2c18f6cd.png)


###6.2.3. Lambda関数作成
* ランタイムは Python3.7

関数の作成
![076.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/a72a3d3a-0150-f714-b8b6-1f328535f380.png)

**一から作成**
![077.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/8573aabf-8e28-0ba8-e0ed-85b95161d1ec.png)

**基本的な情報**
・関数名は適当に（ここでは mediaconvert_ni4-6ra-net）
・ランタイムは Python 3.7
・既存のロール lambda_mediaconvert_ni4-6ra-net
![078.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/3fe1bac0-6d11-07d8-dccb-b1920b08fa32.png)

**関数の作成**

**トリガーを追加**
![079.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4f085c20-fe1b-a7b6-cd62-ce320f5c3ce3.png)

**トリガーの設定**
![080.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cd4342f1-c383-8d37-1f74-35a731946728.png)
![081.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f163bb3c-0b7f-7e4d-0446-76208fb31774.png)

**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のダッシュボードで確認できる
![082.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f1f1f7a5-b5be-340e-921a-f7be34fd41d3.png)
![083.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f725e1ad-d25b-ab35-b1b8-982d07aa6668.png)

**関数コード**

```json:job.json
{
  "OutputGroups": [
    {
        "Name": "Apple HLS",
        "OutputGroupSettings": {
          "Type": "HLS_GROUP_SETTINGS",
          "HlsGroupSettings": {
            "Destination": ""
        }
      }

    }
  ],
  "Inputs": [
    {
      "FileInput": ""
    }
  ]
}
```

```python:lambda_function

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)
```

![084.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/f71b2fdf-af7c-3385-a855-b10c2953cdf0.png)


**テストイベントの設定**

```json:S3PubObject
![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"
            }
         }
      }
   ]
}
```

![085.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/1d364fb8-52d5-aa5b-8e0f-da0e73b087c1.png)

###6.2.4. Lambda関数テスト
MediaConvertで変換した動画ファイルを出力するS3バケットを空にしておく
![086.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/7c9e1e83-1232-d695-c51a-303e907566f3.png)

Lambda テストを実行
* テストイベントJSON の object key で変換する動画ファイルが設定されていることを確認する （今回は /movie/demo01.mp4）

![087.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/cbe92c4d-79a0-156b-28db-ed045c9e826b.png)

* Lambda実行結果
![088.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/6f68e0b5-2741-f0ab-8405-ce8ae6cf37a5.png)

* MediaConvert ジョブステータス
![089.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/4737319e-0457-2231-d7de-1330ff5c8422.png)

* S3バケット drm-ni4-6ra-net-cloudfront-origin 確認
![090.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/3dcd61c9-2a4a-f319-f8e4-277e3af96812.png)

###6.2.5. Web Player で再生確認

src に https://cdn.ni4-6ra.net/movie/demo01_auto.m3u8 を指定

```php:player_auto.php
<?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 にアクセス
![091.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148868/bb1b4062-cbd9-46ab-1ad6-5139806f3601.png)

###実際に動画ファイルを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
<pre>
memory_limit = 2048M
post_max_size = 2048M
upload_max_filesize = 2048M
</pre>
* 動画ファイルサイズを2GBで制限をかける場合は、許可する動画の再生時間を予め決めておく。