Сервер онлайн-мовлень на базі nginx

Складання та налаштування nginx-rtmp

Для додавання модуля nginx-rtmp до nginx потрібно вказати його в опції --add-module при конфігурації nginx, як будь-який інший модуль.

Після складання та інсталяції потрібно додати секцію rtmp<> файл конфігурації nginx.conf. Додавати її треба в корінь конфігу. Наприклад:

Для багатьох випадків цієї простої конфігурації буде достатньо. У ній задається RTMP-додаток з ім'ям myapp. У цю програму ми пізніше публікуватимемо потоки і програватимемо їх з нього. Кожен поток також матиме своє унікальне ім'я. Варто відзначити один важливий аспект, що стосується наведеної вище зміни. Вона вірна для того випадку, коли число воркерів nginx дорівнює одиниці (зазвичай, задається на початку nginx.conf).

Щоб мати можливість використовувати live мовлення з більшим числом воркерів, потрібно вказати директиву rtmp_auto_push on (див. розділ «Воркери та локальна ретрансляція»).

Публікація та відтворення живого потоку

Тут треба врахувати, що RTMP підтримує обмежений набір кодеків, втім такі популярні кодеки, як H264 і AAC, входять до їх числа. Якщо кодеки в тестовому файлі не сумісні з RTMP, потрібно перекодувати:

Приклад мовлення з локальної веб-камери:

Програти потік можна за допомогою ffplay наступною командою:

І, нарешті, простий приклад використання JWPlayer для програвання потоку з браузера (цілком наведено в директорії /test/www модуля):

Відео на запит

При програванні, відповідно, треба вказувати імена файлів, в іншому все аналогічно до живого мовлення.

Ретрансляція

При побудові розподілених систем важливо мати можливість ретрансляції потоків для балансування навантаження по великому числу серверів. Модуль реалізує два типиретрансляції: push та pull. Перший тип ретрансляції полягає у передачі віддалений сервер локально публікованого потоку, а другий — передачі віддаленого потоку на локальний сервер. Приклад push ретрансляції:

Pull-ретрансляції виконують зворотну операцію:

У цьому прикладі з появою клієнта, який бажає локально програти потік rtmp://localhost/myapp/mystream, буде створено з'єднання з rtmp://cdn.example.com/myapp/mytstream і віддалений потік буде ретрансльований на локальний сервер, після чого стане доступним для всіх локальних клієнтів. У той момент, коли не залишиться жодного клієнта, з'єднання буде завершено.

Мовлення на мобільні пристрої (HLS)

Для мовлення на пристрої iPhone/iPad, а також на нові версії Android, використовується протокол HLS (HTTP Live Streaming). Протокол був розроблений компанією Apple і представляє собою «нарізаний» на шматки MPEG-TS/H264/AAC потік, що віддається по HTTP. До потоку додається плейлист у форматі m3u8. Віддавати HTTP nginx вміє добре. Отже, треба лише створити та оновлювати плейлист та фрагменти HLS-потоку, а також стежити за видаленням старих фрагментів. Існує модуль nginx-rtmp-hls. Він знаходиться в директорії hls, проте не збирається за замовчуванням, тому що це не так. вимагає бібліотеки libavformat, що входить у пакет ffmpeg. Для складання nginx з підтримкою HLS треба додати цей модуль явно при конфігурації:

Так сталося, що деякий час тому проект ffmpeg був форкнутий. І тепер у нас є два проекти — ffmpeg та avconv, а отже, відразу почали виникати проблеми сумісності (вірніше, несумісності) бібліотек. Для складання nginx-rtmp потрібен оригінальний ffmpeg. У той же час деякі дистрибутиви Linux перейшли на використання avconv, який для складання не підійде. На цей випадок янаписав докладну інструкцію.

Для генерації HLS достатньо вказати такі директиви:

Ну і, нарешті, в секції http<>, налаштувати віддачу всього, що пов'язано з HLS:

Зазначу, що для програвання iPhone потік повинен бути закодований в H264 і AAC. Якщо вихідний потік відповідає цим умовам, необхідно налаштувати перекодування.

Перекодування

Воркери та локальна ретрансляція

