RTSP vs RTMP

๊ฐ•์ •์šฐยท2025๋…„ 10์›” 17์ผ
0

๊ธฐํƒ€

๋ชฉ๋ก ๋ณด๊ธฐ
4/4
post-thumbnail

RTSP vs RTMP

๐Ÿ“Œ RTSP (Real Time Streaming Protocol)

๐Ÿ› ๏ธ ์šฉ๋„

"์ปจํŠธ๋กค" ํ”„๋กœํ† ์ฝœ์— ๊ฐ€๊นŒ์›€.
โ†’ ์˜์ƒ/์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์‹ค์–ด๋‚˜๋ฅด๊ธฐ๋ณด๋‹ค๋Š” ์žฌ์ƒ, ์ผ์‹œ์ •์ง€, ์ค‘์ง€ ๊ฐ™์€ ๋ช…๋ น ์ œ์–ด์— ์ง‘์ค‘.

๐Ÿ“ฆ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

๋ณดํ†ต RTP(Real-time Transport Protocol)๋ž‘ ์ง๊ฟ์œผ๋กœ ์‚ฌ์šฉ.
์‹ค์ œ ์˜์ƒ ๋ฐ์ดํ„ฐ๋Š” RTP๋กœ ์ „๋‹ฌํ•˜๊ณ , RTSP๋Š” ๊ทธ๊ฑธ ๊ด€๋ฆฌ.

โš™๏ธ ์‚ฌ์šฉ์ฒ˜

