HLS란 무엇인가?
HLS (HTTP Live Streaming) 이며 주문형 스트리밍 이자 라이브 스트리밍 입니다. 일반적으로 우리는 웹상에서 동영상을 볼 때 한 동영상파일의 전체크기를 다운받고 시청을 하지 않습니다. 한 동영상파일을 잘게 분리한다음 한 조각조각씩 사용자가 순서대로 다운받아와서 동영상을 시청할 수 있는 방식입니다.
실제로 일상생활에서도 동영상을 보다가 HTTP통신환경이 좋지않아 동영상이 끊길 경우가 종종 생깁니다. 저는 이 경우를 버퍼링이 걸리는 경우로 기억하고있습니다. 항상 한 가지 개념을 기억하기 가장 좋은 예시는 본인의 경험의 한 상황으로 연결짓는다면 기억에 오래남는 것 같습니다. 실제로 버퍼링의 의미는 말 그대로 버퍼에 데이터를 담는다는 뜻으로 쓰이고 버퍼링이 걸린다 라는 것은 네트워크 통신이 약해져서 우리가 보고있는 (동영상 데이터)가 버퍼에 담기지않아 지금까지 버퍼에 담아두었던 영상의 부분까지만 시청하고 대기상태에 이르는 상황인 것입니다.
다시 HLS의 얘기로 돌아와서 HLS는 비디오 스트리밍 프로토콜로 Apple사가 개발했고 현재는 다양한 장치에서 이 프로토콜이 활용되고 있습니다.
다양한 장치에서까지 이 프로토콜을 사용하는 이유는 무엇일까요?
HLS의 장점으로는 모든 인터넷 연결 장치가 HTTP를 지원하기 때문에 전용 서버가 필요한 스트리밍 프로토콜보다 간단하게 실행할 수 있다는 것입니다.
또 다른 장점은 HLS스트리밍은 재생에 지장을 주지 않으며 네트워크 상태에 따라 비디오품질을 높이거나 낮출 수 있다는 것입니다. 여기까지 읽었을 때 가끔 영상을 보다가 화질이 안좋아지는 경험을 해보신 분이라면 공감을 하실 수 있을 것 같습니다.
이 때문에 사용자는 시청중 품질이 나빠지거나 좋아질 수 있고(네트워크 상황에 따라) 이 기능은 "적응 비트 전송률 비디오 전송", "적응비트 전송률 스트리밍" 이라고 알려져 있으며 이 기능이 없으면 네트워크가 느려진 경우 비디오 재생이 완전히 멈출 수 있습니다.
여기서 스트리밍에 대한 개념을 한번 짚고 넘어가겠습니다.
스트리밍은 무엇이냐?
- 스트리밍은 인터넷을 통해 비디오, 오디오 미디어를 전달하는 방식으로 미디어파일을 한 번에 모두 보내는 대신 한 번에 조금씩 지속적으로 사용자 장치에 보냅니다. 원 미디어 파일은 멀리 떨어진 곳에 저장되어 있거나 라이브 스트리밍의 경우 원격 카메라나 마이크를 이용하여 실시간으로 제작됩니다.
- 위 특징을 읽어보면 HLS의 이야기와 같게 느껴질 수 있습니다. 결론적으로 맞습니다 스트리밍의 방식을 그대로 적용하기 때문입니다.
- 그리고 이 작은 데이터조각들을 지속적으로 사용자가 다운로드받는 것을 버퍼링 이라고 합니다.
그래서 이 HLS는 적응 비트레이트 스트리밍 방식의 스트리밍을 제공합니다.
그렇다면 이제 HLS 중 H에 대한 이야기가 남아있습니다.
H는 HTTP입니다.
HTTP(Hyper Text Transfer Protocol)는 무엇이냐?
- HTTP는 네트워크에 연결된 장치사이 정보를 전송하기 위한 어플리케이션 계층 프로토콜입니다. 일반적인 사용자가 액세스할 수 있는 모든 웹사이트와 어플리케이션은 HTTP에서 실행됩니다. HTTP를 통한 데이터 전송은 일반적으로 용청과 응답에 따라 이루어지며 이 HTTP의 통신방식은 추후 다른 게시글을 통해 자세하게 설명해드리겠습니다. 현재는 이 HTTP는 목적지와 편지를 주고 받는 개념이라고 생각하시면 좋을 것 같습니다.
- 그리고 이 HTTP를 스트리밍의 경우 표준 요청 응답 패턴이 적용되지 않습니다. 클라이언트와 서버 사잉의 연결은 스트리밍 기간 동안 열려 있고 서버는 비디오 데이터를 클라이언트는 비디오 데이터 세그먼트마다 요청하지 않아도 됩니다.
- 또한 HTTP통신 중 데이터를 주고 받을 때 흔히 발생하는 CORS, CORB 에러가 있습니다. 이 에러는 HTTP의 구조를 조금 더 명확하게 알고 있다면 수월하게 해결할 수 있으며 이 문제역시나 다른 게시글에서 조금 더 깊게 다루어 보겠습니다.
이 HLS의 또 다른 특징으로는 스트리밍 데이터를 .m3u8 확장자와 .ts확장자를 가진 파일로 분리한다는 특징이 있습니다.
저는 이것을 직접 구현하기위해 우선 ffmpeg 프로그램을 이용해 동영상 파일은 분리하는 작업을 진행했습니다.
코드는 다음과 같고 ffmpeg파일은 HLS관련 코드를 검색하시면 쉽게 구하실 수 있습니다.
const ffmpeg = require('fluent-ffmpeg');
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
//ffmpegInstaller는 ffmpeg만 사용했을 때 생겼던 오류를 해결하기 위해 사용.
ffmpeg.setFfmpegPath(ffmpegInstaller.path);
ffmpeg('videos/고등어조림.mp4', {timeout : 432000}).addOptions([
'-profile:v baseline',
'-level 3.0',
'-start_number 0',
'-hls_time 10', // hls_time : 몇 초 단위로 동영상을 분할할 것인지 설정
'-hls_list_size 0',
'-f hls' // 포맷을 설정 -> HLS사용.
]).output('videos/output.m3u8').on('end',() =>{
console.log('end');
}).run();
소스를 보시면 fluent-ffmpeg라는 것을 처음 불러오고 이 ffmpeg를 통해 "videos/고등어조림.mp4" 라는 동영상 파일을 옵션에 맞게 분할하는 것을 생각해볼 수 있습니다. 그리고 output부분을 확인해보시면 m3u8의 확장자로 뽑아내는 것을 확인할 수 있습니다.
이렇게 m3u8파일만 뽑는 것처럼 읽을 수 있으나 m3u8뿐만 아니라 ts파일 역시 같이 만들어지게되고 이 m3u8은 ts파일들의 순서를 기록하는 설명서역할을 합니다.
즉 웹 브라우저는 HTTP통신을 통해 처음 m3u8파일을 최초로 가져오게되고 이 m3u8의 내용을 읽어 0번째의 ts(동영상 분할 파일)을 가지고와서 영상데이터를 제공하는 방식입니다.
저는 이 HLS protocol을 이용하는 방식을 React X Spring Boot에서 이용해 보았습니다. 처음 설계를 진행할 때는 이 Spring Boot가 스트리밍 서버의 목적에 맞지 않고 조금더 범용적인 여러 기능을 핸들링할 수 있는 백엔드서버의 역할성 때문에 또 다른 백엔드서버인 Nodejs를 활용해 스트리밍서버를 구성하려고 했으나 해당 프로젝트를 진행할 때 강사님의 조언으로는 백엔드서버가 여러개 있는 것보단 현재 프로젝트 기준으로써는 하나의 백엔드 서버가 맞다는 이야기에 Spring Boot 백엔드 API서버와 React의 react-hls-player를 통해 이 프로토콜을 활용하게 되었습니다.
해당 프로젝트의 소스코드가 궁금하신 분들을 위해 아래 깃허브 링크를 남겨두겠습니다.
이상으로 HLS Protocol에 대한 간단한 개념 정리글을 마치겠습니다.
https://github.com/ukjinlee66/metanet_internship_project
HLS에 대한 기초적인 소스코드를 확인하고싶다면 root위치에 streaming_server/HLSTest 를 확인해주시면 감사하겠습니다.
Reference
'지식 창고' 카테고리의 다른 글
MSA란 무엇일까? (0) | 2023.01.10 |
---|---|
REST API란? (0) | 2022.09.12 |
프레임워크랑 라이브러리는 뭐가 다를까?? (0) | 2022.09.03 |