Модуль RTMP в Nginx: Пошаговая настройка сервера стриминга | AdminWiki

Модуль RTMP в Nginx: Пошаговая настройка сервера стриминга

26 июля 2026 10 мин. чтения

Введение: зачем нужен собственный RTMP-сервер

Собственный сервер стриминга на базе Nginx с модулем RTMP дает полный контроль над видеоинфраструктурой. Вы не зависите от тарифов облачных платформ, не платите лицензионные отчисления за каждый канал и получаете минимальную задержку сигнала, так как трафик не покидает ваш дата-центр. Это легковесное решение принимает RTMP-потоки от энкодеров, ретранслирует их зрителям и конвертирует в HLS или DASH для браузеров.

В этом руководстве разберем полный цикл: установку Nginx с модулем RTMP из репозитория и сборку из исходников, базовую конфигурацию для приема потока, преобразование в HLS и DASH, ограничение доступа по IP и ключам, мониторинг активных стримов через встроенную stat-страницу. В конце соберем итоговый конфиг, готовый к продакшн-эксплуатации.

Материал ориентирован на системных администраторов и DevOps-инженеров, которые хотят развернуть надежную платформу для прямых трансляций без привязки к вендорским сервисам. Все примеры проверены на Ubuntu 24.04 LTS и актуальны на июль 2026 года.

Установка Nginx с модулем RTMP

Модуль RTMP не входит в стандартную сборку Nginx. Установить его можно двумя способами: из предсобранных пакетов (быстрый путь для Ubuntu/Debian) или компиляцией из исходников (универсальный метод для любого дистрибутива).

Установка из репозитория

В Ubuntu 24.04 LTS пакет libnginx-mod-rtmp доступен в официальном репозитории. Установка выполняется одной командой:

sudo apt update
sudo apt install nginx libnginx-mod-rtmp -y

После завершения проверьте, что модуль загружен:

nginx -V 2>&1 | grep -o rtmp

Если вывод содержит rtmp, модуль активен. Для CentOS Stream 10 и RHEL-подобных систем предсобранных пакетов нет, поэтому переходите к сборке из исходников.

Сборка из исходников

Сборка из исходников дает полную свободу в выборе версий Nginx и модуля. Сначала установите зависимости для компиляции:

sudo apt install build-essential libpcre3-dev libssl-dev zlib1g-dev git -y

Загрузите исходники Nginx (версия 1.26.x стабильна на 2026 год) и модуль RTMP:

wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar xzf nginx-1.26.2.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git

Сконфигурируйте сборку с флагом --add-module:

cd nginx-1.26.2
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid \
  --add-module=../nginx-rtmp-module
make
sudo make install

Создайте systemd-юнит для управления сервисом:

sudo tee /etc/systemd/system/nginx.service <<EOF
[Unit]
Description=Nginx with RTMP module
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/usr/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now nginx

Проверьте статус: sudo systemctl status nginx. Сервер готов к настройке.

Базовая конфигурация: прием и раздача RTMP-потока

Конфигурация RTMP задается в отдельном блоке rtmp {} внутри nginx.conf. Этот блок работает параллельно с http {} и не пересекается с ним на уровне логики.

Создание RTMP-приложения

Откройте /etc/nginx/nginx.conf и добавьте блок RTMP перед блоком HTTP:

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record off;
        }
    }
}

Директива listen 1935 указывает стандартный порт для RTMP-трафика. chunk_size 4096 задает размер фрагмента данных в байтах - значение 4096 оптимально для большинства сетей. Внутри application live параметр live on включает режим прямой трансляции, а record off отключает запись на диск.

URL для публикации формируется как rtmp://ваш_сервер/live/streamkey, где live - имя приложения, streamkey - произвольный ключ трансляции. Этот же URL используется зрителями для воспроизведения.

После изменения конфига проверьте синтаксис и перезагрузите Nginx:

sudo nginx -t
sudo systemctl reload nginx

Тестирование с OBS и VLC

Откройте OBS Studio, перейдите в «Настройки» → «Вещание». Выберите службу «Custom», в поле «Сервер» укажите rtmp://192.168.1.100/live, в поле «Ключ потока» - test. Нажмите «Начать вещание».

Для проверки откройте VLC Media Player: «Медиа» → «Открыть URL» → rtmp://192.168.1.100/live/test. Если поток отображается, сервер настроен верно.

Типичные ошибки на этом этапе: порт 1935 закрыт файрволом (проверьте sudo ufw status), неправильный IP-адрес сервера, опечатка в ключе потока. Убедитесь, что OBS использует программное кодирование x264 - аппаратные кодеры иногда выдают поток, несовместимый с модулем RTMP без транскодинга.

Конвертация RTMP в HLS и DASH для веб-плееров

RTMP не поддерживается современными браузерами. Чтобы зрители смотрели трансляцию без Flash, нужно на лету конвертировать поток в HLS (HTTP Live Streaming) или DASH (Dynamic Adaptive Streaming over HTTP). Модуль RTMP делает это автоматически при поступлении входящего потока.

Настройка HLS

Добавьте в application live директивы HLS:

