[AWS] MediaConvert(S3 event lambda) 자동화 CloudFormation

류정현·2024년 10월 2일

고객이 업로드하는 동영상은 정말 다양한 파일크기, 다양한 확장자와 다양한 해상도와 다양한 여러 옵션으로 만들어진 결과물이었다.
우리의 목표는 품질을 최대한 떨어뜨리지 않으며, 영상을 서비스하는데 비용을 아낄 수 있도록 데이터트래픽 비용을 감소하는 것 이었다.

학교에서 배웠던 것을 기억해보면 동영상은 빠르게 화면을 변경해주고, 그 잔상효과로 움직이는 것처럼 느끼게 해주며, 그 위에? 뒤에? 소리가 함께 재생되도록 한 것이었다.
주니어 때 OPEN CV 를 이용해 사람얼굴에 대한 패턴을 영상에 적용해 내 뒤통수에도 눈이 달려 있는 것처럼, 그래서 사무실에서 내 모니터에 대한 보안을 위한 프로그램을 만들었을 때도, 빠르게 찍어내는 사진에 패턴이 적용되고 패턴이 적용된 곳에 사각프레임을 씌우고, BEEP 음을 내도록 했었다.
내 머릿속의 기억은 동영상 = 시간 정렬된 겁나 많은 사진들이었다.

기억은 여기까지였고, 목표를 이루기 위해서는 동영상에 대해 먼저 이해가 필요했다.
인/디코딩방식, 코덱의 종류, 해상도, 초당프레임수(FPS), BIT RATE 등 대충 아는 것과 모르는 것을 모두 뽑아 대충 조사하였다.

그래서 비디오 포멧은?
컨테이너 포멧형식에 따라 무엇이 화질이 좋은가? 라고 생각했던 건 초반의 멍청한 생각이었다. 그러면 우리는 웹에서 표현하기에 가장 적절하고 용이한 포멧을 골라 변환한다. 라는 생각을 했고, 그 중에 wepM 이라는 포멧형식을 선택했었다. (무려 구글의 후원을 받았… 다고 하니 )

WebM(웹엠)은 로열티 비용이 없는 개방형 고화질 영상 압축 형식의 영상 포맷이며 HTML5 비디오와 함께 이용한다. 2010년 5월 19일에 처음 나왔으며 이 프로젝트는 구글의 후원을 받아 개발된다.

WebM 파일은 VP8 비디오와 Vorbis 오디오 스트림으로 이루어져 있으며, 2013년에  VP9 비디오와 Opus 오디오를 수용하는 것으로 갱신되었다. WebM 컨테이너는 마트료시카 프로파일에 기반을 둔다. 이 프로젝트는 BSD 라이선스 하에서 WebM 관련 소프트웨어를 출시하며 모든 사용자는 아무런 비용 없이 이를 이용할 수 있다.

우리 앱은 웹앱으로 제작된 것으로 안드로이드와 iOS 에서 모두 지원되어야 하며, 모바일환경에서 앱과 웹 모두 지원되어야 했기에 주저없이 선택했다.

그래서 용량은?
우리는 원본을 그대로 보여줄 수는 없고(80MB 짜리도 있음 -_- 4K = 가로세로가 3,840개, 세로에 2,160개, 총 830만 개의 픽셀이 있는 해상도 ) 우리사이트의 최적해상도 480px에 맞추어 영상을 퍼블리싱하도록 변환해야만 한다. 를 알 수 있었다.

다시 생각해보니 영상은 정지화면의 시간정렬 집합이고,
이 정지화면을 1초에 얼마나 많이 보여주는가?
그리고 1초에 데이터를 얼마나 처리하는가?
정지화면은 가로세로 크기가 얼마나 되는가?

를 고려해야 한다.

여기엔 정답이 없었다. 영상은 천차만별이었고, 화질(영상의품질)도 고정이 아니었다. 용량이 크다고 화질이 좋은 것도 아니었다. 그래서 얻은 결론은
우리가 확보한 영상들을 기준으로 하는 우리만의 최적화를 위한 TEST !!!!!

실험을 통해

  1. 영상은 가로 480px 로 변환하며 가로세로 비율을 원본과 동일하게 해도 좋다. 단, 원본의 영상 가로 크기가 480px 미만일 경우는 영상크기를 원본과 동일하게 유지한다.
  2. 의외로 FPS ( 정지화면을 1초에 얼마나 많이 보여주는가? ) 는 크게 중요하지 않아 30 FPS로 변환해도 괜찮았다.
  3. Bit Rate 가 중요했는데, 해상도가 높아도 비트레이트가 낮으면 화면이 뭉개진다. 비트레이트를 높이면 원본보다 크기가 커지는 경우가 많아진다. ( = 이율배반 ) 고객의 동영상은 비트레이트가 제각각이다.

위의 3가지를 알 수 있었고, 가장 중요한 원판불변의 법칙(ㅎㅎ) 을 다시 깨닫게 되었다.
원본이 그지 같으면 그 이상의 품질을 용량을 줄이면서 만들 수는 없……