Як відомо, nginx є однопотоковим сервером. Для того, щоб ефективно використовувати всі ядра сучасних процесорів, він зазвичай запускається в кілька воркерів. Обробка HTTP запитів зазвичай відбувається незалежно один від одного, і лише в окремих випадках (як, наприклад, у випадку з кешем), потрібно здійснювати доступ до загальних даних. Такі дані зберігаються в пам'яті, що розділяється.

За живого мовлення ситуація інша. Усі клієнтські з'єднання, що програють потік, очевидно залежать від з'єднання, що публікує цей потік. Використання пам'яті, що розділяється, в даному випадку неефективно, зайве трудомістко, призвело б до синхронізації і великої втрати продуктивності. Тому для використання кількох воркерів було реалізовано механізм внутрішніх ретрансляцій через UNIX-сокети. Власне такі ретрансляції практично нічим не відрізняються від звичайних зовнішніх push-ретрансляцій. Локальні ретрансляції включаються наступною директивою

Вказувати її треба в кореневій секції конфігураційного файлу. Зазначу, що локальні ретрансляції потрібні лише живих мовлень.

Запис відбувається у форматі flv директорію /tmp/rec.

Керувати записом можна в ручному режимі, включаючи та вимикаючи його за допомогою http-запиту. Для цього використовується control-модуль. Інформацію про нього можна знайти на веб-сайті проекту.

Авторизація та бізнес-логіка

Статистика

Кожного часу до вашого сервера можуть бути підключені тисячі клієнтів. Природно, потрібен інтерфейс, що дозволяє побачити їх список, а також всі основні характеристики потоків, що публікуються або програються ними. Причому важливо, щоб цю інформацію можна як аналізувати візуально, так і обробляти програмно. Такий інтерфейс модуля nginx-rtmp існує. Щоб його використовувати, необхідно у http-секції nginx.conf прописати такі директиви.

Директива rtmp_stat включає віддачу XML-документа з повним описом live-клієнтів, що публікують або програють потоки, списком додатків та серверів. Цей документ зручний для програмної обробки, але для візуального аналізу не годиться. Щоб мати можливість переглядати список клієнтів у браузері, директивою rtmp_stat_stylesheet задається відносний шлях до таблиці стилів XML (stat.xsl). Цей файл лежить у корені проекту. Потрібно налаштувати nginx на його роздачу за вказаним урлом. Результат можна переглядати у браузері.

Існує можливість явно розривати клієнтські з'єднання. Для цього використовується control-модуль, який не описаний у статті.

Просте Інтернет-радіо

Сумісність

Модуль сумісний з усім основним софтом, що працює з протоколом RTMP, включаючи FMS/FMLE, Wowza, Wirecast, протестований з найпоширенішими флеш-програвачами JWPlayer, FlowPlayer, StrobeMediaPlayback, а також працює з ffmpeg/avconv і rtmpdump.

Модуль використовує однопоточну асинхронну модель сервера nginx. Це дозволяє досягти високої продуктивності. Ми використовуємо модуль на машинах Intel Xeon E5320/E5645 як один воркер. У цьому режимі вдається досягти максимальної пропускної спроможностінаявних мережевих карток - 2Gbps. Користувачі модуля підтверджують збереження цього ж співвідношення (2Gbps на ядро) у режимі локальної ретрансляції з кількома воркерами. Практика показує, що продуктивність мовника зазвичай упирається в мережу, а не в CPU.

Прямих порівнянь з іншими продуктами я не проводив, проте, «важкі» багатопотокові FMS, Wowza і Red5, будучи більш функціональними, повинні в силу особливостей реалізації суттєво програвати моєму рішенню за кількістю одночасно приєднаних клієнтів і навантаження на CPU. Це підтверджується багатьма користувачами, які проводили такі порівняння, зокрема. у вже згаданій мною статті.

Висновок

  • Сторінка проекту на гітхабі github.com/arut/nginx-rtmp-module.
  • Повний опис директив із прикладами github.com/arut/nginx-rtmp-module/wiki/Directives.
  • Блог, куди я пишу про нові версії, багфікси і новий функціонал rarut.wordpress.com.
  • Гугл-групи, де відповідаю на запитання та обговорюю з користувачами модуля проблеми groups.google.com/group/nginx-rtmp і groups.google.com/group/nginx-rtmp-ru.

Радий, якщо читачам Хабра проект здасться цікавим.