application live {
    live on;
    record off;

    hls on;
    hls_path /var/www/hls;
    hls_fragment 3s;
    hls_playlist_length 30s;
}

hls on включает генерацию HLS-сегментов. hls_path задает директорию для файлов - создайте ее и назначьте права:

sudo mkdir -p /var/www/hls
sudo chown -R www-data:www-data /var/www/hls

hls_fragment 3s определяет длительность одного TS-сегмента. Значение 3 секунды - компромисс между задержкой и стабильностью. hls_playlist_length 30s задает длину плейлиста: 30 секунд означают, что в .m3u8 хранится 10 последних сегментов.

Для раздачи HLS через HTTP добавьте location в блок http {}:

http {
    server {
        listen 80;

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

Теперь HLS-поток доступен по адресу http://ваш_сервер/hls/test.m3u8. Для встраивания в веб-страницу используйте HTML5-плеер:

<video controls>
  <source src="http://192.168.1.100/hls/test.m3u8" type="application/vnd.apple.mpegurl">
</video>

Настройка DASH

DASH добавляется аналогично. Расширьте application:

application live {
    live on;
    record off;

    hls on;
    hls_path /var/www/hls;
    hls_fragment 3s;
    hls_playlist_length 30s;

    dash on;
    dash_path /var/www/dash;
    dash_fragment 3s;
}

Создайте директорию и настройте права:

sudo mkdir -p /var/www/dash
sudo chown -R www-data:www-data /var/www/dash

В HTTP-блоке добавьте location для DASH:

location /dash {
    alias /var/www/dash;
    add_header Cache-Control no-cache;
    add_header Access-Control-Allow-Origin *;
    types {
        application/dash+xml mpd;
        video/mp4 m4v;
    }
}

DASH-манифест доступен по http://ваш_сервер/dash/test.mpd. Обратите внимание: DASH требует инициализационный сегмент, который модуль генерирует автоматически. CORS-заголовок Access-Control-Allow-Origin обязателен для кросс-доменных запросов от плееров.

Ограничение доступа к стримам

Открытый RTMP-сервер позволяет любому, кто знает URL, начать вещание или смотреть чужой поток. Базовые механизмы защиты встроены в модуль и не требуют внешних сервисов.

Защита публикации по IP и ключу

Ограничьте круг IP-адресов, которым разрешена публикация:

application live {
    live on;
    record off;

    allow publish 192.168.1.0/24;
    allow publish 10.0.0.100;
    deny publish all;
}

allow publish разрешает публикацию с указанных адресов или подсетей, deny publish all блокирует все остальные. Аналогично работает allow play / deny play для зрителей.

Дополнительный уровень - уникальный ключ потока. Используйте сложные, непредсказуемые значения: rtmp://server/live/a7f3b9c2e1d4_studio1. Без знания ключа публикация невозможна.

Аутентификация через внешний скрипт

Директива on_publish отправляет HTTP-запрос к вашему бэкенду при каждой попытке начать вещание. Бэкенд возвращает HTTP 200 для разрешения или 403 для запрета:

application live {
    live on;
    record off;
    on_publish http://127.0.0.1:5000/auth;
}

Модуль передает параметры в URL: ?call=publish&name=test&addr=192.168.1.50. Простейший обработчик на Python/Flask:

from flask import Flask, request
app = Flask(__name__)

@app.route('/auth')
def auth():
    key = request.args.get('name')
    if key == 'valid_key':
        return '', 200
    return '', 403

Этот механизм интегрируется с любой системой авторизации: проверяйте ключи в базе данных, валидируйте JWT-токены, логируйте попытки подключения.

Мониторинг активных стримов

Модуль RTMP предоставляет встроенную страницу статистики в формате XML. Она показывает активные публикации, количество зрителей, битрейт и время работы каждого потока.

Включение и настройка stat-страницы

Добавьте в HTTP-блок location с директивой rtmp_stat:

http {
    server {
        listen 80;

        location /stat {
            rtmp_stat all;
            allow 192.168.1.0/24;
            deny all;
        }
    }
}

Откройте http://ваш_сервер/stat в браузере. Вы увидите XML с секциями <server>, <application>, <live>, <stream> и <client>. Для каждого потока указаны: имя, время запуска, входящий битрейт, количество подключенных зрителей.

Для быстрой проверки из командной строки используйте curl:

curl -s http://127.0.0.1/stat | grep -oP '(?<=name=")([^"]+)' | head -5

Интеграция с внешними системами мониторинга

XML-статистику легко парсить скриптами для передачи в Prometheus или Zabbix. Пример парсера на Python, который отдает метрики в формате Prometheus:

import xml.etree.ElementTree as ET
import requests

resp = requests.get('http://127.0.0.1/stat')
root = ET.fromstring(resp.text)

for stream in root.iter('stream'):
    name = stream.find('name').text
    bw_in = stream.find('bw_in').text
    print(f'rtmp_bw_in{{stream="{name}"}} {bw_in}')

На основе этих данных настройте алерты: отсутствие ожидаемого потока более 60 секунд, падение входящего битрейта ниже порога, аномальный рост числа зрителей. Подробнее о настройке мониторинга Nginx читайте в руководстве по мониторингу с Prometheus и Grafana.

Продвинутые возможности: запись, ретрансляция и exec

Модуль RTMP не ограничивается приемом и раздачей. Три функции закрывают большинство потребностей продакшн-среды: автоматическая запись эфиров, ретрансляция на другие серверы и запуск внешних скриптов по событиям.

Запись прямых эфиров

Включите запись всех входящих потоков:

application live {
    live on;
    record all;
    record_path /var/recordings;
    record_unique on;
}

record all сохраняет каждый поток. record_path задает директорию. record_unique on добавляет временную метку к имени файла, предотвращая перезапись. Файлы сохраняются в формате FLV. Для ротации старых записей добавьте cron-задачу: find /var/recordings -name "*.flv" -mtime +7 -delete удаляет файлы старше 7 дней.

Ретрансляция на другие серверы

Директива push отправляет копию потока на удаленный RTMP-сервер. Это основа распределенной доставки:

application live {
    live on;
    push rtmp://cdn-server.example.com/live;
}

Для приема потока с другого сервера используйте pull:

application relay {
    live on;
    pull rtmp://origin-server.example.com/live key=streamkey;
}

В связке push/pull строится иерархия: origin-сервер принимает поток от энкодера, edge-серверы забирают его через pull и раздают зрителям. Это снижает нагрузку на origin и уменьшает задержку для географически распределенной аудитории.

Типичные проблемы и их решение

При настройке RTMP-сервера администраторы сталкиваются с повторяющимся набором ошибок. Разберем их с готовыми решениями.

Проблемы с сетью и файрволом

Порт 1935 не отвечает. Самая частая причина - файрвол. Проверьте правила:

sudo ufw allow 1935/tcp
sudo ufw reload

Для iptables: sudo iptables -A INPUT -p tcp --dport 1935 -j ACCEPT. Если сервер за NAT, настройте проброс порта на маршрутизаторе.

Ошибка 403 при публикации. Проверьте директивы allow publish / deny publish. Убедитесь, что IP энкодера попадает в разрешенную подсеть. Если используется on_publish, проверьте доступность бэкенда: curl http://127.0.0.1:5000/auth?call=publish&name=test должен вернуть 200.

HLS не проигрывается в браузере. Проверьте права на директорию hls_path: владелец должен быть www-data. Убедитесь, что MIME-типы .m3u8 и .ts прописаны в location. Проверьте CORS-заголовки - без Access-Control-Allow-Origin плеер на другом домене не загрузит поток.

Ошибки конфигурации и кодирования

Синтаксические ошибки в nginx.conf. Перед перезагрузкой всегда выполняйте sudo nginx -t. Вывод укажет строку с ошибкой.

Высокая задержка HLS. Уменьшите hls_fragment до 2 секунд и hls_playlist_length до 10 секунд. Учтите, что слишком короткие фрагменты увеличивают накладные расходы на HTTP-запросы.

Поток не стартует в плеере. Модуль RTMP требует ключевые кадры (I-frames) не реже чем раз в 2 секунды. В OBS настройте «Интервал ключевых кадров» на 2 секунды. Без этого HLS-плейлист не сформируется корректно.

Для углубленного анализа логов и отладки ошибок рекомендуем практическое руководство по анализу логов Nginx.

Заключение: итоговый конфиг и дальнейшие шаги

Ниже приведен полный nginx.conf, объединяющий все рассмотренные функции: прием RTMP, генерацию HLS и DASH, ограничение доступа, мониторинг и запись. Скопируйте его, замените IP-адреса на свои и запускайте в продакшн.

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record all;
            record_path /var/recordings;
            record_unique on;

            allow publish 192.168.1.0/24;
            deny publish all;

            hls on;
            hls_path /var/www/hls;
            hls_fragment 3s;
            hls_playlist_length 30s;

            dash on;
            dash_path /var/www/dash;
            dash_fragment 3s;
        }
    }
}

http {
    include mime.types;
    default_type application/octet-stream;

    server {
        listen 80;
        server_name _;

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

        location /dash {
            alias /var/www/dash;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
            types {
                application/dash+xml mpd;
                video/mp4 m4v;
            }
        }

        location /stat {
            rtmp_stat all;
            allow 192.168.1.0/24;
            deny all;
        }
    }
}

Куда двигаться дальше. Добавьте транскодинг через FFmpeg: модуль RTMP передает поток на вход FFmpeg, тот перекодирует его в несколько битрейтов и возвращает обратно в другое приложение. Это даст адаптивный битрейт для HLS и DASH. Настройте CDN на основе edge-серверов с pull-ретрансляцией для масштабирования на тысячи зрителей. Интегрируйте on_publish с корпоративной SSO-системой для сквозной аутентификации стримеров.

Для защиты сервера от сетевых атак на уровне HTTP изучите руководство по защите Nginx от DDoS. Если вы используете Nginx как балансировщик нагрузки для веб-приложений, пригодится практическое руководство по reverse proxy и балансировке.

Поделиться:
Сохранить гайд? В закладки браузера