CCTV, IP ์นด๋ฉ”๋ผ, ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ. (๋„คํŠธ์›Œํฌ ์นด๋ฉ”๋ผ ์ฃผ์†Œ๊ฐ€ rtsp://...์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ.)

๐Ÿ‘ ํŠน์ง•

๋‚ฎ์€ ์ง€์—ฐ ์‹œ๊ฐ„(์ˆ˜๋ฐฑ ms ์ˆ˜์ค€). ๋‹ค๋งŒ ๋ฐฉํ™”๋ฒฝ์ด๋‚˜ NAT ํ™˜๊ฒฝ์—์„œ ์ž˜ ๋ง‰ํžˆ๊ธฐ๋„ ํ•จ.

๐Ÿ“Œ RTMP (Real Time Messaging Protocol)

๐Ÿ› ๏ธ ์šฉ๋„

์›๋ž˜ Adobe Flash Player ์šฉ์œผ๋กœ ๋งŒ๋“  "๋ฐ์ดํ„ฐ ์ „์†ก" ํ”„๋กœํ† ์ฝœ.
โ†’ ์˜์ƒ/์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ๋‚ด๋ ค๋ฐ›์„ ๋•Œ ์ง์ ‘ ์”€.

๐Ÿ“ฆ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

TCP ๊ธฐ๋ฐ˜, ์ž์ฒด ํฌ๋งท์œผ๋กœ ์ „์†ก. ์ง€๊ธˆ์€ HLS/DASH ๊ฐ™์€ ํ‘œ์ค€ ์ŠคํŠธ๋ฆฌ๋ฐ์œผ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์—…๋กœ๋“œ(ingest) ํ”„๋กœํ† ์ฝœ๋กœ ์ž์ฃผ ์‚ฌ์šฉ.

โš™๏ธ ์‚ฌ์šฉ์ฒ˜

์œ ํŠœ๋ธŒ ๋ผ์ด๋ธŒ, ํŠธ์œ„์น˜, ํŽ˜์ด์Šค๋ถ ๋ผ์ด๋ธŒ ๋“ฑ ๋ฐฉ์†ก ํ”Œ๋žซํผ ์†ก์ถœ.

๐Ÿ‘ ํŠน์ง•

์ง€์—ฐ ์‹œ๊ฐ„์€ RTSP๋ณด๋‹ค ์•ฝ๊ฐ„ ํฌ์ง€๋งŒ(1~5์ดˆ), ๋ฒ”์šฉ ์ง€์›์ด ์ข‹๊ณ  ์•ˆ์ •์ ์ž„. ๋ฐฉํ™”๋ฒฝ ์šฐํšŒ๋„ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฌ์›€.

ffmpeg ์œผ๋กœ ๋ฏธ๋””์–ด ์ŠคํŠธ๋ฆผ hls ๋ณ€ํ™˜

0. libnginx-mod-rtmp ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ“œ ์ •์˜

Debian/Ubuntu์—์„œ ์ œ๊ณตํ•˜๋Š” Nginx์šฉ RTMP ๋™์  ๋ชจ๋“ˆ ํŒจํ‚ค์ง€๋‹ค.
์—…์ŠคํŠธ๋ฆผ ์˜คํ”ˆ์†Œ์Šค์ธ nginx-rtmp-module(์ผ๋ฐ˜์ ์œผ๋กœ arut/nginx-rtmp-module)์„ ๋ฐฐํฌํŒ ํฌ๋งท์œผ๋กœ ๋ฌถ์–ด๋‘” ๊ฒƒ์ด๋ผ ๋ณด๋ฉด ๋จ.

โš™๏ธ ์—ญํ• 

  1. Nginx์— rtmp {} ๋ธ”๋ก๊ณผ application {}/live on; ๊ฐ™์€ RTMP ์„œ๋ฒ„ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€
  2. OBS ๊ฐ™์€ ํผ๋ธ”๋ฆฌ์…”๊ฐ€ RTMP๋กœ ์—…๋กœ๋“œ(publish) ํ•˜๋ฉด ์ด๋ฅผ ๋ฐ›์•„ ์ค‘๊ณ„(play/relay)
  3. on_publish, on_play ๋“ฑ ์ด๋ฒคํŠธ ์ฝœ๋ฐฑ(HTTP)๋กœ ์ธ์ฆ/๋กœ๊น…์„ ๋ถ™์ผ ์ˆ˜ ์žˆ์Œ. (๊ด€๋ จ ํ›… ๋งํฌ)
  4. exec๋กœ FFmpeg๋ฅผ ์ž๋™ ์Šคํฐํ•˜์—ฌ ํŠธ๋žœ์Šค์ฝ”๋”ฉ/HLS ์„ธ๊ทธ๋จผํŒ… ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ฐ”๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ์Œ.
  5. (์„ ํƒ) ๋ชจ๋“ˆ ์ž์ฒด์˜ HLS/DASH ์„ธ๊ทธ๋จผํŒ… ๊ธฐ๋Šฅ๋„ ์žˆ์œผ๋‚˜, ์„ธ๋ฐ€ํ•œ ์ œ์–ดยทABR ๊ตฌ์„ฑ์€ ๋ณดํ†ต FFmpeg๊ฐ€ ๋” ์œ ์—ฐํ•จ.

โš ๏ธ ์ฃผ์˜/์ œํ•œ

  1. Nginx ๊ณต์‹ ๋ฒˆ๋“ค ๋ชจ๋“ˆ์ด ์•„๋‹Œ ์„œ๋“œํŒŒํ‹ฐ ๋ชจ๋“ˆ์ž„. (๋ฐฐํฌํŒ์—์„œ ํŽธํ•˜๊ฒŒ ์“ฐ๋„๋ก ํŒจํ‚ค์ง•ํ•œ ๊ฒƒ)
  2. RTMPS(SSL)๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Šใ…“๋Š”๋‹ค.
    ํ•„์š”ํ•˜๋ฉด stunnel/Nginx stream ํ”„๋ก์‹œ ๋“ฑ์œผ๋กœ ๊ฐ์‹ธ ์“ฐ๋Š” ํŒจํ„ด์„ ์‚ฌ์šฉ.
  3. ๋ฌด๊ฑฐ์šด ์‹ค์‹œ๊ฐ„ ํŠธ๋žœ์Šค์ฝ”๋”ฉ์€ FFmpeg(๋˜๋Š” SRS ๋‚ด์žฅ/์™ธ๋ถ€ ํŠธ๋žœ์Šค์ฝ”๋“œ)๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž„.

1. RTMP Ingest ๋ฐฉ์‹

ํŒจํ‚ค์ง€ ์„ค์น˜

sudo apt update
sudo apt install -y nginx libnginx-mod-rtmp ffmpeg
sudo mkdir -p /var/www/hls
sudo chown -R www-data:www-data /var/www/hls

nginx.conf ์ž‘์„ฑ

๋™์  ๋ชจ๋“ˆ ๋กœ๋”ฉ + RTMP ์ธ์ ฏ + FFmpeg ์ž๋™ ๋ณ€ํ™˜ + HLS ์„œ๋น™

# ๋™์  RTMP ๋ชจ๋“ˆ ๋กœ๋“œ (Ubuntu/Debian ํ‘œ์ค€ ๊ฒฝ๋กœ)
load_module modules/ngx_rtmp_module.so;

worker_processes auto;

events { worker_connections 1024; }

# ---------- RTMP(Ingest) ์ด ๋ถ€๋ถ„์€ ์•„์˜ˆ ์ƒˆ๋กœ ์ถ”๊ฐ€ ----------
rtmp {
    server {
        listen 1935;          # RTMP default ํฌํŠธ
        chunk_size 4096;

        application live {
            live on;          # publish/play ํ—ˆ์šฉ
            record off;

            # (์„ ํƒ) ํผ๋ธ”๋ฆฌ์‹œ ์ธ์ฆ HTTP ์ฝœ๋ฐฑ ์˜ˆ์‹œ
            # on_publish http://127.0.0.1:8080/auth?name=$name&key=$arg_key;

            # ์ŠคํŠธ๋ฆผ์ด ๋“ค์–ด์˜ค๋ฉด ์ŠคํŠธ๋ฆผ ์ด๋ฆ„($name)๋ณ„๋กœ FFmpeg๋ฅผ ๋„์›Œ HLS๋ฅผ ์ƒ์„ฑ
            # : ABR(1080/720/480) 3์ข…, 2์ดˆ ์งœ๋ฆฌ ์„ธ๊ทธ๋จผํŠธ, ์˜ค๋ž˜๋œ ์„ธ๊ทธ๋จผํŠธ ์‚ญ์ œ
            exec_kill_signal term;
            exec /usr/bin/ffmpeg -loglevel error -hide_banner \
                -reconnect 1 -reconnect_streamed 1 -reconnect_on_network_error 1 \
                -i rtmp://127.0.0.1/live/$name \
                -c:v libx264 -preset veryfast -profile:v high -level 4.1 -pix_fmt yuv420p \
                -sc_threshold 0 -g 60 -keyint_min 60 \
                -c:a aac -ar 48000 -ac 2 -b:a 128k \
                -filter:v:0 "scale=w=-2:h=1080" -b:v:0 6000k -maxrate:0 6420k -bufsize:0 12000k \
                -filter:v:1 "scale=w=-2:h=720"  -b:v:1 3500k -maxrate:1 3740k -bufsize:1 7000k  \
                -filter:v:2 "scale=w=-2:h=480"  -b:v:2 1200k -maxrate:2 1320k -bufsize:2 2400k  \
                -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
                -hls_time 2 -hls_list_size 6 \
                -hls_flags delete_segments+program_date_time+independent_segments \
                -master_pl_name "$name/master.m3u8" \
                -var_stream_map "v:0,a:0 name:1080p v:1,a:1 name:720p v:2,a:2 name:480p" \
                -hls_segment_type mpegts \
                -hls_segment_filename "/var/www/hls/$name/v%v/seg_%06d.ts" \
                "/var/www/hls/$name/v%v/index.m3u8";
        }
    }
}

# ---------- HLS ์„œ๋น™(HTTP) ์ผ๋ถ€ ์˜ต์…˜ ์ถ”๊ฐ€ ----------
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    server {
        listen 80;
        server_name _;

        # HLS ์ •์  ํŒŒ์ผ ์ œ๊ณต
        location /hls/ {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            alias /var/www/hls/;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Headers *;
        }
    }
}

