Низкая задержка на MediaMTX: чем платит тот, кто уходит с nginx-rtmp
Модуль nginx-rtmp жив, стабилен и держится в продакшене годами без единого падения — но задержка в 5-15 секунд для WebRTC-эпохи выглядит анахронизмом, а сам модуль давно не развивается. MediaMTX обещает задержку в доли секунды через встроенный WebRTC и один бинарник вместо сборки nginx с патчами. Разберём, что вы реально получаете при переходе и чем за это платите — без маркетинга в обе стороны.
Содержание
- Что вообще предлагает каждый из двух серверов
- Задержка: где на самом деле выигрывает MediaMTX
- Установка и первый запуск: binary vs модуль nginx
- Конфигурация: один YAML против директив nginx.conf
- Экосистема и зрелость: то, что теряется при переходе
- Нагрузка и ресурсы: что показывает практика
- Практический план перехода: как не сломать продакшен
- Когда какой сервер выбрать
Что вообще предлагает каждый из двух серверов
nginx-rtmp-module — это модуль для nginx, который добавляет приём и раздачу RTMP-потоков, а заодно умеет транскодировать через ffmpeg exec-директивы и отдавать HLS/DASH через встроенный packager. Разработка модуля официально остановлена ещё в 2020 году, но код настолько прост и стабилен, что это редко становится проблемой на практике — баги в нём давно выловлены сообществом, а конфигурация задокументирована в сотнях статей.
MediaMTX (бывший rtsp-simple-server) — самостоятельный медиасервер на Go, который умеет принимать и отдавать потоки сразу по нескольким протоколам: RTSP, RTMP, HLS, WebRTC и SRT. Ключевое отличие — WebRTC как первоклассный гражданин, а не костыль поверх HLS. Проект активно развивается, релизы выходят регулярно, а конфигурация делается одним YAML-файлом вместо связки nginx.conf с модулями.
Разница философий видна уже на этом уровне: nginx-rtmp — это "добавили стриминг в веб-сервер", MediaMTX — "сделали сервер специально под стриминг и добавили HTTP как побочный протокол". Оба подхода рабочие, но ведут к разным компромиссам ниже.
Задержка: где на самом деле выигрывает MediaMTX
Здесь стоит разделить протоколы, потому что "низкая задержка" MediaMTX — это в первую очередь про WebRTC, а не про магию внутри сервера.
С nginx-rtmp у вас практически всегда HLS на выходе (RTMP как выходной протокол для браузера мёртв — Flash Player похоронили ещё в 2020-м). HLS работает через сегментацию: сервер режет поток на чанки по 2-6 секунд, плеер их скачивает и проигрывает. Даже с агрессивными настройками (hls_fragment 1s, hls_playlist_length 3s вместе с LL-HLS на стороне плеера) вы упрётесь в 3-8 секунд задержки на большинстве связок. Это архитектурный потолок протокола, а не недостаток реализации.
MediaMTX поддерживает тот же HLS с той же задержкой — переход на MediaMTX сам по себе не ускорит HLS-раздачу. Выигрыш появляется, когда зритель подключается по WebRTC: тогда задержка падает до 200-500 миллисекунд (порядок величины, точное число зависит от сети, кодека и клиента — не воспринимайте как гарантию). WebRTC изначально проектировался для видеозвонков, где такая задержка обязательна, и MediaMTX просто переиспользует этот протокол для broadcast-сценария.
Практический вывод: если ваша аудитория смотрит через <video> с HLS.js — разницы в задержке не будет, даже с MediaMTX. Выигрыш реален только там, где вы готовы встроить WebRTC-плеер на сайте или в приложении.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверУстановка и первый запуск: binary vs модуль nginx
MediaMTX распространяется как один статический бинарник без внешних зависимостей:
curl -L -O https://github.com/bluenviron/mediamtx/releases/latest/download/mediamtx_linux_amd64.tar.gz
tar -xzf mediamtx_linux_amd64.tar.gz
sudo mv mediamtx /usr/local/bin/
sudo mv mediamtx.yml /etc/mediamtx.yml
Минимальный конфиг для приёма RTMP и раздачи WebRTC/HLS:
# /etc/mediamtx.yml
rtmp: yes
rtmpAddress: :1935
hls: yes
hlsAddress: :8888
webrtc: yes
webrtcAddress: :8889
paths:
stream:
source: publisher
Systemd-юнит для автозапуска:
# /etc/systemd/system/mediamtx.service
[Unit]
Description=MediaMTX
After=network.target
[Service]
ExecStart=/usr/local/bin/mediamtx /etc/mediamtx.yml
Restart=on-failure
User=mediamtx
[Install]
WantedBy=multi-user.target
С nginx-rtmp путь длиннее: либо собирать nginx из исходников с модулем (штатных пакетов с модулем в базовых репозиториях большинства дистрибутивов нет), либо ставить готовую сборку вроде nginx-full с модулями на Debian/Ubuntu, либо использовать Docker-образ с уже вкомпилированным модулем. Пример сборки из исходников:
apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev git
git clone https://github.com/arut/nginx-rtmp-module.git
wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar -xzf nginx-1.26.2.tar.gz
cd nginx-1.26.2
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module
make -j$(nproc) && sudo make install
Здесь и первая честная потеря: сборка из исходников означает, что обновления безопасности nginx вы либо тащите вручную при каждом релизе, либо застреваете на версии сборки. Пакетный nginx из репозитория обновляется штатным apt upgrade; самосборный — нет.
Конфигурация: один YAML против директив nginx.conf
Конфиг nginx-rtmp живёт внутри блока rtmp {} в nginx.conf и использует ту же директивную модель, что и остальной nginx:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
hls on;
hls_path /var/www/hls;
hls_fragment 3;
hls_playlist_length 60;
# ограничение публикации по ключу
on_publish http://127.0.0.1:8080/auth;
}
}
}
http {
server {
listen 8080;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /var/www;
add_header Cache-Control no-cache;
}
}
}
Для тех, кто уже администрирует nginx как reverse proxy на других сервисах, это плюс: одна и та же ментальная модель, один и тот же процесс перечитывает конфиг (nginx -s reload), один и тот же набор навыков (директивы location, add_header, логирование) переносится на стриминг без обучения с нуля. Если у вас уже настроен nginx как обратный прокси, стоит свериться с материалом про nginx в роли reverse proxy на VPS — многие грабли (перечитывание конфига, кеш заголовков) общие для обоих сценариев.
MediaMTX конфигурируется одним YAML-файлом, где каждый путь (path) описывается декларативно:
paths:
camera1:
source: rtsp://192.168.1.50:554/stream1
sourceOnDemand: yes
live:
# публикация только по токену в query-параметре
publishUser: streamer
publishPass: secret123
all_others:
Это проще для новых пользователей — не нужно знать директивную модель nginx — но означает отдельный синтаксис, отдельную документацию и отдельные грабли, которые не переиспользуются из вашего опыта с nginx. Если в команде уже есть глубокая экспертиза по nginx (кеширование, rate limiting, WAF-правила), она не переносится на MediaMTX автоматически.
Динамическая перезагрузка конфига тоже устроена по-разному: MediaMTX перечитывает файл по SIGHUP или через API без разрыва активных соединений; nginx требует nginx -s reload, который в целом тоже не рвёт активные RTMP-сессии, но проверка синтаксиса (nginx -t) обязательна перед каждым reload — иначе рискуете уронить весь nginx, включая остальные виртуальные хосты на этом сервере.
Экосистема и зрелость: то, что теряется при переходе
Это главная статья расходов при смене инструмента, и именно её проще всего недооценить на старте.
Документация и комьюнити. nginx-rtmp существует с 2012 года. За это время накопились тысячи форумных тредов, Stack Overflow-ответов, блог-постов с разбором конкретных ошибок ("почему HLS-плейлист не обновляется", "как настроить authentication callback"). У MediaMTX документация хорошая и растёт, но объём проверенных временем рецептов для нестандартных ситуаций пока меньше на порядок.
Интеграции. Готовые docker-compose стеки, Kubernetes helm-чарты, Ansible-роли и мониторинговые дашборды (Grafana, Zabbix) исторически написаны под nginx-rtmp — он был стандартом де-факто много лет. Для MediaMTX такие интеграции есть, но их меньше, и часть придётся собирать вручную.
Стабильность конфига. Модуль nginx-rtmp не менялся годами — плюс (нечему ломаться) и следствие остановки разработки одновременно. MediaMTX выпускает релизы регулярно, что хорошо для новых фич, но в проекте случались breaking changes в структуре YAML между мажорными версиями — перед апгрейдом стоит сверяться с CHANGELOG, а не обновлять вслепую на проде.
Multiplexing нагрузки. У nginx-rtmp вы получаете стриминг и обычный HTTP/reverse-proxy в одном процессе — удобно для маленьких проектов, где один сервер и раздаёт сайт, и принимает RTMP. MediaMTX — отдельный процесс, и для отдачи сайта всё равно понадобится nginx или Caddy рядом. Если стоит вопрос выбора веб-сервера, у нас есть отдельное сравнение Caddy и nginx для сервера.
Готовые аналоги под конкретные задачи. Если цель — не универсальный медиасервер, а self-hosted аналог Twitch с чатом и записью эфиров, быстрее и стабильнее будет готовое решение вроде Owncast в Docker Compose, которое уже включает RTMP-приём под капотом.
Нагрузка и ресурсы: что показывает практика
Точных бенчмарков "MediaMTX держит X зрителей, nginx-rtmp держит Y" в этой статье не будет — на сравнение сильно влияет железо, битрейт, кодек, включено ли транскодирование и сеть между сервером и зрителями, и любая конкретная цифра без контекста конкретного окружения будет вводить в заблуждение. Ориентируйтесь на нагрузочное тестирование в вашей собственной конфигурации, а не на числа из статей в интернете.
Что можно сказать про архитектурные различия:
- nginx-rtmp — модуль внутри worker-based модели nginx. Раздача HLS через
location— по сути обычная отдача статики, которая масштабируется предсказуемо черезworker_processesиworker_connections. Транскодирование черезexec ffmpegупирается в CPU транскодера, а не в сам nginx. - MediaMTX написан на Go и использует горутины для параллельной обработки соединений — модель, которая неплохо утилизирует несколько ядер без ручной настройки worker'ов. WebRTC-раздача добавляет накладные расходы на ICE/STUN-негоциацию и шифрование (DTLS-SRTP) для каждого зрителя отдельно, в отличие от HLS, где один сегмент раздаётся всем без пересчёта.
Если у вас узкое место — не сам сервер раздачи, а транскодирование потока в несколько битрейтов, оба сервера в конечном счёте зовут внешний ffmpeg-процесс, и разница между ними в этой части нагрузки минимальна. Ключевой ресурс здесь — не выбор медиасервера, а мощность CPU (или GPU при аппаратном кодировании) под транскодирование.
Практический план перехода: как не сломать продакшен
Если вы решаете мигрировать с работающего nginx-rtmp на MediaMTX, не делайте это одним шагом на проде.
- Поднимите MediaMTX параллельно на другом порту — RTMP на 1935 уже занят nginx, временно используйте 1936 для тестового инстанса, чтобы не трогать боевой поток.
- Продублируйте публикацию потока через OBS Studio или ffmpeg на оба сервера одновременно (
ffmpeg -i input -c copy -f flv rtmp://host:1935/live/stream -f flv rtmp://host:1936/live/stream), чтобы сравнить задержку и стабильность на реальном трафике без риска для зрителей. - Протестируйте нагрузку с реалистичным числом одновременных зрителей — через постепенный перевод небольшой части живой аудитории, а не только синтетическими скриптами.
- Проверьте специфичные функции: авторизацию публикации по токену, запись на диск, вебхуки при старте/остановке — у MediaMTX это
runOnPublish/runOnReady, у nginx-rtmp —on_publish/exec. Синтаксис разный, логика переносимая, но переписывать придётся руками. - Держите nginx-rtmp как fallback минимум пару недель после переключения основного трафика — откат должен занимать минуты, а не часы пересборки.
- Перепишите мониторинг. Алерты на число активных RTMP-сессий через
stat-модуль nginx-rtmp (XML на отдельном location) не работают с MediaMTX — там свой HTTP API (/v3/paths/list) с другим форматом ответа.
Для базовой отказоустойчивости самого VPS под систему на этом этапе не помешает свериться с общими принципами настройки Docker Compose для продакшена — политики перезапуска и healthcheck пригодятся вне зависимости от того, какой медиасервер вы в итоге выбрали.
Когда какой сервер выбрать
Сведём выбор к практическим сценариям, а не к абстрактному "что лучше".
| Сценарий | Рекомендация | Почему |
|---|---|---|
| Нужен near-realtime (интерактивный стрим, аукцион, торги, видеозвонок с broadcast) | MediaMTX | WebRTC даёт задержку в доли секунды, HLS с этим не справится в принципе |
| Обычная трансляция для зрителей через веб-плеер (HLS достаточно) | nginx-rtmp, если уже работает | Задержка одинаковая, а стабильность и документация у nginx-rtmp выше |
| Нужен RTSP от IP-камер плюс раздача наружу | MediaMTX | Нативная поддержка RTSP на вход и выход без костылей |
| Один сервер должен и стримить, и быть reverse proxy для сайта | nginx-rtmp | Меньше движущихся частей, один процесс на два дела |
| Команда уже глубоко знает nginx и его экосистему | nginx-rtmp | Экспертиза переносится напрямую, ниже риск простоя от незнакомых граблей |
| Новый проект с нуля, без legacy-конфигов | MediaMTX | Проще стартовать, активная разработка, меньше избыточности в стеке |
| Критична многолетняя предсказуемость без сюрпризов в апгрейдах | nginx-rtmp | Модуль не меняется, меньше риска breaking changes |
Гибридный вариант тоже жизнеспособен: держать nginx-rtmp как основной приёмник RTMP от энкодера (OBS, vMix) и параллельно поднять MediaMTX только для WebRTC-раздачи той группе зрителей, которым критична задержка. Это добавляет процесс в инфраструктуру, но не требует полного отказа от проверенной схемы.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли настроить низкую задержку на nginx-rtmp без перехода на MediaMTX?
Частично — уменьшением hls_fragment до 1 секунды и включением LL-HLS на стороне плеера можно снизить задержку HLS до 3-5 секунд, но настоящий near-realtime (доли секунды) требует WebRTC, которого в самом nginx-rtmp нет — только через сторонние надстройки.
MediaMTX поддерживает запись потоков на диск?
Да, через параметр record: yes и настройку пути записи в конфиге path — аналог record on в nginx-rtmp, но с другими опциями сегментации файлов.
Нужен ли отдельный STUN/TURN-сервер для WebRTC в MediaMTX?
Для локальной сети и большинства прямых подключений хватает встроенного ICE-агента MediaMTX, но если зрители сидят за симметричным NAT или строгим корпоративным файрволом, потребуется внешний TURN-сервер (например, coturn) — без него часть подключений просто не установится.
Совместим ли MediaMTX с OBS Studio и другими энкодерами?
Да, приём RTMP в MediaMTX работает с любым RTMP-энкодером без изменений на стороне энкодера — переключение точки публикации это просто смена адреса сервера в настройках вывода.
Что произойдёт, если конфиг nginx-rtmp содержит синтаксическую ошибку после правки?
nginx -s reload откажется применять изменения и оставит старый рабочий конфиг активным, если не выполнить предварительно nginx -t — но безопаснее всегда проверять синтаксис перед reload вручную, чтобы не столкнуться с падением при следующем полном перезапуске.
Можно ли одновременно принимать RTMP и раздавать HLS на MediaMTX без транскодирования?
Да, при совместимых кодеках (обычно H.264/AAC) MediaMTX ретранслирует поток без перекодирования — как и nginx-rtmp, он не делает транскодинг сам, а вызывает внешний ffmpeg только если вы явно это настроили.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →