본문 바로가기
서버 개발 (AWS, Linux, DevOps)/아마존 (AWS)

AWS : Cloudfront + S3로 mpeg-dash 영상 업로드 후 테스트해보기 (with FFmpeg)

by 번데기 개발자 2023. 10. 18.
반응형

 

 

Streaming 프로토콜이 필요한 이유


웹에서 <video/> 태그를 통해 홈페이지에 올라가 있는 큰 영상파일을 출력하면 비디오 미디어 파일을 모두 다운로드 하기전에 재생이 안됩니다. 

 

이를 해결하기 위해 영상의 일부를 먼저 다운로드하고 재생을 하고 다음 일부를 다운로드하고 재생하는 스트리밍 방식을 사용할수 있는데요, 가장 대표적인게 HLS와 MEPG-DASH 라고 하는 스트리밍 프로토콜입니다.

 

위와같은 Streaming 프로토콜을 통해 영상의 일부를 먼저 다운로드 받아서 빠르게 재생을 할 수 있을 뿐 아니라 동적으로 비트레이트(bitrate)를 조절하여 환경에 따라 적절한 bitrate의 영상을 불러올수도 있고 , Client의 저장공간을 효율적으로 사용하거나, 실시간으로 라이브 방송을 스트리밍할수도 있는 다양한 장점들이 있습니다.

 

 

S3 + Cloudfront 를 통한 스트리밍 

 

AWS에서는 S3 + Cloudfront를 사용하여 HLS 또는 DASH 비디오를 호스팅 할 수 있는데요, 일반적으로 비디오 파일을 HLS 등의 형식으로 인코딩 한뒤에 원본 S3 경로에 올려놓으면 됩니다.

 

이번에 실습해 볼 내용으로 .mp4 .mov 파일과 같은 영상을 가지고 있을 때 해당 비디오파일을 mpeg-dash 파일 형식으로 인코딩한 뒤 S3 + Cloudfront에 올려서 정상적으로 웹에서 불러와지는지를 목표로 한번 테스트해보도록 하겠습니다. 

 

 

FFmpeg 으로 Dash 인코딩하기

 

FFmpeg는 오픈 소스 멀티미디어 프레임워크로 오디오, 비디오, 이미지 등 다양한 멀티미디어 형식을 처리하는데 사용되며, 인코딩 및 디코딩 작업에도 많이 활용됩니다.

 

위는 FFmpeg 을 통해 1.mp4 파일을 FFmpeg으로 인코딩한 결과입니다.

 

최종적으로는 output.mpd 파일과 chunk 파일들이 생성됩니다. 

 

간단히 테스트용으로 인코딩한 결과이기 때문에 생각보다 오래걸리지는 않았습니다.

 

 

추가) 

 

아래와 같이 HLS도 가능하며 bitrate별로도 인코딩을 할수 있으니 참고하시면 좋을것 같습니다.

 

// FFmpeg을 사용한 영상 HLS 트랜스코딩 / 8k → 8k, 4k, 2k, FHD, HD, 480p, 360p
ffmpeg -i lesserafim.mkv \
  -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
  -filter:v:0 scale=w=640:h=360  -maxrate:v:0 1500k -b:a:0 500k \
  -filter:v:1 scale=w=854:h=480  -maxrate:v:1 4000k -b:a:1 500k \
  -filter:v:2 scale=w=1280:h=720 -maxrate:v:2 9500k -b:a:2 500k \
  -filter:v:3 scale=w=1920:h=1080 -maxrate:v:3 15000k -b:a:3 500k \
  -filter:v:4 scale=w=2560:h=1440 -maxrate:v:4 30000k -b:a:4 500k \
  -filter:v:5 scale=w=3840:h=2160 -maxrate:v:5 68000k -b:a:5 500k \
  -filter:v:6 scale=w=7680:h=4320 -maxrate:v:6 150000k -b:a:6 500k \
  -var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p v:3,a:3,name:1080p v:4,a:4,name:1440p v:5,a:5,name:2160p v:6,a:6,name:4320p" \
  -preset fast -hls_list_size 10 -threads 0 -f hls \
  -hls_time 3 -hls_flags independent_segments \
  -master_pl_name "lesserafim-master.m3u8" \
  -y "lesserafim-%v.m3u8"