์ ์šฉ:

sudo nginx -t && sudo systemctl reload nginx

OBS ์„ค์ •

  • ์„œ๋ฒ„: rtmp://<์„œ๋ฒ„IP ๋˜๋Š” ๋„๋ฉ”์ธ>/live
  • ์ŠคํŠธ๋ฆผ ํ‚ค: ์˜ˆ) mystream
    (์ธ์ฆ์„ ๋ถ™์˜€๋‹ค๋ฉด mystream?key=YOURSECRET ์‹์œผ๋กœ)

ํ‘ธ์‹œ๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด HLS๋Š” ๋‹ค์Œ ๊ฒฝ๋กœ์— ์ƒ๊ธด๋‹ค.

  • ๋งˆ์Šคํ„ฐ ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ: http://<์„œ๋ฒ„>/hls/mystream/master.m3u8
  • ๊ฐœ๋ณ„ ๋ ˆ๋ฒจ: /hls/mystream/v0/index.m3u8(1080p), v1(720p), v2(480p)

2. RTMP Ingress

exec๋ฅผ ์“ฐ์ง€ ์•Š๊ณ , ๊ณ ์ • ์ŠคํŠธ๋ฆผ์„ ๋ณ„๋„ ์„œ๋น„์Šค๋กœ ๋Œ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•
์ด๊ฒŒ ํ›จ์”ฌ ๋ณด๊ธฐ๊ฐ€ ์ข‹์Œ.
๋Œ€์ถฉ -p ์˜ต์…˜์œผ๋กœ /usr/local/bin/rtmp2hls.sh ์ž‘์„ฑ