1번과 2번은 결정되었는데 3번의 결정이 어려워 검색을 해 본 결과, 우리가 사용한 고정 bit rate 말고 가변 bit rate(variable bitrate, VBR) 가 있다는 것을 알게되었다.
정지화면에서 영상의 색과 표현되는 객체가 복잡한 경우 bit rate 를 높게, 그렇지 않을 경우 bit rate 를 낮게 하는 방식이다.
또한 품질 기반 가변 비트레이트(QVBR) 가 있다는 것을 알게 되었고 우리가 사용할 MediaConvert에서 제공하고 있다는 것도 알게 되었다.

인코딩한 비디오의 가장 중요한 특성이 품질이라면 이를 달성하는 간단하고 확실한 방법은 일정한 비디오 품질을 제공하고 프로세스에서 제로 비트를 낭비하지 않도록 설계된 품질 기반 가변 비트레이트(QVBR) 제어를 사용하는 것입니다.
즉, 비디오 품질 요구 사항이 높지만 대역폭 예산이 낮은 경우 QVBR은 두 가지 요구를 모두 충족시킵니다. AWS Elemental 소프트웨어에는 추가 라이선스 비용 없이 QVBR이 포함되어 있습니다.

위에서 언급한 wepM 은 QVBR을 지원하지 않는다. 따라서 QVBR 을 지원하면서 범용성이 좋은 mp4 인코딩 컨테이너로 결정하였다.

이제는

  1. 영상을 변환하고
  2. 영상을 크기에 맞게 잘라보여주도록 하면

품질의 손상을 최소화하면서 트래픽 비용을 감소하도록 하는 전략이 만들어 졌다.

영상 변환 아키텍처


S3 에 원본을 올린다.

S3 putitem event trigger 가 감지되면 Lambda Function 이 MediaConvert를 호출하고
영상에 대한 변환을 지정한 옵션에 맞추어 진행한 후,
MediaConvert 가 S3 에 변환된 영상을 저장한다.
CloudFront 는 변환된 영상이 지정된 S3를 원본으로 하여 CDN 서비스를 사용하도록 한다.

작업이 완료되면 SNS 를 통해 메일 혹은 Slack 으로 영상변환에 대한 알림을 한다.

출력 그룹 옵션 설정

인코딩 속도가 중요해서 단일패스HQ 를 선택

S3 원본 버킷과 변환 버킷

CloudFormation 템플릿

