Table of Contents

Servidor de RTMP con nginx

Fichero nginx.conf

daemon off;

error_log /dev/stdout info;

events {
    worker_connections 1024;
}

rtmp {
    server {
        listen 1935;
        chunk_size 4000;

        application stream {
            live on;

            exec ffmpeg -i rtmp://localhost:1935/stream/$name
              -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 2500k -f flv -g 30 -r 30 -s 1280x720 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_720p2628kbs
              -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 1000k -f flv -g 30 -r 30 -s 854x480 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_480p1128kbs
              -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 750k -f flv -g 30 -r 30 -s 640x360 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_360p878kbs
              -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 400k -f flv -g 30 -r 30 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p528kbs
              -c:a libfdk_aac -b:a 64k -c:v libx264 -b:v 200k -f flv -g 15 -r 15 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p264kbs;
        }

        application hls {
            live on;
            hls on;
            hls_fragment_naming system;
            hls_fragment 5;
            hls_playlist_length 10;
            hls_path /opt/data/hls;
            hls_nested on;

            hls_variant _720p2628kbs BANDWIDTH=2628000,RESOLUTION=1280x720;
            hls_variant _480p1128kbs BANDWIDTH=1128000,RESOLUTION=854x480;
            hls_variant _360p878kbs BANDWIDTH=878000,RESOLUTION=640x360;
            hls_variant _240p528kbs BANDWIDTH=528000,RESOLUTION=426x240;
            hls_variant _240p264kbs BANDWIDTH=264000,RESOLUTION=426x240;
        }
    }
}

http {
    root /www/static;
    sendfile off;
    tcp_nopush on;
    server_tokens off;
    access_log /dev/stdout combined;

    # Uncomment these lines to enable SSL.
    # ssl_protocols TLSv1.2 TLSv1.3;
    # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    # ssl_prefer_server_ciphers off;
    # ssl_session_cache shared:SSL:10m;
    # ssl_session_timeout 1d;

    server {
        listen 80;

        # Uncomment these lines to enable SSL.
        # Update the ssl paths with your own certificate and private key.
            
        # listen 443 ssl;
        # ssl_certificate     /opt/certs/example.com.crt;
        # ssl_certificate_key /opt/certs/example.com.key;

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /opt/data;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        location /live {
          alias /opt/data/hls;
          types {
              application/vnd.apple.mpegurl m3u8;
              video/mp2t ts;
          }
          add_header Cache-Control no-cache;
          add_header Access-Control-Allow-Origin *;
        }

        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root /www/static;
        }

        location /crossdomain.xml {
            default_type text/xml;
            expires 24h;
        }
    }
}

Ejecutamos docker

docker run -d \
    -p 1935:1935 \
    -p 8080:80 \
    -v ~/nginx-rtmp/nginx.conf:/etc/nginx/nginx.conf \
    --name rtmp-server \
    alfg/nginx-rtmp

Enviar vídeo a RTMP

ffmpeg -re -i video.mp4 -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -c:a aac -ar 44100 -b:a 128k -f flv rtmp://localhost:1935/stream/test

Ver vídeo en servidor

http://localhost:8080/live/test.m3u8

En el directorio /opt/data/hls del docker están los vídeos

docker exec -it rtmp-server /bin/sh
/ # ls /opt/data/hls
test.m3u8         test_240p264kbs   test_240p528kbs   test_360p878kbs   test_480p1128kbs  test_720p2628kbs

Podemos crear un player en el servidor, en /www/static/player.html entonces lo podemos ver en: http://localhost:8080/player.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HLS Stream Player</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <style>
        body {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            background-color: #000;
        }
        video {
            width: 80%;
            max-width: 800px;
        }
    </style>
</head>
<body>
    <video id="video" controls autoplay></video>
    <script>
        const video = document.getElementById('video');
        const videoSrc = 'http://localhost:8080/live/test_240p264kbs/index.m3u8'; // URL de la calidad deseada

        if (Hls.isSupported()) {
            const hls = new Hls();
            hls.loadSource(videoSrc);
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                video.play();
            });
        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = videoSrc;
            video.addEventListener('loadedmetadata', () => {
                video.play();
            });
        }
    </script>
</body>
</html>

Configurar proxy RTMP a proxy RTSP

Con el docker de rtmp no acaba de funcionar.

Pero con este software si. Paramos el docker y descargamos este software:
https://github.com/bluenviron/mediamtx/releases

Lo descomprimimos y lo ejecutamos:

./mediamtx 
2024/11/10 15:58:59 INF MediaMTX v1.9.3
2024/11/10 15:58:59 INF configuration loaded from /home/jose/streaming/mediamtx.yml
2024/11/10 15:58:59 INF [RTSP] listener opened on :8554 (TCP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
2024/11/10 15:58:59 INF [RTMP] listener opened on :1935
2024/11/10 15:58:59 INF [HLS] listener opened on :8888
2024/11/10 15:58:59 INF [WebRTC] listener opened on :8889 (HTTP), :8189 (ICE/UDP)
2024/11/10 15:58:59 INF [SRT] listener opened on :8890 (UDP)

Y ahora emitimos el vídeo al servidor rtmp:

ffmpeg -re -i video.mp4 -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -c:a aac -ar 44100 -b:a 128k -f flv rtmp://localhost:1935/stream/test

Y creamos el proxy:

ffmpeg -i rtmp://localhost:1935/stream/test -c:v copy -c:a copy -f rtsp rtsp://localhost:8554/live

Ahora podemos configurar OBS en la dirección:

rtsp://localhost:8554/live