• 티스토리 홈
  • 프로필사진
    알쓸개잡
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
알쓸개잡
  • 프로필사진
    알쓸개잡
    • 분류 전체보기 (93)
      • 스프링부트 (52)
      • AWS (5)
      • 쿠버네티스 (7)
      • 자바 (19)
      • 인프라 (1)
      • ETC (8)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      • 반응형
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • AWS MediaConvert SDK 사용 방법 (2) - Job 생성 코드
        2023년 08월 18일
        • 알쓸개잡
        • 작성자
        • 2023.08.18.:49
        반응형

        이전 포스팅에서는 MediaConvert 를 사용하기 위한 role 을 생성하는 방법에 대해서 알아 보았습니다. 이번 포스팅에서는 Spring Boot 프로젝트에 MediaConvert SDK 를 사용하여 Job 을 생성하는 샘플코드를 작성해 보겠습니다.

         

        AWS MediaConvert 디펜던시

        AWS MediaConvert SDK 를 사용하기 위해서는 software.amazon.awssdk:mediaconvert 디펜던시가 필요합니다.

        샘플코드를 작성하기 이전에 트랜스코딩 대상 미디어 파일은 S3 에 업로드 되어 있다고 가정하겠습니다.

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>software.amazon.awssdk</groupId>
                    <artifactId>bom</artifactId>
                    <version>2.20.87</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>io.awspring.cloud</groupId>
                    <artifactId>spring-cloud-aws-dependencies</artifactId>
                    <version>3.0.1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        
        <dependencies>
        	...
        	<dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>mediaconvert</artifactId>
            </dependency>
            <dependency>
                <groupId>io.awspring.cloud</groupId>
                <artifactId>spring-cloud-aws-starter-sns</artifactId>
            </dependency>
        	<dependency>
                <groupId>io.awspring.cloud</groupId>
                <artifactId>spring-cloud-aws-autoconfigure</artifactId>
            </dependency>
            ...
        </dependencies>

         

        software.amazon.awssdk (AWS java SDK) 와 io.awspring.cloud 에 정의된 패키지들을 사용할 것입니다. 

        io.awspring.cloud (spring cloud AWS) 는 AWS 관련 서비스를 사용하기 위한 인프라 관련 코드를 최대한 피할 수 있도록 Spring 에서 제공하는 Spring 기반 통합 모듈입니다. 즉, AWS 서비스를 사용하기 위한 코드를 보다 간단한 설정으로 사용할 수 있게 해줍니다.

        io.awspring.cloud 관련 내용은 아래 링크를 참고하시면 도움이 됩니다.

        https://docs.awspring.io/spring-cloud-aws/docs/2.4.1/reference/html/index.html#using-amazon-web-services

         

        참고로 mediaconvert artifact 가 어떤 버전을 사용하는지 확인하려면

        software.amazon.awssdk:bom 파일과 software.amazon.aswsdk:aws-sdk-java-pom 파일을 살펴보면 됩니다.

        software.amazon.awssdk:bom 파일을 보면 아래와 같이 정의 되어 있습니다.

        <parent>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>aws-sdk-java-pom</artifactId>
            <version>2.20.87</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        
        ....
        
        <dependencyManagement>
        	<dependencies>
            	...
                ...
                <dependency>
                    <groupId>software.amazon.awssdk</groupId>
                    <artifactId>mediaconvert</artifactId>
                    <version>${awsjavasdk.version}</version>
                </dependency>
                ...
                ...
        	</dependencies>
        </dependencyManagement>

        software.amazon.awssdk:aws-sdk-java-pom 파일에 보면 awsjavasdk.version 을 확인할 수 있습니다.

        <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
                 xmlns="http://maven.apache.org/POM/4.0.0"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <modelVersion>4.0.0</modelVersion>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>aws-sdk-java-pom</artifactId>
            <version>2.20.87</version>
            <packaging>pom</packaging>
            <name>AWS Java SDK :: Parent</name>
            ...
            ...
            <properties>
                ...
                <awsjavasdk.version>${project.version}</awsjavasdk.version>
                ...
            </properties>
            ...
            ...
        </project>

        예시에서 사용된 software.amazon.awssdk 의 project.version 은 2.20.87 임을 알 수 있습니다.

         

        application.yml 설정

        ...
        spring:
          cloud:
            aws:
              credentials:
                access-key: ${AWS_ACCESS_KEY}
                secret-key: ${AWS_SECRET_KEY}
              region:
                static: ${AWS_REGION}
                
        media-convert:
          role-arn: <MediaConvert role arn 정보를 입력합니다>
        ...

        spring.cloud.aws.credentials 는 spring cloud AWS 모듈에서 참조하는 정보로써 AWS 계정 인증 정보를 입력합니다.

        예시에서는 AWS_ACCESS_KEY, AWS_SECRET_KEY, AWS_REGION 을 시스템 환경변수로 등록하여 설정한 것입니다. 환경 변수로 등록하지 않고 직접 값을 입력해도 됩니다.

        media-convert.role-arn 에는 앞선 AWS MediaConvert SDK 사용 방법 (1) - role 생성하기 에서 생성한 role 의 arn 정보를 입력합니다. 

         

         

        MediaConvertClient Bean 생성

        package global.voda.operator.config;
        
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
        import software.amazon.awssdk.regions.providers.AwsRegionProvider;
        import software.amazon.awssdk.services.mediaconvert.MediaConvertClient;
        import software.amazon.awssdk.services.mediaconvert.model.DescribeEndpointsRequest;
        import software.amazon.awssdk.services.mediaconvert.model.DescribeEndpointsResponse;
        
        import java.net.URI;
        
        @Slf4j
        @Configuration
        public class AwsMediaConvertConfig {
            @Bean
            public MediaConvertClient mediaConvertClient(AwsCredentialsProvider credentialsProvider, 
                                                         AwsRegionProvider regionProvider) {
                DescribeEndpointsResponse describeEndpointsResponse = MediaConvertClient.builder()
                    .credentialsProvider(credentialsProvider)
                    .region(regionProvider.getRegion())
                    .build()
                    .describeEndpoints(
                    	//한번에 반환할 MediaConvert 서비스 endpoint 최대 개수 지정
                    	DescribeEndpointsRequest.builder().maxResults(20).build()
                    );
        
                if (describeEndpointsResponse.endpoints().size() == 0) {
                    log.error("cannot find MediaConvert service endpoint URL");
                    throw new RuntimeException("cannot find MediaConvert service endpoint URL");
                }
        
                String endPointUrl = describeEndpointsResponse.endpoints().get(0).url();
                if (log.isDebugEnabled()) {
                    log.debug("MediaConvert endpoint URL: {}", endPointUrl);
                }
        
                //가져온 MediaConvert 서비스 endpoint URL 을 MediaConvertClient 에 셋팅하여 
                //MediaConvertClient Bean 을 생성
                return MediaConvertClient.builder()
                    .region(regionProvider.getRegion())
                    .endpointOverride(URI.create(endPointUrl))
                    .build();
            }
        }

        AwsCredentialsProvider, AwsRegionProvider 는 spring.cloud.aws.credentials 설정을 기반으로 자동 주입됩니다.

         

         

        MediaConvert Job 생성 코드

        package com.example.mediaconvert.service;
        
        import lombok.RequiredArgsConstructor;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.beans.factory.annotation.Value;
        import org.springframework.stereotype.Service;
        import software.amazon.awssdk.services.mediaconvert.MediaConvertClient;
        import software.amazon.awssdk.services.mediaconvert.model.*;
        
        @Service
        @Slf4j
        @RequiredArgsConstructor
        public class MediaConvertServiceEx {
            @Value("${media-convert.role-arn:}")
            private String roleArn;
        
            private final MediaConvertClient mediaConvertClient;
        
            /**
             * 동영상을 트랜스 코딩하기 위해서 media convert job 을 생성하는 메소드
             *
             * @param s3InputPath 트랜스코딩 대상 영상 파일 S3 object 경로
             * @param s3OutputPath 트랜스코딩 결과 파일 저장하기 위한 S3 object 경로
             * @throws MediaConvertException MediaConvert 예외
             */
            public void videoConvert(String s3InputPath,
                                     String s3OutputPath) throws MediaConvertException {
                Output.Builder outputBuilder = commonOutputBuilder();
                Output output = outputBuilder.videoDescription(
                    VideoDescription.builder()
                        .codecSettings(VideoCodecSettings.builder()
                            //mp4 형식 출력
                            .codec(VideoCodec.H_264)
                            .h264Settings(H264Settings.builder()
                                .maxBitrate(1000000)
                                .rateControlMode(H264RateControlMode.QVBR)
                                .sceneChangeDetect(H264SceneChangeDetect.TRANSITION_DETECTION)
                                .build())
                            .build())
                        .build()
                ).build();
        
                OutputGroup.Builder outputGroupBuilder =
                    commonOutputGroupBuilder(s3OutputPath);
                OutputGroup outputGroup = outputGroupBuilder
                    .outputs(output)
                    .build();
        
                Input input = Input.builder()
                    .timecodeSource(InputTimecodeSource.ZEROBASED)
                    .fileInput(s3InputPath)
                    .build();
        
                executeMediaConvert(outputGroup, input);
            }
        
            /**
             * 이미지를 정지 영상으로 생성하기 위해서 media convert job 을 생성하는 메소드
             *
             * @param s3InputPath    이미지 파일 S3 object 경로
             * @param s3OutputPath   트랜스코딩 결과 파일 저장하기 위한 S3 object 경로
             * @param width          이미지 파일 가로 해상도
             * @param height         이미지 파일 세로 해상도
             * @param timeDurationMs 트랜스 코딩된 영상 재생시간 (MS)
             * @throws MediaConvertException MediaConvert 예외
             */
            public void imageConvert(String s3InputPath,
                                     String s3OutputPath,
                                     int width,
                                     int height,
                                     int timeDurationMs) throws MediaConvertException {
                int outputWidth = (int) (Math.ceil((double) width / 2) * 2);
                int outputHeight = (int) (Math.ceil((double) height / 2) * 2);
                int framerateNumerator = 30;
                int framerateDenominator = 1;
        
                Output.Builder outputBuilder = commonOutputBuilder();
                Output output = outputBuilder.videoDescription(
                    VideoDescription.builder()
                        .width(outputWidth)
                        .height(outputHeight)
                        .videoPreprocessors(VideoPreprocessor.builder()
                            .imageInserter(ImageInserter.builder()
                                .insertableImages(InsertableImage.builder()
                                    .imageX(0)
                                    .imageY(0)
                                    .layer(1)
                                    .imageInserterInput(s3InputPath)
                                    .opacity(100)
                                    .build())
                                .build())
                            .build())
                        .codecSettings(VideoCodecSettings.builder()
                            .codec(VideoCodec.H_264)
                            .h264Settings(H264Settings.builder()
                                .maxBitrate(1000000)
                                .framerateDenominator(framerateDenominator)
                                .framerateControl(H264FramerateControl.SPECIFIED)
                                .framerateNumerator(framerateNumerator)
                                .rateControlMode(H264RateControlMode.QVBR)
                                .sceneChangeDetect(H264SceneChangeDetect.TRANSITION_DETECTION)
                                .build())
                            .build())
                        .build()
                ).build();
        
                OutputGroup.Builder outputGroupBuilder =
                    commonOutputGroupBuilder(s3OutputPath);
                OutputGroup outputGroup = outputGroupBuilder
                    .outputs(output)
                    .build();
        
                double oneFrameTime = (double) framerateDenominator / framerateNumerator;
                int oneFrameTimeMs = (int)(oneFrameTime * 1000);
        
                //마지막에 1 frame 시간이 재생시간에 추가되기 때문에 재생시간에서 1 frame 만큼의 시간을 빼준다.
                Input input = Input.builder()
                    .videoGenerator(InputVideoGenerator.builder()
                        .duration(timeDurationMs - oneFrameTimeMs)
                        .build())
                    .build();
        
                executeMediaConvert(outputGroup, input);
            }
        
            private void executeMediaConvert(OutputGroup outputGroup, Input input) {
                try {
                    JobSettings jobSettings = JobSettings.builder()
                        .timecodeConfig(TimecodeConfig.builder()
                            .source(TimecodeSource.ZEROBASED)
                            .build())
                        .inputs(input)
                        .outputGroups(outputGroup)
                        .build();
        
                    CreateJobRequest createJobRequest = CreateJobRequest.builder()
                        .role(roleArn)
                        .settings(jobSettings)
                        .build();
                    CreateJobResponse jobResponse = mediaConvertClient.createJob(createJobRequest);
                    log.info("success to create image media convert job, id={}", jobResponse.job().id());
                } catch (MediaConvertException e) {
                    log.error("failure create image media convert job, {}", e.getMessage());
                    throw e;
                }
            }
        
            private OutputGroup.Builder commonOutputGroupBuilder(String s3OutputPath) {
                return OutputGroup.builder()
                    .name("File Group")
                    .outputGroupSettings(OutputGroupSettings.builder()
                        .type(OutputGroupType.FILE_GROUP_SETTINGS)
                        .fileGroupSettings(FileGroupSettings.builder()
                            .destination(s3OutputPath)
                            .build())
                        .build());
            }
        
            private Output.Builder commonOutputBuilder() {
                return Output.builder()
                    .containerSettings(ContainerSettings.builder()
                        .container(ContainerType.MP4)
                        .build());
            }
        }

        샘플 코드에는 동영상 파일을 트랜스코딩 하는 메소드와 이미지 파일을 정지된 동영상 파일로 트랜스코딩 하는 메소드가 있습니다.

        이미지 파일 하나를 정지된 동영상 파일로 만드는 경우에는 MediaConvert Job Input 에 재생하고자 하는 시간 길이의 black video 를 생성하고 Output 에는 Encoding settings 에서 Image inserter 에 input 이미지를 지정해서 만듭니다.

         

         

        MediaConvert Job 생성 샘플 코드

        package com.example.mediaconvert;
        
        import com.example.mediaconvert.service.MediaConvertServiceEx;
        import lombok.RequiredArgsConstructor;
        import org.springframework.boot.CommandLineRunner;
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        
        @SpringBootApplication
        @RequiredArgsConstructor
        public class MediaconvertApplication implements CommandLineRunner {
        
        	private final MediaConvertServiceEx mediaConvertServiceEx;
        
        	public static void main(String[] args) {
        		SpringApplication.run(MediaconvertApplication.class, args);
        	}
        
        	@Override
        	public void run(String... args) throws Exception {
        		//이미지 해상도 600 * 120
        		String input = "s3://my-media-convert-source/600x120.png";
        		String output = "s3://my-media-convert-target/600x120";
                
        		//출력 영상 재생시간은 15초
        		mediaConvertServiceEx.imageConvert(input, output, 600, 120, 15000);
        	}
        }

        참고로 이미지의 경우 해상도 정보는 tika 라이브러리를 통해서 이미지 해상도 정보를 얻어 올 수 있습니다.

        위와 같이 실행해 봤을 때 생성된 MediaConvert Job id 는 아래와 같습니다.

        AWS 관리 콘솔 상에서 Job 이 정상적으로 생성이 되었는지 확인해 봅니다.

        MediaConvert Job 생성을 위한 셋팅 요소들이 많기 때문에 JOB 생성을 위한 SDK 를 사용하기 전에 AWS 관리 콘솔에서 JOB 을 직접 생성한 후에 Job 목록에서 해당 Job ID 의 상세 정보 페이지에서 [View JSON] 으로 Job 에 대한 명세를 보고 SDK 를 사용하면 많은 도움이 됩니다.

         

        지금까지 MediaConvert SDK 를 이용하여 Job 을 생성하는 샘플코드를 작성해 봤습니다.

        다음 포스팅에서는 AWS SNS 를 통해 요청된 Job 의 완료 이벤트를 REST API 기반으로 수신하는 방법에 대해서 알아 보겠습니다.

        반응형
        저작자표시 비영리 변경금지 (새창열림)

        'AWS' 카테고리의 다른 글

        bitbucket pipeline을 이용한 AWS ECS 애플리케이션 배포  (0) 2023.10.23
        AWS MediaConvert SDK 사용 방법 (3) - SNS 연결하기  (0) 2023.08.18
        AWS MediaConvert SDK 사용 방법 (1) - role 생성하기  (0) 2023.08.17
        AWS SES 사용하기  (0) 2023.07.31
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바