본문으로 건너뛰기

Object Storage와 CDN으로 HTTP Live Streaming 구현

카카오클라우드 Object Storage와 CDN을 이용하여 간단한 HLS(HTTP Live Streaming) 예제를 구현하는 방식을 설명합니다. Object Storage API를 통해 코드 기반으로 HLS 구성 파일을 업로드하고, CDN을 통해 배포하여 진행합니다.

안내
  • 예상 소요 시간: 25분
  • 사용자 환경
    • 권장 운영 체제: MacOS
    • Region: kr-central-2
  • 사전 준비 사항
    • Python 실행 환경 설정
    • pip: Python 패키지 관리 도구 설치

시작하기 전에

1. FFmpeg 관련 패키지 설치

  1. 아래 명령을 실행하여 비디오 파일 인코딩과 segmentation을 지원하는 오픈소스 소프트웨어인 FFmpeg을 설치합니다.

    ffmpeg 설치
    brew install ffmpeg
  2. Python FFmpeg를 사용하기 위해 아래의 명령을 실행해 Python FFmpeg Video Streaming 패키지를 설치합니다. 해당 패키지는 DASH 및 HLS와 같은 온라인 스트리밍을 위한 미디어 콘텐츠를 패키지화합니다.

    Python FFmpeg Video Streaming 설치
    pip install python-ffmpeg-video-streaming

2. Object Storage 버킷 생성

Object Storage 버킷 & 폴더 생성에 대한 자세한 예제는 Object Storage API를 이용하여 이미지 업로드하기 문서의 API 호출로 버킷 관리API 호출로 오브젝트 관리 > Step 1. 버킷 생성하기를 참고하시기 바랍니다.

  1. Python으로 버킷(Bucket)을 생성하는 API 호출 코드를 작성하여 버킷을 생성합니다. 버킷 이름은 my-bucket-new 로 설정합니다.
  2. Python으로 버킷에 대한 접근을 관리하는 API 호출 코드를 작성하여 버킷에 대한 접근을 관리합니다. 이번 예제에서는 버킷에 대한 모든 IP 주소의 퍼블릭 액세스를 허용합니다.
  3. Python으로 생성한 버킷 안에 폴더를 생성하는 API 호출 코드를 작성하여 폴더를 생성합니다. 폴더 이름은 hls 로 설정합니다.

3. CDN 생성

CDN 설정하기에 대한 자세한 예제는 Object Storage, CDN을 이용한 정적 웹사이트 호스팅하기 문서의 Step 4. CDN 설정하기를 참고하시기 바랍니다.

  1. 카카오클라우드 콘솔 > Beyond Networking Service > CDN에서 CDN을 생성합니다.

    1단계: 서비스 및 오리진 서버 설정
    항목
    서비스 이름hls-test-cdn
    호스트 서버KiC CDN
    오리진 서버KakaoCloud object storage
    - 버킷: my-bucket-new 선택
    오리진 서버 프로토콜HTTPS
    오리진 서버 포트 번호443
    오리진 서버 경로/hls
    Gzip Compression사용
    2단계: 캐시 설정
    항목
    만료 정책사용자 설정
    유지 기간3 초
    URL Query String포함
    이미지(JPG) 파일 최적화-
  2. 생성된 CDN 서비스의 [더 보기] 아이콘 > 시작 또는 재시작을 클릭해 CDN 서비스를 시작합니다.

시작하기

Step 1. 예제 정적 웹 사이트 생성 및 업로드