// FFmpeg을 사용한 영상 HLS 트랜스코딩 / FHD → FHD, HD, 480p, 360p (결과물 폴더구조)
ffmpeg -i aespa.mkv \
  -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
  -filter:v:0 scale=w=640:h=360  -maxrate:v:0 1500k -b:a:0 500k \
  -filter:v:1 scale=w=854:h=480  -maxrate:v:1 4000k -b:a:1 500k \
  -filter:v:2 scale=w=1280:h=720 -maxrate:v:2 9500k -b:a:2 500k \
  -filter:v:3 scale=w=1920:h=1080 -maxrate:v:3 15000k -b:a:3 500k \
  -var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p v:3,a:3,name:1080p" \
  -preset fast -hls_list_size 10 -threads 0 -f hls \
  -hls_time 3 -hls_flags independent_segments \
  -master_pl_name "aespa-master.m3u8" \
	-hls_segment_filename "res_%v/file_%03d.ts" "res_%v/index.m3u8"

 

  • -hls_init_time (seconds) : 초기 대상 세크먼트 길이를 초단위로 설정, 기본값은 0
  • -hls_time (seconds) : 세그먼트의 길이를 초단위로 설정, 기본값은 2
  • -hls_list_size (size) : 최대 엔트리수 제한, 예를들어 10으로 설정하면 현재위치기준 이전 10개 빼고 모든 엔트리 삭제, 기본값 5
  • -hls_delete_threshold (size) : 세그먼트를 삭제하기 전에 디스크에 보관할 세그먼트 수, 기본값 1
  • -b:v : 비디오 스트림의 비트레이트, 한 화소를 그리는데 얼마나 많은 정보를 사용할지. 값이 높을수록 품질 향상
  • -maxrate : 최대 비트레이트. -b:v는 평균적인 설정값, 영상의 특정값에는 비정상적으로 큰값을 가질수있기때문에 상한선 설정
  • -b:a : 오디오 스트림의 비트레이트
  • -f : 파일의 포멧
  • -preset : 압축을 하는데 걸리는 시간, 또는 압축률. 압축률이 높을수록 걸리는 시간 오래걸림 (ultrafast, fast, slow.. 등 사용가능)
  • -map : 입력의 어떤 스트림이 출력에 포함되어야 하는지. ex) map:0:0은 입력스트림 0의 첫번째 스트림
    ("-map 0:v:0 -map 0:a:0" 은 출력 스트림의 개수 만큼 N 번 들어가야 함)
  • -var_stream_map : 오디오 비디오 자막 스트림을 다른 변형 스트림으로 그룹화하는 방법을 지정
    (“name:360p”와 같이 이름으로 설정된 “360p” 문자열은 이후 hls_segment_filename 옵션의 %v에 대입)
  • -threads : 작업에 사용되는 CPU 코어의 갯수, 0으로 설정하면 알아서 최적화된 코어 개수 사용

 

 

FFMPEG + S3 + Cloudfront 으로 Dash 파일 업로드하기

 

 

위와같이 CloudFront 에 연결된 S3 버킷의 특정 위치에 Dash의 Manifest 파일(.mpd) 및 세그먼트(.m4s) 파일을 업로드 하였습니다. 

 

 

 

HTML 에서 동작시켜보기

 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
    }
    
    video {
      max-width: 100%;
      max-height: 100%;
      width: auto;
      height: auto;
    }
  </style>
  <script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
<body>

  <video id="videoPlayer" controls></video>
</body>

<script>
  (function(){
    var url = "https://cloudfront주소/apps/dash-test/output.mpd";
    var player = dashjs.MediaPlayer().create();
    player.initialize(document.querySelector("#videoPlayer"), url, true);
  })();
</script>

</html>


MPEG-DASH 로 되어있는 스트리밍 프로토콜을 Web에서 재생시키기위해서는 MPEG-DASH 프로토콜을 구현하는 JavaScript 기반의 오픈 소스 미디어 플레이어 라이브러리인 dash.js를 설치하는 것이 쉬운 방법입니다.

 

위와같이 CDN으로 dash.js를 다운받고 요청하면 아래와 같이 영상이 잘 재생되는것을 확인할수 있습니다.

 

마무리

 

이번에는 FFmpeg를 이용하여 비디오 파일을 MPEG-DASH 파일로 인코딩하고 S3에 올려서 해당 주소를 통해 웹에서 스트리밍 데이터를 받아오는 것을 한번 테스트해보았습니다.

 

FFmpeg 에 대해 자세히 알 수 있었고, 영상 스트리밍에 대한 이해도 많이 생긴것 같아서 의미있었던것 같습니다.

 

다음에도 유용한 내용으로 포스팅하도록 하겠습니다.

 

감사합니다. 

 

반응형