AWS Lambda와 MediaConverter를 사용해 Vod 스트리밍 서비스 개발하기
AWS Lambda와 MediaConverter를 사용해 HLS Vod Steaming을 서비스를 개발해보겠습니다.
목차는 다음과 같습니다.
- 전체적인 구조
- Adaptive Bitrate Streaming에 대해서
- 1. IAM 역할 만들기
- 2. S3 설정하기
- 3. Lambda 만들기
- 영상 업로드 및 변환 테스트
- 크롬에서 m3u8 파일 실행하기
전체적인 구조
- 클라이언트가 S3에 비디오 파일을 업로드합니다.
- 비디오가 입력 버킷에 업로드되는 즉시 Lambda 함수를 트리거합니다.
- 람다 함수는 인풋 파일, 설정, HLS 아웃풋 그룹 등의 설정을 토대로 Job을 생성하고 MediaConverter를 실행합니다.
- MediaConverter는 전달받은 Job을 토대로 HLS 파일로 트랜스 코딩을 진행합니다.
- 변환된 파일들은 S3의 지정된 버킷 안의 폴더에 저장됩니다.
Adaptive Bitrate Streaming에 대해서
- Adaptive Bitrate Streaming은 클라이언트의 네트워크 상황에 따라 다른 해상도와 비트레이트 영상을 스트리밍이 되도록 하는 기술입니다.
- 대표적으로 Apple이 개발한 HLS(HTTP Live Streaming) 프로토콜이 있습니다.
- HLS manifest 파일 구조
- 클라이언트는 .m3u8 확장자를 가진 manifest 파일을 받습니다.
- manifest 파일은 각 비트레이트에 맞는 청크들의 리스트가 적혀 있습니다.
- 플레이어는 가장 낮은 비트레이트를 가진 청크를 재생합니다.
- 이후 다운로드 스피드를 보고 조금 더 큰 사이즈의 파일을 받아도 되면 SD, HD 영상들을 플레이하게 됩니다.
- 만약 플레이 중에 네트워크 상항이 안 좋아지게 되면 영상의 해상도를 더 낮게 재생합니다.
개발 프로세스는 다음과 같습니다.
- IAM 역할 만들기
- S3 설정하기
- Lambda 만들기
- MediaConverter 설정
1. IAM 역할 만들기
역할은 다음 두 개를 만들어야 합니다.
- Role_MediaConvert
- Role_LambdaVod(labmda를 실행할 권한)
먼저 MediaConvert를 사용하기 위한 역할을 만들겠습니다.
IAM > 역할 > 역할 만들기를 클릭합니다.
다른 AWS 서비스의 사용 사례에서 MediaConvert를 클릭합니다.
권한은 다음과 같이 S3FullAccess와 APIGatewayFullAccess 두 개가 추가된 것을 확인할 수 있습니다.
이름은 Role_MediaConvert로 설정했고 역할을 생성합니다.
다음으로 Lambda 함수를 위한 역할을 생성합니다.
사용 사례에서 Lambda를 클릭하고 AWSLambdaBasicExecutionRole을 권한 정책으로 추가합니다.
이름은 Role_LambdaVod로 설정했고 역할을 생성합니다.
다음으로 Role_LambdaVod 역할에 Role_MediaConvert 정책을 추가하겠습니다.
먼저 Role_MediaConvert에 있는 ARN을 복사합니다.
Role_LambdaVod 상세보기 화면으로 가서 '인라인 정책 생성'을 클릭합니다.
JSON을 클릭한 다음 추가합니다.
Resource 부분에 이전에 Role_MediaConvert에서 복사한 ARN을 삽입합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*",
"Effect": "Allow",
"Sid": "Logging"
},
{
"Action": ["iam:PassRole"],
"Resource": ["이전에 생성한 Role_MediaConvert의 ARN"],
"Effect": "Allow",
"Sid": "PassRole"
},
{
"Action": ["mediaconvert:*"],
"Resource": ["*"],
"Effect": "Allow",
"Sid": "MediaConvertService"
},
{
"Action": ["s3:*"],
"Resource": ["*"],
"Effect": "Allow",
"Sid": "S3Service"
}
]
}
다음과 같이 4개의 권한이 보입니다.
이름을 입력하고 정책을 추가합니다.
2. S3 설정하기
S3 버킷을 생성합니다.
버킷의 안에 다음과 같이 input과 output 폴더를 생성합니다.
input/ : 원본 동영상 저장 경로
output/ : 결과 동영상 저장 경로
먼저 퍼블릭 엑세스 차단에 가서 4번째인 '임의의 퍼블릭 버킷 또는 액세스 지점 정책을 통해 부여된 버킷 및 객체에 대한 퍼블릭 및 교차 계정 액세스 차단'을 제외하고 체크를 해제합니다.
버킷을 생성한 후에는 원본을 저장할 버킷에 들어가 권한 탭을 클릭해 버킷 정책을 다음으로 삽입합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::[버킷이름]/*"
}
]
}
3. Lambda 만들기
함수 생성을 클릭합니다. 이후 파이썬 3.8 버전을 선택한다.
이름을 등록하고 실행 역할은 위에서 만든 Role_LambdaVod를 등록한 후 함수를 생성합니다.
함수에 등록할 코드를 다음 github에 들어가 코드를 다운로드합니다.
https://github.com/aws-samples/aws-media-services-vod-automation
MediaConvert-WorkflowWatchFolderAndNotification 폴더에 들어가면 convert.py 와 job.json 파일이 있습니다.
두 파일을 zip으로 압축한 뒤 람다에 등록합니다.
둘을 합친 압축 파일은 여기에 올려둡니다.
코드 등록이 완료되면 다음과 같이 두 파일이 보이게 됩니다.
그리고 런타임 설정을 해줍니다. 런타임 핸들러에 규칙은 [파일명]. [메서드명]인데 업로드한 파일에서 convert.py 가 그 역할을 할 것이고 그 안에 handler를 호출할 것이기 때문에 다음처럼 설정합니다.
convert.handler
그럼 트리거를 등록하기 전에 테스트를 진행하는 게 좋은데 그러기 위해선 2가지를 해야 합니다.
1. 환경변수 설정
2. 테스트 등록
환경변수 설정은
구성 -> 환경변수 > 편집에 들어가 다음처럼 설정합니다.
DestinationBucket, MediaConvertRole, Application을 입력한다.
Application = VOD
MediaConvertRole = [위에서 등록한 Role_MediaConvert의 ARN]
DestinationBucket = [output버킷이름]/[저장폴더]
참고로 DestinationBucket를 입력할 때 output/ 경로에 저장할 것이기 때문에 [버킷 이름]/output/으로 등록했습니다.
그리고 경로가 겹치면(대체로 파일명이겠지만) 이전 파일을 덮어쓰게 됩니다.
테스트 탭으로 들어가 다음을 입력하여 진행합니다.
테스트의 내용을 아래 내용으로 채웁니다.
{
"Records": [
{
"eventVersion": "2.0",
"eventTime": "2017-08-08T00:19:56.995Z",
"requestParameters": { "sourceIPAddress": "54.240.197.233" },
"s3": {
"configurationId": "90bf2f16-1bdf-4de8-bc24-b4bb5cffd5b2",
"object": {
"eTag": "2fb17542d1a80a7cf3f7643da90cc6f4-18",
"key": "vodconsole/TRAILER.mp4",
"sequencer": "005989030743D59111",
"size": 143005084
},
"bucket": {
"ownerIdentity": { "principalId": "" },
"name": "rodeolabz-us-west-2",
"arn": "arn:aws:s3:::rodeolabz-us-west-2"
},
"s3SchemaVersion": "1.0"
},
"responseElements": {
"x-amz-id-2": "K5eJLBzGn/9NDdPu6u3c9NcwGKNklZyY5ArO9QmGa/t6VH2HfUHHhPuwz2zH1Lz4",
"x-amz-request-id": "E68D073BC46031E2"
},
"awsRegion": "us-west-2",
"eventName": "ObjectCreated:CompleteMultipartUpload",
"userIdentity": { "principalId": "" },
"eventSource": "aws:s3"
}
]
}
테스트 버튼을 클릭합니다.
실행 결과가 성공으로 뜨면 세부 정보를 확인합니다.
세부 정보에서 statusCode가 200으로 온 것을 확인하면 됩니다.
다음으로 MediaConverter에 해당 작업이 성공적으로 수행됐는지 확인합니다.
상태다 'COMPLETE'이면 성공한 겁니다.
만약 상태가 다음과 같이 'ERROR'로 나온다면 작업 상세 화면에 들어가서 오류 메시지를 확인해줍니다.
저의 경우에는 버킷이 ACLs을 허용하지 않아서 생기는 오류였습니다.
다음과 같이 ACL을 활성화하게 버킷의 '객체 소유권'을 수정해줍니다.
이제 Lambda 트리거에 S3를 등록하겠습니다.
버킷명을 입력하고 이벤트 유형은 모든 객체 생성 이벤트로, 그리고 접두사에 input/ 을 입력합니다.
이제 input/ 에 파일을 업로드해보겠습니다.
영상 업로드 및 변환 테스트
위 Lambda 함수의 job.json 코드에서 설정을 통해 다음 4가지 화질을 만듭니다.
HLS: 360, 540, 720
mp4: 720
그 외 thumbnail(썸네일) 이미지 다수
output/을 보면 HLS로 화질 별로 트랜스 코딩된 영상을 확인할 수 있습니다.
크롬에서 m3u8 파일 실행하기
크롬에서 위처럼 변환된 영상을 실행해주는 HLS 플레이어 플러그인이 있습니다.
플러그인을 설치하고 m3u8 파일을 실행하면 어떤 순서로 영상을 불러오는지 확인할 수 있습니다.
1. 처음에는 메니페이스 파일인 {영상이름}.m3u8 파일을 가져옵니다.
파일에는 해상도별 .m3u8 파일과 대역폭이 명시되어 있습니다.
2. 처음에는 가장 낮은 화질인 {영상이름}_360.m3u8 파일을 가져오고
3. {영상이름}_360.m3u8에 청크 단위로 나누어져 있는 ts 리스트 중에서 첫 파일을 가져옵니다.
4. 네트워크 상황이 좋다 보니 다음 ts 파일은 540을 건너뛰고 720.m3u8에 있는 ts 파일을 불러옵니다.