1. 예제 정적 웹 사이트 생성하기

  1. 아래 명령을 실행하여 작업 디렉터리를 생성합니다.

    작업 디렉터리 생성
    mkdir -p ~/hls-handson
  2. 하단의 html 예제를 참고하여 접근 웹 html 파일을 작성합니다. HLS 구현을 위해 오픈소스 자바스크립트 라이브러리인 Hls.js를 이용합니다.

    • 텍스트와 영상을 출력하는 간단한 정적 웹 사이트입니다. HTML5의 video 태그를 이용하고, video 태그의 소스(src) 속성은 'hls.m3u8'로 설정합니다. 이는 추후 과정에서 생성할 hls.m3u8 파일의 접근 경로입니다.
    정적 웹사이트 출력 예제
    cat <<EOF > ~/hls-handson/index.html
    <!DOCTYPE html>
    <head>
    <meta charset="utf-8">
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    </head>
    <body onkeydown="return false" oncontextmenu="return false" onselectstart="return false" ondragstart="return false">
    <h1>HLS Test Page</h1>
    <video height="720" width="1280" autoplay muted id="video"></video>
    <script>
    var video = document.getElementById('video');
    var videoSrc = 'hls.m3u8';
    if (video.canPlayType('application/x-mpegURL')) {
    video.src = videoSrc;
    } else if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
    }
    </script>
    </body>
    </html>
    EOF

2. API 호출로 예제 사이트 업로드하기

본 단계에서는 Python으로 코드를 작성합니다. [Step 1]에서 생성한 hls-handson 폴더 안에 Python 파일(.py)을 생성해 해당 파일에서 작업을 진행합니다.

  1. 사전 작업에서 생성한 Object Storage 폴더 안에 index.html 파일을 업로드하는 API 호출 Python 코드를 작성합니다.

    index.html 파일 업로드
    import requests

    def uploadFile():
    headers = {
    'X-Auth-Token': '{X_AUTH_TOKEN}',
    'Content-Type': 'text/html'
    }
    data = open('{FILE_PATH}', 'rb')
    res = requests.put('https://objectstorage.kr-central-2.kakaocloud.com/v1/{ACCOUNT}/{BUCKET_NAME}/{FOLDER_NAME}/{FILE_NAME}', headers=headers, data=data)
    data.close()

    uploadFile()
    변수설명실습 설정값
    X_AUTH_TOKENAPI 인증 토큰
    FILE_PATH파일이 위치한 경로. 이번 실습에서는 index.html 파일이 위치한 경로index.html
    ACCOUNT프로젝트 ID
    - 토큰 발급 시 확인 가능
    - Response Body의 token > project > id 값
    BUCKET_NAME파일이 업로드될 버킷 이름my-bucket-new
    FOLDER_NAME파일이 업로드될 폴더 이름hls
    FILE_NAME생성(업로드)할 파일 이름index.html
  2. 코드 실행 후,카카오클라우드 콘솔 > Object Storage 서비스에서 my-bucket-new 버킷을 선택합니다.

  3. 객체 탭에서 hls 폴더 안에 index.html 파일이 업로드된 것을 확인합니다.

3. 예제 사이트 접속 확인하기

CDN 서비스 도메인의 index.html 경로로 접속합니다.

  1. 카카오클라우드 콘솔 > Beyond Networking Service > CDN > 서비스 목록에서 생성된 CDN의 서비스 도메인을 복사합니다.

  2. 웹 브라우저에서 테스트 페이지로의 정상 접속을 확인합니다.

    # 접속할 서비스 도메인 주소
    http://{CDN에서 생성한 URL}/index.html
  3. 도메인 접속 시 텍스트가 출력됩니다. 스트리밍에 필요한 파일이 아직 준비되지 않았으므로 영상은 출력되지 않습니다.

    영상 CDN 서비스 도메인 접속 결과

Step 2. 버킷에 HLS 구성 파일 업로드하기

1. 동영상 파일 준비하기

로컬 터미널에서 아래의 코드를 실행하여 로컬의 ~/hls-handson 폴더에 스트리밍을 위한 동영상 파일(kakaoenterprise.mp4)을 다운로드합니다.

동영상 다운로드 명령어
curl -o ~/hls-handson/kakaoenterprise.mp4 \
https://objectstorage.kr-central-2.kakaocloud.com/v1/fe631cd1b7a14c0ba2612d031a8a5619/public/tutorial/hls-live-streaming/kakaoenterprise.mp4

2. FFmpeg으로 동영상 파일(.MP4) 인코딩 및 Segmentation하기

