영상 스트리밍 #9. 라이브 스트리밍

Bobby·2023년 8월 21일
2

streaming

목록 보기
9/9

🎥 개요

지금까지는 저장된 영상을 스트리밍을 해봤다.
실시간 영상 데이터를 스트리밍 하려면 어떻게 해야 할까?

  • 영상 데이터는 마이크와 카메라로 캡쳐 된다.
  • 캡쳐된 영상 데이터를 그대로 전달하는 것을 비효율적이므로 압축/인코딩 작업을 거친다.
  • 인코딩 작업을 마친 영상 데이터를 미디어 서버로 전달한다.(보통 rtmp를 사용)
  • 미디어 서버에 전달된 영상 데이터를 시청자에게 전달 한다.
    • 보통 다양한 기기 및 환경에서 잘 지원되는 http 기반의 HLS 프로토콜을 사용한다.
  • 빠른 재생을 위해 CDN을 사용하기도 한다.
  • 시청자들은 각자의 장치의 플레이어가 압축해제/디코딩 작업을 하여 재생한다.

실시간 스트리밍을 위한 다양한 프로토콜이 있지만 보편적으로 RTMP, HLS를 사용한다.


🎥 준비물

RTMP

  • 프로토콜 이란 데이터를 어떻게 주고 받을 것인가에 대한 규약이다.
  • 웹에서는 보통 http를 통해 데이터를 주고 받는다.
  • 물론 http로도 실시간 영상 데이터를 전달 할 수 있을 것이다.
    (지금까지도 영상 데이터를 http기반의 tus protocol을 이용해서 영상 전송을 했었다.)
  • RTMP는 영상 데이터를 효율적이게 주고받을 수 있도록 실시간 스트리밍에 특화된 프로토콜 중 하나이다.

미디어서버

  • rtmp 서버를 직접 구현하는 것은 매우 어려운 일..
  • 미디어서버를 제공하는 여러 솔루션들이 있다.(AWS IVS, WOWZA, ... )
    • 매우 비싸다ㅎㅎ
  • 오픈소스 rtmp-nginx 모듈을 사용해서 구축해보자.

FFMPEG

  • 오픈소스 인코딩 프로그램
  • 미디어 서버에서 rtmp 데이터를 hls 포멧으로 인코딩 할 때 사용

rtmp송출 프로그램


🎥 미디어 서버 구축

nginx.conf

worker_processes  auto;

user root;

events {
    worker_connections  1024;
}

# http 모듈
http {
	
    server {
        listen 8080;

        root /tmp;
			
        # 8080 포트에서 hls 재생
        location /hls {
            types {
                 application/vnd.apple.mpegurl m3u8;
                 video/mp2t ts;
            }
        }
    }
}

# rmtp 모듈
rtmp {
    server {
    	# rtmp 는 기본적으로 1935 포트를 사용한다.
        listen 1935;
        chunk_size 4096; # 청크 사이즈

		# app 이름 live
        application live {
			
            live on;

			# 들어온 rtmp 데이터를 ffmpeg를 이용해서 hls로 인코딩
            # 화질별로 인코딩 $app은 app 이름 $name은 식별자(채널 같은 의미)
            exec_push ffmpeg -i rtmp://localhost:1935/$app/$name -async 1 -vsync -1
                             -c:v libx264 -c:a aac -b:v 256k  -b:a 64k  -vf "scale=480:trunc(ow/a/2)*2"  -tune zerolatency -preset superfast -crf 23 -f flv rtmp://localhost:1935/hls/$name_low
                             -c:v libx264 -c:a aac -b:v 768k  -b:a 128k -vf "scale=720:trunc(ow/a/2)*2"  -tune zerolatency -preset superfast -crf 23 -f flv rtmp://localhost:1935/hls/$name_mid
                             -c:v libx264 -c:a aac -b:v 1024k -b:a 128k -vf "scale=960:trunc(ow/a/2)*2"  -tune zerolatency -preset superfast -crf 23 -f flv rtmp://localhost:1935/hls/$name_high
                             -c:v libx264 -c:a aac -b:v 6000k -r 60  -b:a 128k -vf "scale=1280:trunc(ow/a/2)*2" -tune zerolatency -preset superfast -crf 23 -f flv rtmp://localhost:1935/hls/$name_hd720
                             -c copy -f flv rtmp://localhost:1935/hls/$name_src;

            drop_idle_publisher 10s;
        }

		# hls 파일로 저장~
        application hls {
            live on;
            hls on;
            hls_fragment 10s;
            hls_playlist_length 10;
            hls_path /tmp/hls; # 파일 위치

            hls_variant _src BANDWIDTH=4096000;
            hls_variant _hd720 BANDWIDTH=2048000;
            hls_variant _high BANDWIDTH=1152000;
            hls_variant _mid BANDWIDTH=448000;
            hls_variant _low BANDWIDTH=288000;
        }
    }
}

Dockerfile

FROM alpine:3.13.4 as builder

RUN apk add --update build-base git bash gcc make g++ zlib-dev linux-headers pcre-dev openssl-dev

# nginx, nginx-rtmp-module 다운
RUN git clone https://github.com/arut/nginx-rtmp-module.git && \
    git clone https://github.com/nginx/nginx.git

# nginx를 설치하고 nginx-rtmp-module 추가
RUN cd nginx && ./auto/configure --add-module=../nginx-rtmp-module && make && make install

FROM alpine:3.13.4 as nginx

# ffmpeg 설치
RUN apk add --update pcre ffmpeg

# 빌드된 파일 및 설정파일 복사
COPY --from=builder /usr/local/nginx /usr/local/nginx
COPY nginx.conf /usr/local/nginx/conf/nginx.conf

# 실행
ENTRYPOINT ["/usr/local/nginx/sbin/nginx"]
CMD ["-g", "daemon off;"]

실행

# 이미지 빌드
docker build -t nginx-rtmp .

# 실행
docker run -d -p 1935:1935 -p 8080:8080 --name nginx-rtmp nginx-rtmp


🎥 실시간 영상 송출하기

좀 더 예쁜 streamlabs 사용했다.

송출 화면 설정

  • 이미지, 영상, 화면캡처, 브라우저 소스 등등 여러가지 송출 소스들을 추가 할 수 있다.
  • 브라우저 소스로 타이머를 추가해봤다.

송출 서버 설정

  • url은 1935 포트로 app 이름을 live로 설정(nginx.conf)
  • 스트림키는 고유 식별자로 아무거나 적으면 된다.
    • 설정 파일에서 $name 값으로 들어간다.

송출

  • 파일을 확인해보자.
docker exec -it nginx-rtmp sh
  • hls로 잘 인코딩 되고 있다.

시청

  • 사파리로 실행해보자. 또는 hls 파일을 실행할 수 있는 플레이어

http://localhost:8080/hls/test-stream-key_src.m3u8

profile
물흐르듯 개발하다 대박나기

1개의 댓글

comment-user-thumbnail
2024년 1월 23일

감사합니다.

답글 달기