본문 바로가기
Insight/회고

[Liven 1.0] 아티스트 허브 - AWS MediaConvert 사용

by 싯벨트 2025. 3. 6.
728x90

배경

아티스트 허브는 아티스트의 소개페이지입니다. 아티스트의 sns를 모아두고 관련 정보를 제공하는 페이지이며, 킥이 되는 포인트는 배경 이미지를 이미지뿐만 아니라 영상으로도 구성할 수 있다는 점입니다. 이때 원본 영상에서 원하는 시간대를 입력하여 영상을 자르고, .m3u8 파일 형식의 스트리밍 가능하게 저장했습니다. 스트리밍으로 구현하면 전체 파일을 다운받지 않고 재생이 가능하므로 리소스 측면에서 보다 효율적으로 기능을 구현할 수 있습니다.

그래서 이번 글에서는 이를 구현하기 위해 사용했던 AWS MediaConvert의 사용법S3 태깅을 통한 수명관리에 대해 정리해보겠습니다.

AWS MediaConvert 사용

준비

@aws-sdk/client-mediaconvert를 사용해서 작업을 만드는 CreateJobCommandInput 속성에 대한 상세는 공식문서나 GPT를 참고하면 잘 나올 것이기에 넘어가도록 하고, 동작을 위한 필수 요소들에 대해 설명해보겠습니다.

시퀀스 다이어그램

영상 처리 시퀀스 다이어그램

영상을 처리하는 로직은 범용적으로 사용될 수 있으므로, converter 컨텍스트를 따로 구성하여 람다 클라이언트로 통신하도록 구성했습니다. MediaConvert에 작업을 요청하면 EventBridge에 설정한 규칙에 의해 완료 후 SNS에 작업 결과를 게시합니다. 이후, Background 모델을 가지고 있는 Artist 컨텍스트에서 해당 메시지를 구독하여 videoUri를 저장하고 상태를 바꿔줍니다.

역할 생성

@aws-sdk/client-mediaconvert 에서 CreateJobCommandInput를 사용할 경우, Role을 필수값으로 설정해줘야 합니다. MediaConvert_Default_Role와 같은 역할명을 정하고, AmazonS3FullAccess, AmazonSNSFullAccess를 추가줍니다. 만약, SQS로 구현을 한다면 AmazonSQSFullAccess를 추가해주고, S3의 권한이 너무 많이 부여되는 게 불편하다면 따로 정책을 생성한 뒤 그것을 연결해줘도 좋습니다. 이렇게 생성한 역할의 ARN을 CreateJobCommandInput Role 속성에 넣어줍니다.

이벤트 규칙 - SNS 푸시 및 구독 생성

이벤트 버스의 규칙에서 이벤트 패턴을 지정해줍니다. 그리고 대상으로 해당 메시지를 받을 SNS 토픽을 지정합니다. 저는 에러와 완료 상태에 대해서만 메시지를 받도록 설정했습니다.

{
  "source": ["aws.mediaconvert"],
  "detail": {
    "status": ["ERROR", "COMPLETE"]
  }
}

s3:// 로 시작하는 uri 구성

CreateJobCommandInput에서 S3의 리소스, 버킷을 사용한다면 “s3://”로 시작하는 값을 입력해주어야 합니다. 인풋에서 FileInput에 리소스를 넣거나 아웃풋에서 Destination으로 버킷명을 넣을 때 주의하세요.

썸네일 추출

아웃풋 그룹에 아래처럼 설정하면 썸네일을 추출할 수 있습니다. 퀄리티나 사진 개수 등의 디테일한 부분은 필요한대로 조정하시면 됩니다.

 {
      CustomName: "Extracting_Thumbnail_From_Video",
      Name: "Thumbnail Maker",
      OutputGroupSettings: {
          Type: "FILE_GROUP_SETTINGS",
          FileGroupSettings: {
              Destination: `s3://${thumbnailBucket}/`,
          },
      },
      Outputs: [
          {
              ContainerSettings: {
                  Container: "RAW",
              },
              VideoDescription: {
                  Sharpness: 50,
                  CodecSettings: {
                      Codec: "FRAME_CAPTURE",
                      FrameCaptureSettings: {
                          MaxCaptures: 1,
                          Quality: 80,
                      },
                  },
              },
          },
      ],
  }

필요 정보 전달

비디오 컨버팅은 다른 곳에서도 사용할 수 있는 유틸성 기능이기 때문에 해당 도메인에서 컨버팅 완료 후 상태값을 업데이트하는 로직을 실행할 때, 어떤 도메인의 어떤 데이터인지를 전달받는 것이 필요했습니다. 이때는 UserMetadata 속성을 사용하여 필요한 정보를 전달하면, MediaConvert 가 작업(Job)을 완료된 후 전달할 때 입력된 정보를 함께 전달할 수 있어서 후속 처리가 가능해집니다.

UserMetadata: { domain: content.domain, domainId: content.domainId },

SAM 정책 설정

Converter 컨텍스트에서 MediaConvert를 호출하는 람다에는 AWSElementalMediaConvertFullAccess 정책을 추가해주세요.

태깅을 통한 수명주기 관리

s3 버킷의 관리를 보면 수명 주기 규칙을 설정할 수 있습니다. 해당 규칙은 태그를 가지고 있는 리소스에만 적용할 수 있는데, 이렇게 하면 DB에서 삭제되어 사용되지 않는 데이터에 매칭되는 s3 리소스도 삭제하여 효율적인 관리를 할 수 있습니다.

수명 주기 규칙과 그 규칙의 대상이 되는 태그를 {deletable: true} 로 설정했다면, 아래처럼 삭제될 리소스에 태그를 추가하는 코드를 구성할 수 있습니다.

export class S3Utils {
    private s3Client;
    constructor() {
        this.s3Client = new S3Client({ region: process.env.REGION });
    }

    async putDeleteTagging(uri: string): Promise<void> {
        const { bucket, key } = parseUri(uri);

        const input: PutObjectTaggingCommandInput = {
            Bucket: bucket,
            Key: key,
            Tagging: { TagSet: [{ Key: "deletable", Value: "true" }] },
        };

        await this.s3Client.send(new PutObjectTaggingCommand(input));
    }
}