{
  "Description": "(SO0146) Video on Demand on AWS Foundation Solution Implementation. Version v1.3.4",
  "Mappings": {
    "Send": {
      "AnonymizedUsage": {
        "Data": "Yes"
      }
    }
  },
  "Parameters": {
    "emailAddress": {
      "Type": "String",
      "AllowedPattern": "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)(\\.[A-Za-z]{2,})$",
      "Description": "The admin email address to receive SNS notifications for job status."
    }
  },
  "Resources": {
    "Logs6819BB44": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccessControl": "LogDeliveryWrite",
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {
              "ServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
              }
            }
          ]
        },
        "OwnershipControls": {
          "Rules": [
            {
              "ObjectOwnership": "ObjectWriter"
            }
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "VersioningConfiguration": {
          "Status": "Enabled"
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Logs bucket does not require logging configuration"
            },
            {
              "id": "W51",
              "reason": "Logs bucket is private and does not require a bucket policy"
            }
          ]
        },
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Used to store access logs for other buckets",
              "id": "AwsSolutions-S1"
            },
            {
              "reason": "Bucket is private and is not using HTTP",
              "id": "AwsSolutions-S10"
            }
          ]
        }
      }
    },
    "LogsPolicy90DB40C9": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {
          "Ref": "Logs6819BB44"
        },
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "s3:",
              "Condition": {
                "Bool": {
                  "aws:SecureTransport": "false"
                }
              },
              "Effect": "Deny",
              "Principal": {
                "AWS": ""
              },
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "Logs6819BB44",
                    "Arn"
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Logs6819BB44",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Logs/Policy/Resource"
      }
    },
    "Source71E471F1": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": "vastyle-veed-origin",
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {
              "ServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
              }
            }
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {
            "Ref": "Logs6819BB44"
          },
          "LogFilePrefix": "source-bucket-logs/"
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "VersioningConfiguration": {
          "Status": "Enabled"
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W51",
              "reason": "source bucket is private and does not require a bucket policy"
            }
          ]
        },
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Bucket is private and is not using HTTP",
              "id": "AwsSolutions-S10"
            }
          ]
        }
      }
    },
    "SourcePolicyE5AB5F73": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {
          "Ref": "Source71E471F1"
        },
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "s3:",
              "Condition": {
                "Bool": {
                  "aws:SecureTransport": "false"
                }
              },
              "Effect": "Deny",
              "Principal": {
                "AWS": ""
              },
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "Source71E471F1",
                    "Arn"
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Source71E471F1",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Source/Policy/Resource"
      }
    },
    "Destination920A3C57": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": "vastyle-veed-converted",
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {
              "ServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
              }
            }
          ]
        },
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": [
                ""
              ],
              "AllowedMethods": [
                "GET"
              ],
              "AllowedOrigins": [
                ""
              ],
              "MaxAge": 3000
            }
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {
            "Ref": "Logs6819BB44"
          },
          "LogFilePrefix": "destination-bucket-logs/"
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "VersioningConfiguration": {
          "Status": "Enabled"
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Destination/Resource",
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Bucket is private and is not using HTTP",
              "id": "AwsSolutions-S10"
            }
          ]
        }
      }
    },
    "DestinationPolicy7982387E": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {
          "Ref": "Destination920A3C57"
        },
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "s3:",
              "Condition": {
                "Bool": {
                  "aws:SecureTransport": "false"
                }
              },
              "Effect": "Deny",
              "Principal": {
                "AWS": ""
              },
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "Destination920A3C57",
                    "Arn"
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Destination920A3C57",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            },
            {
              "Action": "s3:GetObject",
              "Effect": "Allow",
              "Principal": {
                "CanonicalUser": {
                  "Fn::GetAtt": [
                    "CloudFrontCloudFrontDistributionOrigin1S3Origin17B88F1A",
                    "S3CanonicalUserId"
                  ]
                }
              },
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    {
                      "Fn::GetAtt": [
                        "Destination920A3C57",
                        "Arn"
                      ]
                    },
                    "/"
                  ]
                ]
              }
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Destination/Policy/Resource",
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F16",
              "reason": "Public website bucket policy requires a wildcard principal"
            }
          ]
        },
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Bucket is private and is not using HTTP",
              "id": "AwsSolutions-S10"
            }
          ]
        }
      }
    },
    "CloudFrontCloudFrontDistributionOrigin1S3Origin17B88F1A": {
      "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity",
      "Properties": {
        "CloudFrontOriginAccessIdentityConfig": {
          "Comment": "Identity for VodFoundationCloudFrontCloudFrontDistributionOrigin1F191A578"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/CloudFront/CloudFrontDistribution/Origin1/S3Origin/Resource"
      }
    },
    "CloudFrontCloudFrontDistribution824F3346": {
      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
        "DistributionConfig": {
          "Comment": {
            "Fn::Join": [
              "",
              [
                {
                  "Ref": "AWS::StackName"
                },
                " Video on Demand Foundation"
              ]
            ]
          },
          "DefaultCacheBehavior": {
            "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
            "Compress": true,
            "TargetOriginId": "VodFoundationCloudFrontCloudFrontDistributionOrigin1F191A578",
            "ViewerProtocolPolicy": "redirect-to-https"
          },
          "DefaultRootObject": "index.html",
          "Enabled": true,
          "HttpVersion": "http2",
          "IPV6Enabled": true,
          "Logging": {
            "Bucket": {
              "Fn::GetAtt": [
                "Logs6819BB44",
                "RegionalDomainName"
              ]
            },
            "Prefix": "cloudfront-logs/"
          },
          "Origins": [
            {
              "DomainName": {
                "Fn::GetAtt": [
                  "Destination920A3C57",
                  "RegionalDomainName"
                ]
              },
              "Id": "VodFoundationCloudFrontCloudFrontDistributionOrigin1F191A578",
              "S3OriginConfig": {
                "OriginAccessIdentity": {
                  "Fn::Join": [
                    "",
                    [
                      "origin-access-identity/cloudfront/",
                      {
                        "Ref": "CloudFrontCloudFrontDistributionOrigin1S3Origin17B88F1A"
                      }
                    ]
                  ]
                }
              }
            }
          ]
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/CloudFront/CloudFrontDistribution/Resource",
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W70",
              "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion"
            }
          ]
        },
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Use case does not warrant CloudFront Geo restriction",
              "id": "AwsSolutions-CFR1"
            },
            {
              "reason": "Use case does not warrant CloudFront integration with AWS WAF",
              "id": "AwsSolutions-CFR2"
            },
            {
              "reason": "CloudFront automatically sets the security policy to TLSv1 when the distribution uses the CloudFront domain name",
              "id": "AwsSolutions-CFR4"
            }
          ]
        }
      }
    },
    "MediaConvertRole031A64A9": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "mediaconvert.amazonaws.com"
              }
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/MediaConvertRole/Resource"
      }
    },
    "MediaconvertPolicy9E3026EC": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": [
                "s3:GetObject",
                "s3:PutObject"
              ],
              "Effect": "Allow",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Source71E471F1",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Destination920A3C57",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            },
            {
              "Action": "execute-api:Invoke",
              "Effect": "Allow",
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    "arn:",
                    {
                      "Ref": "AWS::Partition"
                    },
                    ":execute-api:",
                    {
                      "Ref": "AWS::Region"
                    },
                    ":",
                    {
                      "Ref": "AWS::AccountId"
                    },
                    ":"
                  ]
                ]
              }
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "MediaconvertPolicy9E3026EC",
        "Roles": [
          {
            "Ref": "MediaConvertRole031A64A9"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/MediaconvertPolicy/Resource",
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "/ required to get/put objects to S3",
              "id": "AwsSolutions-IAM5"
            }
          ]
        }
      }
    },
    "CustomResourceRoleAB1EF463": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/CustomResourceRole/Resource"
      }
    },
    "CustomResourcePolicy79526710": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": [
                "s3:PutObject",
                "s3:PutBucketNotification"
              ],
              "Effect": "Allow",
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "Source71E471F1",
                    "Arn"
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Source71E471F1",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            },
            {
              "Action": "mediaconvert:DescribeEndpoints",
              "Effect": "Allow",
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    "arn:aws:mediaconvert:",
                    {
                      "Ref": "AWS::Region"
                    },
                    ":",
                    {
                      "Ref": "AWS::AccountId"
                    },
                    ":"
                  ]
                ]
              }
            },
            {
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Effect": "Allow",
              "Resource": ""
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "CustomResourcePolicy79526710",
        "Roles": [
          {
            "Ref": "CustomResourceRoleAB1EF463"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/CustomResourcePolicy/Resource",
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Resource ARNs are not generated at the time of policy creation",
              "id": "AwsSolutions-IAM5"
            }
          ]
        },
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W12",
              "reason": "Resource ARNs are not generated at the time of policy creation"
            }
          ]
        }
      }
    },
    "CustomResource8CDCD7A7": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Fn::Sub": "solutions-${AWS::Region}"
          },
          "S3Key": "video-on-demand-on-aws-foundation/v1.3.4/asset593ffc2c71667806ba8de7036f9925188e1e3c155d93996a4f18a4b478c8b8c8.zip"
        },
        "Description": "CFN Custom resource to copy assets to S3 and get the MediaConvert endpoint",
        "Environment": {
          "Variables": {
            "SOLUTION_IDENTIFIER": "AwsSolution/SO0146/v1.3.4"
          }
        },
        "Handler": "asset593ffc2c71667806ba8de7036f9925188e1e3c155d93996a4f18a4b478c8b8c8/index.handler",
        "Role": {
          "Fn::GetAtt": [
            "CustomResourceRoleAB1EF463",
            "Arn"
          ]
        },
        "Runtime": "nodejs18.x",
        "Timeout": 30
      },
      "DependsOn": [
        "CustomResourcePolicy79526710",
        "CustomResourceRoleAB1EF463"
      ],
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W58",
              "reason": "Invalid warning: function has access to cloudwatch"
            },
            {
              "id": "W89",
              "reason": "Invalid warning: lambda not needed in VPC"
            },
            {
              "id": "W92",
              "reason": "Invalid warning: lambda does not need ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "Endpoint": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": {
          "Fn::GetAtt": [
            "CustomResource8CDCD7A7",
            "Arn"
          ]
        }
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete",
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Endpoint/Default"
      }
    },
    "JobSubmitRole4FA8E972": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobSubmitRole/Resource"
      }
    },
    "JobSubmitRoleDefaultPolicy20E077D9": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "sns:Publish",
              "Effect": "Allow",
              "Resource": {
                "Ref": "NotificationSnsTopicB941FD22"
              }
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "JobSubmitRoleDefaultPolicy20E077D9",
        "Roles": [
          {
            "Ref": "JobSubmitRole4FA8E972"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobSubmitRole/DefaultPolicy/Resource"
      }
    },
    "JobSubmitPolicy098DF0F8": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "iam:PassRole",
              "Effect": "Allow",
              "Resource": {
                "Fn::GetAtt": [
                  "MediaConvertRole031A64A9",
                  "Arn"
                ]
              }
            },
            {
              "Action": "mediaconvert:CreateJob",
              "Effect": "Allow",
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    "arn:",
                    {
                      "Ref": "AWS::Partition"
                    },
                    ":mediaconvert:",
                    {
                      "Ref": "AWS::Region"
                    },
                    ":",
                    {
                      "Ref": "AWS::AccountId"
                    },
                    ":"
                  ]
                ]
              }
            },
            {
              "Action": "s3:GetObject",
              "Effect": "Allow",
              "Resource": [
                {
                  "Fn::GetAtt": [
                    "Source71E471F1",
                    "Arn"
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      {
                        "Fn::GetAtt": [
                          "Source71E471F1",
                          "Arn"
                        ]
                      },
                      "/"
                    ]
                  ]
                }
              ]
            },
            {
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Effect": "Allow",
              "Resource": ""
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "JobSubmitPolicy098DF0F8",
        "Roles": [
          {
            "Ref": "JobSubmitRole4FA8E972"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobSubmitPolicy/Resource",
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Resource ARNs are not generated at the time of policy creation",
              "id": "AwsSolutions-IAM5"
            }
          ]
        },
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W12",
              "reason": "Resource ARNs are not generated at the time of policy creation"
            }
          ]
        }
      }
    },
    "jobSubmitB391E42F": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Fn::Sub": "solutions-${AWS::Region}"
          },
          "S3Key": "video-on-demand-on-aws-foundation/v1.3.4/asset44691a20d2ce91fc1c3225baffe7e83a47587d2272d208d2f5df001811fc3865.zip"
        },
        "Description": "Submits an Encoding job to MediaConvert",
        "Environment": {
          "Variables": {
            "MEDIACONVERT_ENDPOINT": {
              "Fn::GetAtt": [
                "Endpoint",
                "Endpoint"
              ]
            },
            "MEDIACONVERT_ROLE": {
              "Fn::GetAtt": [
                "MediaConvertRole031A64A9",
                "Arn"
              ]
            },
            "JOB_SETTINGS": "job-settings.json",
            "DESTINATION_BUCKET": {
              "Ref": "Destination920A3C57"
            },
            "SOLUTION_ID": "SO0146",
            "STACKNAME": {
              "Ref": "AWS::StackName"
            },
            "SOLUTION_IDENTIFIER": "AwsSolution/SO0146/v1.3.4",
            "SNS_TOPIC_ARN": {
              "Ref": "NotificationSnsTopicB941FD22"
            },
            "SNS_TOPIC_NAME": {
              "Fn::GetAtt": [
                "NotificationSnsTopicB941FD22",
                "TopicName"
              ]
            }
          }
        },
        "Handler": "asset44691a20d2ce91fc1c3225baffe7e83a47587d2272d208d2f5df001811fc3865/index.handler",
        "Role": {
          "Fn::GetAtt": [
            "JobSubmitRole4FA8E972",
            "Arn"
          ]
        },
        "Runtime": "nodejs18.x",
        "Timeout": 30
      },
      "DependsOn": [
        "JobSubmitPolicy098DF0F8",
        "JobSubmitRoleDefaultPolicy20E077D9",
        "JobSubmitRole4FA8E972"
      ],
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W58",
              "reason": "Invalid warning: function has access to cloudwatch"
            },
            {
              "id": "W89",
              "reason": "Invalid warning: lambda not needed in VPC"
            },
            {
              "id": "W92",
              "reason": "Invalid warning: lambda does not need ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "jobSubmitEventInvokeConfig0385F502": {
      "Type": "AWS::Lambda::EventInvokeConfig",
      "Properties": {
        "FunctionName": {
          "Ref": "jobSubmitB391E42F"
        },
        "MaximumRetryAttempts": 0,
        "Qualifier": "$LATEST"
      },
      "DependsOn": [
        "JobSubmitPolicy098DF0F8",
        "JobSubmitRoleDefaultPolicy20E077D9",
        "JobSubmitRole4FA8E972"
      ],
      "Metadata": {
        "aws:cdk:path": "VodFoundation/jobSubmit/EventInvokeConfig/Resource"
      }
    },
    "jobSubmitS3Trigger3DEB8D7C": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::GetAtt": [
            "jobSubmitB391E42F",
            "Arn"
          ]
        },
        "Principal": "s3.amazonaws.com",
        "SourceAccount": {
          "Ref": "AWS::AccountId"
        }
      },
      "DependsOn": [
        "JobSubmitPolicy098DF0F8",
        "JobSubmitRoleDefaultPolicy20E077D9",
        "JobSubmitRole4FA8E972"
      ],
      "Metadata": {
        "aws:cdk:path": "VodFoundation/jobSubmit/S3Trigger"
      }
    },
    "JobCompleteRole81FD9028": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              }
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobCompleteRole/Resource"
      }
    },
    "JobCompleteRoleDefaultPolicyD4DC2F12": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "sns:Publish",
              "Effect": "Allow",
              "Resource": {
                "Ref": "NotificationSnsTopicB941FD22"
              }
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "JobCompleteRoleDefaultPolicyD4DC2F12",
        "Roles": [
          {
            "Ref": "JobCompleteRole81FD9028"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobCompleteRole/DefaultPolicy/Resource"
      }
    },
    "JobCompletePolicyBBFD3892": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "mediaconvert:GetJob",
              "Effect": "Allow",
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    "arn:",
                    {
                      "Ref": "AWS::Partition"
                    },
                    ":mediaconvert:",
                    {
                      "Ref": "AWS::Region"
                    },
                    ":",
                    {
                      "Ref": "AWS::AccountId"
                    },
                    ":"
                  ]
                ]
              }
            },
            {
              "Action": [
                "s3:GetObject",
                "s3:PutObject"
              ],
              "Effect": "Allow",
              "Resource": {
                "Fn::Join": [
                  "",
                  [
                    {
                      "Fn::GetAtt": [
                        "Source71E471F1",
                        "Arn"
                      ]
                    },
                    "/"
                  ]
                ]
              }
            },
            {
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Effect": "Allow",
              "Resource": ""
            }
          ],
          "Version": "2012-10-17"
        },
        "PolicyName": "JobCompletePolicyBBFD3892",
        "Roles": [
          {
            "Ref": "JobCompleteRole81FD9028"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobCompletePolicy/Resource",
        "cdk_nag": {
          "rules_to_suppress": [
            {
              "reason": "Resource ARNs are not generated at the time of policy creation",
              "id": "AwsSolutions-IAM5"
            }
          ]
        },
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W12",
              "reason": "Resource ARNs are not generated at the time of policy creation"
            }
          ]
        }
      }
    },
    "JobComplete703682D0": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Fn::Sub": "solutions-${AWS::Region}"
          },
          "S3Key": "video-on-demand-on-aws-foundation/v1.3.4/asset4d8cbdf2ef743ca7aaac8177d00f15e4f064ceaf4e6c0d1b44ec4441dc06ce95.zip"
        },
        "Description": "Triggered by EventBridge,processes completed MediaConvert jobs.",
        "Environment": {
          "Variables": {
            "MEDIACONVERT_ENDPOINT": {
              "Fn::GetAtt": [
                "Endpoint",
                "Endpoint"
              ]
            },
            "CLOUDFRONT_DOMAIN": {
              "Fn::GetAtt": [
                "CloudFrontCloudFrontDistribution824F3346",
                "DomainName"
              ]
            },
            "SOURCE_BUCKET": {
              "Ref": "Source71E471F1"
            },
            "JOB_MANIFEST": "jobs-manifest.json",
            "STACKNAME": {
              "Ref": "AWS::StackName"
            },
            "METRICS": {
              "Fn::FindInMap": [
                "Send",
                "AnonymizedUsage",
                "Data"
              ]
            },
            "SOLUTION_ID": "SO0146",
            "VERSION": "v1.3.4",
            "UUID": {
              "Fn::GetAtt": [
                "Endpoint",
                "UUID"
              ]
            },
            "SOLUTION_IDENTIFIER": "AwsSolution/SO0146/v1.3.4",
            "SNS_TOPIC_ARN": {
              "Ref": "NotificationSnsTopicB941FD22"
            },
            "SNS_TOPIC_NAME": {
              "Fn::GetAtt": [
                "NotificationSnsTopicB941FD22",
                "TopicName"
              ]
            }
          }
        },
        "Handler": "asset4d8cbdf2ef743ca7aaac8177d00f15e4f064ceaf4e6c0d1b44ec4441dc06ce95/index.handler",
        "Role": {
          "Fn::GetAtt": [
            "JobCompleteRole81FD9028",
            "Arn"
          ]
        },
        "Runtime": "nodejs18.x",
        "Timeout": 30
      },
      "DependsOn": [
        "JobCompletePolicyBBFD3892",
        "JobCompleteRoleDefaultPolicyD4DC2F12",
        "JobCompleteRole81FD9028"
      ],
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W58",
              "reason": "Invalid warning: function has access to cloudwatch"
            },
            {
              "id": "W89",
              "reason": "Invalid warning: lambda not needed in VPC"
            },
            {
              "id": "W92",
              "reason": "Invalid warning: lambda does not need ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "JobCompleteEventInvokeConfig692D89BE": {
      "Type": "AWS::Lambda::EventInvokeConfig",
      "Properties": {
        "FunctionName": {
          "Ref": "JobComplete703682D0"
        },
        "MaximumRetryAttempts": 0,
        "Qualifier": "$LATEST"
      },
      "DependsOn": [
        "JobCompletePolicyBBFD3892",
        "JobCompleteRoleDefaultPolicyD4DC2F12",
        "JobCompleteRole81FD9028"
      ],
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobComplete/EventInvokeConfig/Resource"
      }
    },
    "JobCompleteAwsEventsLambdaInvokePermission1ED79B615": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::GetAtt": [
            "JobComplete703682D0",
            "Arn"
          ]
        },
        "Principal": "events.amazonaws.com",
        "SourceArn": {
          "Fn::GetAtt": [
            "EventTriggerEventsRule76A88FDF",
            "Arn"
          ]
        }
      },
      "DependsOn": [
        "JobCompletePolicyBBFD3892",
        "JobCompleteRoleDefaultPolicyD4DC2F12",
        "JobCompleteRole81FD9028"
      ],
      "Metadata": {
        "aws:cdk:path": "VodFoundation/JobComplete/AwsEventsLambdaInvokePermission-1"
      }
    },
    "S3Config": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": {
          "Fn::GetAtt": [
            "CustomResource8CDCD7A7",
            "Arn"
          ]
        },
        "SourceBucket": {
          "Ref": "Source71E471F1"
        },
        "LambdaArn": {
          "Fn::GetAtt": [
            "jobSubmitB391E42F",
            "Arn"
          ]
        }
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete",
      "Metadata": {
        "aws:cdk:path": "VodFoundation/S3Config/Default"
      }
    },
    "EventTriggerEventsRule76A88FDF": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "EventPattern": {
          "source": [
            "aws.mediaconvert"
          ],
          "detail": {
            "userMetadata": {
              "StackName": [
                {
                  "Ref": "AWS::StackName"
                }
              ]
            },
            "status": [
              "COMPLETE",
              "ERROR",
              "CANCELED",
              "INPUT_INFORMATION"
            ]
          }
        },
        "State": "ENABLED",
        "Targets": [
          {
            "Arn": {
              "Fn::GetAtt": [
                "JobComplete703682D0",
                "Arn"
              ]
            },
            "Id": "Target0"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/EventTrigger/EventsRule/Resource"
      }
    },
    "NotificationSnsTopicB941FD22": {
      "Type": "AWS::SNS::Topic",
      "Properties": {
        "KmsMasterKeyId": {
          "Fn::Join": [
            "",
            [
              "arn:",
              {
                "Ref": "AWS::Partition"
              },
              ":kms:",
              {
                "Ref": "AWS::Region"
              },
              ":",
              {
                "Ref": "AWS::AccountId"
              },
              ":alias/aws/sns"
            ]
          ]
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Notification/SnsTopic/Resource"
      }
    },
    "NotificationSnsTopicPolicy4027082A": {
      "Type": "AWS::SNS::TopicPolicy",
      "Properties": {
        "PolicyDocument": {
          "Statement": [
            {
              "Action": [
                "SNS:Publish",
                "SNS:RemovePermission",
                "SNS:SetTopicAttributes",
                "SNS:DeleteTopic",
                "SNS:ListSubscriptionsByTopic",
                "SNS:GetTopicAttributes",
                "SNS:Receive",
                "SNS:AddPermission",
                "SNS:Subscribe"
              ],
              "Condition": {
                "StringEquals": {
                  "AWS:SourceOwner": {
                    "Ref": "AWS::AccountId"
                  }
                }
              },
              "Effect": "Allow",
              "Principal": {
                "AWS": {
                  "Fn::Join": [
                    "",
                    [
                      "arn:",
                      {
                        "Ref": "AWS::Partition"
                      },
                      ":iam::",
                      {
                        "Ref": "AWS::AccountId"
                      },
                      ":root"
                    ]
                  ]
                }
              },
              "Resource": {
                "Ref": "NotificationSnsTopicB941FD22"
              },
              "Sid": "TopicOwnerOnlyAccess"
            },
            {
              "Action": [
                "SNS:Publish",
                "SNS:RemovePermission",
                "SNS:SetTopicAttributes",
                "SNS:DeleteTopic",
                "SNS:ListSubscriptionsByTopic",
                "SNS:GetTopicAttributes",
                "SNS:Receive",
                "SNS:AddPermission",
                "SNS:Subscribe"
              ],
              "Condition": {
                "Bool": {
                  "aws:SecureTransport": "false"
                }
              },
              "Effect": "Deny",
              "Principal": {
                "AWS": ""
              },
              "Resource": {
                "Ref": "NotificationSnsTopicB941FD22"
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        },
        "Topics": [
          {
            "Ref": "NotificationSnsTopicB941FD22"
          }
        ]
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Notification/SnsTopic/Policy/Resource"
      }
    },
    "NotificationSnsTopicTokenSubscription1209F3ABA": {
      "Type": "AWS::SNS::Subscription",
      "Properties": {
        "Endpoint": {
          "Ref": "emailAddress"
        },
        "Protocol": "email",
        "TopicArn": {
          "Ref": "NotificationSnsTopicB941FD22"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/Notification/SnsTopic/TokenSubscription:1/Resource"
      }
    },
    "AppRegistryAttributeGroup7AF07446": {
      "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
      "Properties": {
        "Attributes": {
          "ApplicationType": "AWS-Solutions",
          "SolutionVersion": "v1.3.4",
          "SolutionID": "SO0146",
          "SolutionName": "Video on Demand on AWS Foundation"
        },
        "Description": "Attribute group for solution information.",
        "Name": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::Region"
              },
              "-",
              {
                "Ref": "AWS::StackName"
              }
            ]
          ]
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/AppRegistryAttributeGroup/Resource"
      }
    },
    "AppRegistryAttributeGroupApplicationAttributeGroupAssociatione92bb36ecd06C2AD27E6": {
      "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation",
      "Properties": {
        "Application": {
          "Fn::GetAtt": [
            "AppRegistryApp5349BE86",
            "Id"
          ]
        },
        "AttributeGroup": {
          "Fn::GetAtt": [
            "AppRegistryAttributeGroup7AF07446",
            "Id"
          ]
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/AppRegistryAttributeGroup/ApplicationAttributeGroupAssociatione92bb36ecd06"
      }
    },
    "AppRegistryApp5349BE86": {
      "Type": "AWS::ServiceCatalogAppRegistry::Application",
      "Properties": {
        "Description": "Service Catalog application to track and manage all your resources. The SolutionId is SO0146 and SolutionVersion is v1.3.4.",
        "Name": {
          "Fn::Join": [
            "",
            [
              "vod-foundation-",
              {
                "Ref": "AWS::Region"
              },
              "-",
              {
                "Ref": "AWS::AccountId"
              },
              "-",
              {
                "Ref": "AWS::StackName"
              }
            ]
          ]
        },
        "Tags": {
          "Solutions:ApplicationType": "AWS-Solutions",
          "Solutions:SolutionID": "SO0146",
          "Solutions:SolutionName": "Video on Demand on AWS Foundation",
          "Solutions:SolutionVersion": "v1.3.4"
        }
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/AppRegistryApp/Resource"
      }
    },
    "AppRegistryAssociation": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Properties": {
        "Application": {
          "Fn::GetAtt": [
            "AppRegistryApp5349BE86",
            "Id"
          ]
        },
        "Resource": {
          "Ref": "AWS::StackId"
        },
        "ResourceType": "CFN_STACK"
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/AppRegistryAssociation"
      }
    },
    "CDKMetadata": {
      "Type": "AWS::CDK::Metadata",
      "Properties": {
        "Analytics": "v2:deflate64:H4sIAAAAAAAA/3VSTW/bMAz9LbnLatL0sN6Weu1QoEODOPdClmmPjS0JopSiEPTfB8lObGzrRSQfv6l3y8P9lof1SnxQIZtT0WPNQ+WEPLGyVb+EMai6pO6FFQM4sEx80FugLQ8PXp7AJeekjWKve5SfMzzZo/EgCCKTvfZNa7VyPPxAchZr71Ar9mqxQ7WTEoieG1AOXa5UpoSnlPBVxLJMZCgGHg66h+TKcp5q1CLrxVA3gocnr2RuXrbqqj+eQblnddYnKLVqMd/gv+Ae7IBEuS1t3wQROOK7JBikBOLh4KdJfA+RkSIejtqgTNio5HeecWlWviZp0VxmXNqREdgzSpDCiV53whgLXTrFJw9lq3ZuPAr8tNob9g+yI9ISxaX0zpge5dU8AGlvJSyiYmQXlOUdKye6TBFPTg9X3yI76a/eGZ+pUmrV4Dj6uhC9+S34evV9ot9Nkl9uNIWHv5ZaDB0ju7u91CPdZzZQIbUiZ710lBuEmX4FbfnMraOutuOf1RabDoqJIo8zdNQvGZvYU6S/HJGjrhTFyJRugL/TzXnzjW/u+Wb1ToiF9crhAPwwyj8bMrXOeAMAAA=="
      },
      "Metadata": {
        "aws:cdk:path": "VodFoundation/CDKMetadata/Default"
      },
      "Condition": "CDKMetadataAvailable"
    }
  },
  "Outputs": {
    "SourceBucket": {
      "Description": "Source S3 Bucket used to host source video and MediaConvert job settings files",
      "Value": {
        "Ref": "Source71E471F1"
      },
      "Export": {
        "Name": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::StackName"
              },
              "-SourceBucket"
            ]
          ]
        }
      }
    },
    "DestinationBucket": {
      "Description": "Source S3 Bucket used to host all MediaConvert ouputs",
      "Value": {
        "Ref": "Destination920A3C57"
      },
      "Export": {
        "Name": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::StackName"
              },
              "-DestinationBucket"
            ]
          ]
        }
      }
    },
    "CloudFrontDomain": {
      "Description": "CloudFront Domain Name",
      "Value": {
        "Fn::GetAtt": [
          "CloudFrontCloudFrontDistribution824F3346",
          "DomainName"
        ]
      },
      "Export": {
        "Name": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::StackName"
              },
              "-CloudFrontDomain"
            ]
          ]
        }
      }
    },
    "SnsTopic": {
      "Description": "SNS Topic used to capture the VOD workflow outputs including errors",
      "Value": {
        "Fn::GetAtt": [
          "NotificationSnsTopicB941FD22",
          "TopicName"
        ]
      },
      "Export": {
        "Name": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::StackName"
              },
              "-SnsTopic"
            ]
          ]
        }
      }
    }
  },
  "Conditions": {
    "CDKMetadataAvailable": {
      "Fn::Or": [
        {
          "Fn::Or": [
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "af-south-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-east-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-northeast-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-northeast-2"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-south-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-southeast-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ap-southeast-2"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "ca-central-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "cn-north-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "cn-northwest-1"
              ]
            }
          ]
        },
        {
          "Fn::Or": [
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-central-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-north-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-south-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-west-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-west-2"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "eu-west-3"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "me-south-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "sa-east-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "us-east-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "us-east-2"
              ]
            }
          ]
        },
        {
          "Fn::Or": [
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "us-west-1"
              ]
            },
            {
              "Fn::Equals": [
                {
                  "Ref": "AWS::Region"
                },
                "us-west-2"
              ]
            }
          ]
        }
      ]
    }
  }
}

역할 생성 및 정책 연결 항목

역할을 생성하고 권한에 대해 정책을 할당해야 함. 아래는 필수 정책 연결 항목.

AmazonEventBridge

AmazonS3

AmazonSNS

AWSBatchServiceEventTargetRole

AWSElementalMediaConvert

AWSLambda

AWSServiceCatalogAppRegistry

CloudFront

IAM

CloudFront 설정

CloudFront 비용 절감

AWS Partner 사와 CloudFront 협약으로 70% 비용할인

profile
사용자의 경험을 설계하고 시스템의 생명주기를 책임지는 개발자

0개의 댓글