RTMP(Real Time Messaging Protocol) + HLS 으로 실시간 방송 구현하기(기초 구성) - 1
구현 전 사전 간단한 개념.
1. RTMP(Real-Time Messaging Protocol)
1-1. 역할
- 실시간 오디오/비디오 데이터를 Client -> Server 로 전달 하기 위한 전송 프로토콜
1-2. 네트워크 특성
- 기본 포트 : 1935
- TCP 기반 연결 (지속 연결과 신뢰성 우선)
1-3. 전송 방식
- Push 방식
- Client(OBS-RTMP)가 Server로 밀어 넣음
1-4. 한계
- 일부 브라우저 에선 직접 재생 불가 Safari에선 가능하지만 다른 브라우저는 hls.js로 화면을 송출 해야함.
2. NGINX-RTMP-MODULE
2-1. 역할
- RTMP Stream을 받아들이는 ingest Server
2-2. 기능
- RTMP 연결 수신 (listen 1935)
- Stream Session 관리(Application, Stream Key)
- Stream Life Cycle 관리 (on_publish, on_done, on_pley)
- RTMP -> HLS 패키징(ts 기반)를 nginx-rtmp-module이 자체적으로 수행 가능(DASH 패키징은 불가능)
2-3. FFmpeg 연동
- exec 지시자를 통해 외부 FFmpeg 프로세스 실행
- RTMP ingest 이후 트랜스코딩/재패키징을 외부로 위임 가능
- NGINX-RTMP-MODULE 내에서 연동은 가능하지만 FFmpeg는 따로 컨테이너를 띄우는 방식으로 함.
2-3. 한계
- 인코딩 없음
- 트랜스코딩 없음
- DASH / CMAF 패키징 없음
- HLS(ts) 패키징만 자체 지원
3.FFmpeg(오디오 / 비디오 처리용 멀티미디어 프레임워크)
3-1. 역할
- RTMP Stream 디코딩(필요 시)
- 재인코딩(Transcoding)
- 포맷 변환 및 패키징(Packaging)
3-2. 대표 처리
- 해상도 및 비트레이트 분기(ABR를 위해 다중 화질 스트림을 생성)
3-3. 결과물
- .ts, .m4s, .m3u8, .mpd 등
- HTTP 기반 스트리밍 가능 형태
4.OBS Studio(RTMP client)
4-1. 역할
- 사용자 화면/카메라/오디오 캡처
- Stream Key 지정
- 실시간 인코딩 수행
4-2. 인코딩
- Video: H.264
- Audio: AAC
4-3. 출력
- RTMP Push to Server
5. HLS(Http Live Streaming)
5-1. 역할
- 실시간/준실시간 오디오/비디오를 HTTP 기반으로 전달하기 위한 적응형 스트리밍 프로토콜
- 브라우저/모바일 단말에서 재생 가능한 최종 배포 포맷
5-2. 네트워크 특성
- 전송 방식: HTTP/HTTPS
- 포트: 80 / 443
- CDN 친화적 (Segment는 캐시 가능, Playlist는 캐시 제어 필요)
- TCP 기반(HTTP 위에서 동작)
5-3. 전송 방식
- Pull 방식
- Client(Player)가 서버로부터 Segment 파일을 요청
- 다중 화질 스트림 중 시청자의 네트워크 상태에 따라 적절한 화질을 자동으로 선택 및 전환할 수 있는 ABR 구조를 제공
5-4. 구성 요소(HLS의 핵심 구조: .m3u8과 .ts의 관계)
- Media Playlist
- .m3u8
- Master Playlist (Variant 선택)
- Media Playlist (Segment 목록)
- Media Segment
- .ts(전통적)
- .m4s(CMAF 기반)
📌이 부분은 HLS 동작 원리이므로 추후에 설명.
5-5. 특징
- Safari / iOS 네이티브 지원
- <video src="*.m3u8"> 로 바로 재생 가능
- 라이브 / VOD 모두 지원
- LL-HLS(Low Latency HLS) 지원가능
5-6. 한계
- DASH 대비 표준 유연성 낮음(Apple 주도)
- 브라우저 DRM 확장성 제한적 (FairPlay 중심)
- 전통 HLS(ts) 기준으로 초저지연에는 제약
6. 아키텍쳐 구조
7. 구현 코드
7-1. docker-compose.yml
7-2. nginx.conf
daemon off;events { worker_connections 1024; }
rtmp { server { listen ${RTMP_PORT}; chunk_size 4096; # OBS publish # EndPoint : rtmp://HOST:${RTMP_PORT}/live # RTMP URL EndPoint의 /live는 application 이름이며, application live {} 설정에 의해 결정된다. application live { live on;
# RTMP -> HLS # RTMP ingest → (nginx 내부) HLS 패키징 hls on; hls_path /var/www/hls; hls_fragment 5; hls_playlist_length 10; } }}
http { # 응답 헤더/에러 페이지 등에 nginx 버전 노출을 줄임(보안/깔끔함) server_tokens off; # HTTP access log를 파일 대신 표준출력으로 보냄 # Docker에서 로그 수집하기 좋음. access_log /dev/stdout combined;
server { listen ${HTTP_PORT}; # 정적 파일 제공 루트 디렉토리 # index.html을 찾는 기준. root /var/www/html;
location = / { try_files /index.html =404; }
# HLS 제공 http://HOST:${HTTP_PORT}/live/hello.m3u8 # hello는 OBS Studio에서 정한 Stream Key location /live/ { alias /var/www/hls/; types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } # HLS는 “계속 바뀌는 라이브 파일”이므로 캐시로 오래 잡히면 문제가 됨. add_header Cache-Control no-cache; # CORS 허용. add_header Access-Control-Allow-Origin *; } }}
7-3. index.html
7-4. 디렉토리 구조
hls-live
├── docker-compose.yml
├── nginx.conf
└── www
└── index.html


댓글
댓글 쓰기