본문 바로가기
프로그래밍/Go

[AWS Mediaconvert] go SDK 로 mediaconvert job 실행하기

by 동네로봇 2022. 10. 15.

https://docs.aws.amazon.com/sdk-for-go/api/service/mediaconvert/

 

mediaconvert - Amazon Web Services - Go SDK

 

docs.aws.amazon.com

 

 

이전 글에서 만들었던 Encrypted HLS 템플릿을 활용하여, go SDK로 템플릿을 호출하여 mediaconvert job을 실행시켜보자.

2022.10.09 - [프로그래밍/ETC] - [AWS Mediaconvert] 암호화된 HLS 생성하기

 

[AWS Mediaconvert] 암호화된 HLS 생성하기

AWS Mediaconvert AWS Elemental MediaConvert는 파일 기반의 비디오 및 오디오 트랜스코딩 서비스이다. 이 서비스를 사용하면 브로드캐스트와 멀티스크린 전달을 위한 VOD(주문형 비디오) 콘텐츠를 직접 관

heyinsayshey.tistory.com

 

간단한 예제라 모든 기능은 main.go에 넣어버렸다.

 

package main

import (
	"errors"
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/mediaconvert"
	"log"
	"time"
)

type MCClient struct {
	cli *mediaconvert.MediaConvert
}

func main() {
	mcClient, err := createClient()
	if err != nil {
		log.Fatalln(err)
	}

	err = mcClient.encodeToEncryptHls()
	if err != nil {
		log.Fatalln(err)
	}
}

main의 역할은 mediaconvert client를 생성해주고 client를 통해 job을 실행해주는 아주 간단한 기능이다.

포인터 수신기를 선언한 메서드를 만들기위해 mediaconvert client를 담은 struct를 하나 생성하였다. 

 

createClient()를 통해 mediaconvert api를 사용할 수 있는 client를 생성한다.

func createClient() (*MCClient, error) {
	var sess *session.Session
	var err error

	if sess, err = session.NewSession(&aws.Config{
		Region:   aws.String("ap-northeast-2"),                                                 // seoul 지역 설정
		Endpoint: aws.String("https://testEndpoint.mediaconvert.ap-northeast-2.amazonaws.com"), // mediaconvert endpoint
	}); err != nil {
		return nil, err
	}

	return &MCClient{
		cli: mediaconvert.New(sess),
	}, nil
}

 

MCClient 구조체를 통해 HLS로 인코딩 하는 메서드를 작성한다.

func (m *MCClient) encodeToEncryptHls() error {
	jobTemplateName := "test-hls-encrypt" // Template 이름
	role := "mediaconvert-access-role"    // Mediaconvert 실행 권한 role 이름
	fileInputPath := "s3://test-bucket/mp3/test.mp3"
	hlsOutputFilePath := "s3://test-output-bucket/hls/"
	key := "8ac41bcbf159f77897251b6d0e4927c0" //	암호화 키
	keyUrl := "http://test-key-server/test"   //	암호화 키 저장된 라이센스 서버 url

	jobInput := &mediaconvert.CreateJobInput{
		JobTemplate: aws.String(jobTemplateName),
		Role:        aws.String(role),
		Settings: &mediaconvert.JobSettings{
			Inputs: []*mediaconvert.Input{
				{
					FileInput: aws.String(fileInputPath),
				},
			},
			OutputGroups: []*mediaconvert.OutputGroup{
				{
					OutputGroupSettings: &mediaconvert.OutputGroupSettings{
						HlsGroupSettings: &mediaconvert.HlsGroupSettings{
							Destination: aws.String(hlsOutputFilePath),
							Encryption: &mediaconvert.HlsEncryptionSettings{
								Type:             aws.String(mediaconvert.HlsKeyProviderTypeStaticKey),
								EncryptionMethod: aws.String(mediaconvert.HlsEncryptionTypeAes128),
								StaticKeyProvider: &mediaconvert.StaticKeyProvider{
									StaticKeyValue: aws.String(key),
									Url:            aws.String(keyUrl),
								},
							},
						},
					},
				},
			},
		},
	}

	// Create Mediaconvert Job
	job, err := m.cli.CreateJob(jobInput)
	if err != nil {
		return err
	}

	retryCnt := 0

_WAIT_DONE:
	// Wait for Job Done
	if err = m.WaitForJobDone(job.Job.Id); err != nil {
		if retryCnt > 5 {
			return errors.New("retry count over 5")
		} else if err.Error() == "PROCESSING" {
			// Retry WaitJob since 429(Too Many Request Err) or TCP operation timed out error.
			time.Sleep(time.Second * 5)

			retryCnt++
			goto _WAIT_DONE
		} else {
			return err
		}
	}

	return nil
}

createJobInput에서 설정하는 값들은 템플릿 중 변경되어야 하는 값만 설정해주면 된다.

예를 들면, input/output 파일 경로나 혹은 미디어 파일마다 암호화 키를 다르게 설정해줘야 한다면 Settings 필드에서 값을 설정해준다.

이외에 모든 hls 파일에 대한 설정은 template에 입력한 값 그대로 인코딩된다.

 

템플릿을 통해 생성한 job의 id를 통해서 job의 진행 상태를 체크하여 완료 여부를 확인한다.

func (m *MCClient) WaitForJobDone(jobId *string) error {
	var err error
	jobDone := false

	checkTicker := time.NewTicker(time.Second * 5)

	for {
		select {
		case <-checkTicker.C:
			if err = m.CheckJobDone(jobId); err != nil {
				return err

			} else if jobDone && err == nil {
				return nil
			}
		}
	}
}

func (m *MCClient) CheckJobDone(jobId *string) error {
	job, err := m.cli.GetJob(&mediaconvert.GetJobInput{Id: jobId})
	if err != nil {
		return err
	}

	switch *job.Job.Status {
	case "PROCESSING":
		return errors.New("PROCESSING")
	case "COMPLETE":
		return nil
	case "ERROR":
		return errors.New(fmt.Sprintf("%v", *job.Job.ErrorMessage))
	default:
		return errors.New("still not complete")
	}
}

 

결과 파일은 s3://test-output-bucket/hls/ 하위에 떨어질 것이다.