#!/usr/bin/env bash
set -Eeuo pipefail

IN="rtmp://127.0.0.1/live/mystream"   # OBS๊ฐ€ ํ‘ธ์‹œํ•˜๋Š” RTMP
OUTDIR="/var/www/hls/mystream"

mkdir -p "$OUTDIR"
exec /usr/bin/ffmpeg -loglevel error -hide_banner \
  -reconnect 1 -reconnect_streamed 1 -reconnect_on_network_error 1 \
  -i "$IN" \
  -c:v libx264 -preset veryfast -profile:v high -level 4.1 -pix_fmt yuv420p \
  -sc_threshold 0 -g 60 -keyint_min 60 \
  -c:a aac -ar 48000 -ac 2 -b:a 128k \
  -hls_time 2 -hls_list_size 6 \
  -hls_flags delete_segments+program_date_time+independent_segments \
  -f hls -hls_segment_filename "$OUTDIR/seg_%06d.ts" \
  "$OUTDIR/index.m3u8"

๊ถŒํ•œ ์ถ”๊ฐ€

sudo chmod +x /usr/local/bin/rtmp2hls.sh

์„œ๋น„์Šค ํŒŒ์ผ(.ini) ์ž‘์„ฑ

# /etc/systemd/system/rtmp2hls.service
[Unit]
Description=RTMP -> HLS (FFmpeg)
After=network.target nginx.service

[Service]
User=www-data
Group=www-data
ExecStart=/usr/local/bin/rtmp2hls.sh
Restart=always
RestartSec=2
WorkingDirectory=/var/www/hls

[Install]
WantedBy=multi-user.target

๋ฐ๋ชฌ ๋กœ๋“œ ํ›„ ์„œ๋น„์Šค ์ž๋™ ๋“ฑ๋ก ๋ฐ ์‹คํ–‰

sudo systemctl daemon-reload
sudo systemctl enable --now rtmp2hls

3. ์ฒดํฌ๋ฆฌ์ŠคํŠธ

๊ถŒํ•œ: /var/www/hls์— www-data(๋˜๋Š” Nginx/FFmpeg๊ฐ€ ๋„๋Š” ์‚ฌ์šฉ์ž) ์“ฐ๊ธฐ ๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ํ•จ.

๊ฒฝ๋กœ: load_module modules/ngx_rtmp_module.so;๊ฐ€ ์‹คํŒจํ•˜๋ฉด modules ๊ฒฝ๋กœ(๋Œ€๊ฐœ /usr/lib/nginx/modules/)๋ฅผ ํ™•์ธ.

CORS: ์›น ํ”Œ๋ ˆ์ด์–ด์—์„œ ํฌ๋กœ์Šค๋„๋ฉ”์ธ ์š”์ฒญ์ด๋ฉด /hls/์— CORS ํ—ค๋” ์ถ”๊ฐ€(์œ„ ์˜ˆ์‹œ ํฌํ•จ).

ํ‚คํ”„๋ ˆ์ž„ ๊ฐ„๊ฒฉ: ์„ธ๊ทธ๋จผํŠธ ๊ธธ์ด(์˜ˆ: 2์ดˆ)์˜ ์ •์ˆ˜๋ฐฐ๋กœ -g(GOP) ๋งž์ถ”๋Š” ๊ฒƒ์ด ์•ˆ์ •์ .

์„ฑ๋Šฅ: -preset veryfast๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์—ฌ์œ ๋˜๋ฉด faster/fast๋กœ ์˜ฌ๋ฆฌ๊ธฐ.

๋ธŒ๋ผ์šฐ์ € RTMP: ๋ถˆ๊ฐ€. ์›น์€ HLS(๋˜๋Š” LL-HLS/WEBRTC)๋ฅผ ์‚ฌ์šฉ.

profile
ๆ™บ(์ง€)! ๅพท(๋•)! ้ซ”(์ฒด)!

0๊ฐœ์˜ ๋Œ“๊ธ€