Что такое онлайн-видео?
Под термином онлайн-видео я понимаю длительное вещание какого-то живого видеосигнала (к примеру, из телестудии). Традиционные средства отдачи видео (flv- и mp4-стриминг) в данном случае не работают, просто потому что файла, содержащего весь видеопоток, не существует.
В этой статье речь будет идти не об организации видеохостинга, а об организации видеовещания в прямом эфире. Это две принципиально разные задачи, и обычно способы их решения существенно отличаются друг от друга.
RTMP-протокол
RTMP — Real Time Messaging Protocol (вики) — протокол, который обычно используется для раздачи живого видео- и аудиоконтента клиентам. Он удобен тем, что в AS3 есть его поддержка из коробки, требует не слишком много ресурсов на клиенте и поддерживает множество плюшек (например, трансляцию с переменными битрейтами и переключение клиентов на более высокое качество при наличии свободного канала).
NB: Помимо RTMP существует набор других протоколов вещания медиапотоков (RTSP, Apple HTTP Live Streaming и др.), но в этой статье они не рассматриваются.
Протокол RTMP — детище компании Adobe. Единственным официальным сервером, которым можно вещать RTMP-поток, является Adobe Flash Media Server. Его цена и производительность, к сожалению, оставляют желать лучшего, поэтому различными разработчиками были предприняты попытки создать более или менее совместимые альтернативные реализации протокола. К сожалению, у RTMP-протокола есть известные проблемы с лицензированием, к примеру, его официальная спецификация, если следовать ей строго, не позволяет написать работающий RTMP-сервер. Тем не менее, существует несколько реализаций:
- Red5 — один из первых RTMP-серверов, написан на Java
- Wowza — проприетарный RTMP-сервер, написан на Java. Помимо RTMP, поддерживает также RTSP, Apple HLS, и Smoothstreaming (Silverlight)
- erlyvideo — проприетарный RTMP-сервер (есть и бесплатная версия), написан на Erlang. Проект пишется русскими программистами и активно развивается.
Java тормозит
В тестах, которые я проводил, Red5 и Wowza показали неприлично низкую производительность. При мегабитном видеопотоке Wowza при 1000 зрителей онлайн съедала уже около 300% процессорного времени (Intel Xeon E5607). Если требуется вещать хотя бы для 20000 человек онлайн, то нужно закупать 20 серверов? Это слишком дорого.
Что же делать?
Использовать неблокирующие операции. Тормоза в Wowza и Red5 следуют из-за далеко не самой оптимальной схемы обработки событий. Для реализации действительно быстрого стримингового сервера, нужно использовать эффективный метод обработки событий (для linux это epoll). Именно такую схему работы и реализовал Roman Arutyunyan (блог, github-профиль) в своём RTMP-сервере, реализованном как модуль к nginx.
nginx-rtmp-module
Достоинства:
- Нереально шустрый. На том же физическом сервере, который я использовал для тестов Wowza, nginx выдержал 2500 мегабитных соединений на ядро, т.е. 10000 на весь сервер целиком.
- Удобные конфиги :). После километровых XML-конфигов Wowza эти выглядят спасением.
- Отзывчивость автора к фичреквестам.
Недостатки:
- Проект молодой, наличествуют баги, которые, впрочем, оперативно исправляются.
- Небольшая функциональность. Сервер вещает только в RTMP, перекодировка появилась буквально несколько дней назад, имеет статус экспериментальной и фактически является обёрткой над ffmpeg. UNIX-way во всей своей красе.
- Нет многопоточности. Модуль может работать только в том случае, если nginx запускается с одним воркером. Для утилизации всех процессорных ядер нужно запускать несколько воркеров на разных IP-адресах и/или портах.
Многопоточность можно реализовать с помощью примерно такого костыля (Ubuntu):
for ip in $(cat /etc/network/interfaces | grep address | awk '{print $2}') ; do
touch /etc/nginx/nginx.$ip.conf
cp /etc/nginx/nginx.conf.skel /etc/nginx/nginx.$ip.conf
sed -i "s/%IPADDR%/${ip}/g" /etc/nginx/nginx.$ip.conf
/usr/sbin/nginx -c /etc/nginx/nginx.$ip.conf
done
При этом у вас должен быть написан скелет конфига с указанием %IPADDR% вместо IP-адреса. Например, такой:
worker_processes 1;
error_log logs/error.%IPADDR%.log debug;
pid /var/run/nginx.%IPADDR%.pid;
worker_rlimit_nofile 65536;
events {
worker_connections 16384;
}
rtmp {
server {
listen %IPADDR%:1935;
chunk_size 4000;
application live {
live on;
pull live stream 193.9.17.213;
}
}
}
http {
server {
listen %IPADDR%:8080;
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /srv/nginx/html;
}
}
}
Впрочем, автор обещает реализовать нормальную многопоточность в будущих релизах.
С помощью nginx-rtmp-module мне удалось полностью утилизировать 10-гигабитный канал. При этом основной проблемой стала вовсе не прожорливость самого nginx, а необходимость тюнинга сетевой карты и параметров ядра, чтобы software interrupts не съедали 100% CPU.
Ссылки по теме:
RTMP на Википедии
Wowza — официальный сайт
Erlyvideo — официальный сайт
Nginx-rtmp-module — проект на GitHub
Автор: Aecktann