본 단계에서는 Python으로 코드를 작성합니다. [Step 1]에서 생성한 hls-handson 폴더 안에 Python 파일(.py)을 생성해 해당 파일에서 작업을 진행합니다.

  1. HLS로 영상을 제공하기 위해서는 재생 정보가 담긴 m3u8 파일과 원본 영상을 잘게 분할한 ts 파일이 필요합니다. 아래 코드를 실행하여 원본 동영상 파일(.mp4)을 변환해 m3u8 파일과 ts 파일을 화질 별로 생성할 수 있습니다.

    동영상 파일 변환 명령어
    import ffmpeg_streaming
    from ffmpeg_streaming import Formats, Bitrate, Representation, Size

    capture = ffmpeg_streaming.input('{MP4_FILE_PATH}')

    _360p = Representation(Size(640, 360), Bitrate(276 * 1024, 128 * 1024))
    _480p = Representation(Size(854, 480), Bitrate(750 * 1024, 192 * 1024))
    _720p = Representation(Size(1280, 720), Bitrate(2048 * 1024, 320 * 1024))

    hls = capture.hls(Formats.h264())
    hls.representations(_360p, _480p, _720p)
    hls.output('output/hls.m3u8')
    변수설명실습 설정값
    MP4_FILE_PATHmp4 파일이 위치한 경로kakaoenterprise.mp4
  2. 코드 실행 시 하단의 폴더 구조와 같이 ~/hls-handson/output 폴더 내에 화질 별 m3u8 파일과 ts 파일들이 생성됩니다.

    폴더 구조
    output/
    ├── hls.m3u8
    ├── hls_360p.m3u8
    ├── hls_360p_0000.ts
    ├── …
    ├── hls_480p.m3u8
    ├── hls_480p_0000.ts
    ├── …
    ├── hls_720p.m3u8
    ├── hls_720p_0000.ts
    └── …

3. Object Storage API를 이용하여 버킷에 m3u8, ts 파일 업로드하기

Object Storage 버킷에 파일을 업로드하는 API 호출 코드를 작성하여 my-bucket-new 버킷의 hls 폴더 안에 m3u8 파일과 ts 파일을 업로드합니다.

  1. 파일 업로드 API 호출 시 headersContent-Type에는 MIME type 문자열을 입력해야 합니다. m3u8audio/mpegurl 유형으로, ts 파일은 application/octet-stream 유형으로 Content-Type을 설정합니다.

    파일 업로드 API 호출 코드
    import requests
    import os

    def uploadHlsFile():
    headers = {'X-Auth-Token': '{X_AUTH_TOKEN}'}

    for file in os.listdir('{OUTPUT_FOLDER_PATH}'):
    file_extension = file.split('.')[1]
    if file_extension == 'm3u8':
    headers['Content-Type'] = 'audio/mpegurl'
    if file_extension == 'ts':
    headers['Content-Type'] = 'application/octet-stream'

    data = open('{OUTPUT_FOLDER_PATH}'+'/'+file, 'rb')
    res = requests.put('https://objectstorage.kr-central-2.kakaocloud.com/v1/{ACCOUNT}/{BUCKET_NAME}/{FOLDER_NAME}/'+file, headers=headers, data=data)
    if res.status_code == 201:
    print("File upload succeeded: " + file)
    else:
    print("File upload failed: " + file)
    data.close()

    uploadHlsFile()
    변수설명실습 설정값
    OUTPUT_FOLDER_PATHm3u8, ts 파일이 위치한 output 폴더의 경로output
    BUCKET_NAME파일이 업로드될 버킷 이름my-bucket-new
    FOLDER_NAME파일이 업로드될 폴더 이름hls
  2. 코드 실행 후, 카카오클라우드 콘솔 > Object Storage 서비스에서 my-bucket-new 버킷을 선택합니다.

  3. 객체 탭에서 hls 폴더 안에 m3u8 파일과 ts 파일이 업로드된 것을 확인할 수 있습니다.

Step 3. 영상 출력 확인하기

도메인에서 업로드한 영상이 잘 출력되는지 확인합니다. CDN 서비스 도메인의 index.html 경로로 접근하여 출력된 영상을 확인합니다.

영상 출력 확인
# 접속할 서비스 도메인 주소
http://{CDN에서 생성한 URL}/index.html

영상 서비스 도메인 접속 결과