Video Surveillance

Как строится архитектура передачи видео из приложения на сервер и дальше к зрителю

Облачные технологии Новость дня Новости видеонаблюдения Отраслевые решения
Когда говорят о передаче видео на сайт, часто смешивают сразу несколько разных задач. Первая задача, как приложение отправляет поток на сервер. Вторая, что сервер делает с этим потоком дальше. Третья, каким способом зритель потом получает видео в плеере. Пока эти части не разделены, архитектура получается запутанной, а выбор протокола превращается в спор о вкусе. На практике у каждого звена своя роль, и хороший результат обычно появляется не там, где выбран один универсальный протокол на все случаи жизни, а там, где каждый протокол используется по назначению.

С чего правильно начинать

Начинать нужно не с веб-плеера и не с красивого доменного имени, а с источника. Надо понять, в каком виде настольное приложение будет отдавать поток наружу. Здесь чаще всего рассматривают RTP, RTSP, RTMP, SRT, HLS и WebRTC. Но у них разные задачи. Одни лучше подходят для публикации потока на сервер, другие для доставки на сайт, третьи для внутренней работы между устройствами.
Из-за этого главный принцип очень простой. Протокол публикации и протокол просмотра это не одно и то же. То, что хорошо подходит для передачи потока с приложения на сервер, может оказаться плохим вариантом для браузера. И наоборот. Поэтому почти всегда правильная архитектура строится в два этапа. Сначала приложение публикует поток на медиасервер. Потом медиасервер отдает его зрителю уже в том формате, который удобен для сайта, мобильного клиента или операторского интерфейса.

Общая модель работы

В самой здоровой схеме есть три роли. Источник видео, то есть настольное приложение или отдельный агент. Медиасервер, который принимает поток, при необходимости переупаковывает или перекодирует его и раздает дальше. И прикладной сервер, который отвечает за пользователей, права доступа, логику интерфейса и выбор нужного потока.
В такой модели приложение не должно изображать из себя веб-сервер, а веб-сервер не должен без необходимости заниматься приемом входящего потока. Каждый делает свою работу. Приложение отправляет видео. Медиасервер занимается медиа. Основной сервер отвечает за логику системы и доступ.

RTP и RTSP: где они полезны и где начинаются проблемы

RTP хорош как транспорт внутри профессиональной среды. Он легкий, привычный для видеоустройств и давно используется в системах реального времени. Но сам по себе он не является хорошим ответом на вопрос, как показать видео на сайте. Для браузера RTP неудобен, для интернета капризен, а для массового просмотра требует промежуточного узла.
RTSP исторически удобен для камер и регистраторов. Он позволяет управлять потоком и получать видео от устройства. Но для сайта у него старая беда. Браузеры его напрямую не любят, работа через NAT и фильтры провайдеров бывает нестабильной, а при попытке тянуть RTSP сразу в веб-плеер почти всегда появляется дополнительный слой костылей. Поэтому RTSP хорош как внутренний протокол между камерой и сервером, но редко бывает хорошим конечным вариантом для веб-доставки.
Если сказать совсем коротко, RTSP удобен для устройств, но неудобен для массового веб-просмотра. Это как хороший складской погрузчик. Для склада замечательно, для прогулки по бульвару не очень.

Почему RTMP до сих пор жив

RTMP остается удобным входным протоколом для публикации потока. Он прост, понятен, живет по стабильной схеме сервер плюс приложение плюс ключ потока и хорошо подходит для настольного клиента, который должен просто передать видео на сервер. Настроить его обычно проще, чем более современные варианты, а встроить в приложение или внешний процесс несложно.
Слабое место RTMP не во входе, а в выходе. Для веб-плеера он давно не лучший вариант. Поэтому RTMP разумно использовать как протокол публикации на сервер, а уже сервер должен превратить поток в HLS, WebRTC или другой формат просмотра.

Почему SRT во многих случаях лучше RTMP

SRT нужен там, где сеть между приложением и сервером неидеальна. Если поток идет не по уютной локальной сети, а через интернет, удаленные площадки, нестабильные каналы и сложные провайдерские условия, SRT обычно оказывается надежнее. Он лучше переносит потери, дрожание канала и прочие радости реальной жизни.
Это не значит, что RTMP плохой. Это значит, что RTMP проще, а SRT устойчивее. Если вам нужна максимально прямолинейная схема и сеть хорошая, RTMP вполне подойдет. Если сеть сложная, длинная или капризная, SRT обычно выглядит взрослее. Для современных систем это очень сильный вариант именно как входной транспорт на сервер.

Почему HLS хорош для просмотра, но неудобен как вход из приложения

HLS изначально силен как способ доставки видео зрителю. Он работает поверх обычного HTTP, хорошо дружит с веб-инфраструктурой, прокси, кешами и масштабированием. Именно поэтому HLS отлично подходит для сайта.
Но если заставить настольное приложение стримить сразу в HLS, жизнь резко усложняется. Приложению приходится не просто кодировать видео, а резать его на сегменты, вести плейлист, удалять старые куски, публиковать множество файлов и следить, чтобы все это обновлялось синхронно. То есть приложение начинает выполнять работу небольшого медиасервера. Это можно сделать, но архитектурно обычно хуже, чем просто отправить поток на сервер в RTMP или SRT и отдать сегментацию самому серверу.
Поэтому HLS почти всегда лучше рассматривать как выходной формат для зрителя, а не как входной формат от приложения.

Где нужен WebRTC

WebRTC нужен тогда, когда важнее всего низкая задержка. Если оператор должен видеть почти живую картинку без длинной паузы, WebRTC дает очень приятный результат. Но у этого есть цена. Он тяжелее для сервера, сложнее в сетевой части и хуже масштабируется на большое количество зрителей, чем HLS.
Именно поэтому WebRTC хорош для операторских интерфейсов, переговорных сценариев, интерактивных задач и быстрой визуальной реакции. А HLS лучше для большого числа зрителей, для публикации на сайте и для более спокойной нагрузки на сервер.

Прямой HLS из приложения: когда это имеет смысл

Такую схему можно построить. Приложение кодирует поток, режет его на сегменты и кладет плейлист и файлы в папку или на удаленное HTTP-хранилище. Сайт потом читает этот плейлист и показывает поток в плеере.
Плюс у такого подхода один. Можно обойтись без отдельного сервера для публикации потока.
Минусов больше. Выше нагрузка на приложение. Больше операций с файлами. Больше риска на сетевых сбоях. Сложнее сопровождение. Хуже управляемость при росте числа потоков. Поэтому как инженерный эксперимент схема интересная, а как основа для серьезной системы обычно проигрывает варианту с отдельным медиасервером.

Проблема H.265 в веб-плеере

H.265 хорош как кодек с точки зрения качества и экономии полосы. Там, где он поддерживается, он дает очень приятный результат. Но в мире веб-плееров все упирается в совместимость. Один браузер его понимает лучше, другой хуже, третий вообще ведет себя как человек, который пришел на свадьбу, но не знаком ни с женихом, ни с невестой.
Поэтому H.265 может быть хорошим внутренним форматом доставки или хранения, но не всегда хорошим универсальным форматом для сайта. Для массового веб-плеера H.264 до сих пор остается более безопасным выбором. Он скучнее, но зато реже устраивает сюрпризы.
Если вы хотите показывать поток через WebRTC, проблема становится еще заметнее. Поддержка H.265 в браузерном мире далеко не так ровна, как хотелось бы. И там, где в HLS еще можно жить, в WebRTC уже часто приходится возвращаться к H.264.

Почему H.265 на входе может стать очень дорогим

Если приложение отправляет поток в H.265, а зрителю на сайте надо показать H.264, значит где-то по дороге придется перекодировать. Это уже не легкая переупаковка и не смена контейнера. Это полноценное декодирование и повторное кодирование видео.
На одном-двух потоках еще можно махнуть рукой и сделать вид, что так и надо. На десятках потоков сервер превращается в горячий спор между процессором, памятью и здравым смыслом. На сотне потоков без аппаратного ускорения это уже не архитектура, а спортивная дисциплина.
Отсюда практический вывод. Если конечная цель это веб-плеер, а особенно WebRTC, лучше по возможности как можно раньше привести поток к H.264, чем тащить H.265 до сервера и заставлять сервер массово заниматься перекодированием. Иначе медиасервер начинает работать не как транспортный узел, а как котельная.

Сравнение основных архитектур

Приложение -> RTMP -> медиасервер -> HLS -> сайт

Это классический и понятный вариант. Приложение публикует поток просто и стабильно. Сервер режет его в HLS. Сайт показывает поток через обычный веб-плеер. Эта архитектура хорошо подходит для большого числа зрителей и не требует экзотики. Минус один, задержка выше, чем у WebRTC. Зато по надежности и масштабу это один из самых спокойных вариантов.

Приложение -> SRT -> медиасервер -> HLS -> сайт

Очень сильный вариант, если приложение и сервер находятся в разных сетях или работают через интернет. На входе получаем более надежный транспорт, на выходе удобный и масштабируемый формат просмотра. Для видеонаблюдения, где важна устойчивость, а не только красивая теоретическая схема, такой путь выглядит очень здраво.

Приложение -> RTMP -> медиасервер -> WebRTC -> сайт

Подходит там, где нужна минимальная задержка, а сеть на входе относительно простая. Плюс, довольно прямой вход и быстрый просмотр. Минус, более тяжелый выход и меньшая дружелюбность к большому числу зрителей.

Приложение -> SRT -> медиасервер -> WebRTC -> сайт

Наиболее интересный вариант для низкой задержки в реальных сетях. На входе устойчивый транспорт, на выходе очень быстрая картинка. Минусы стандартные для WebRTC. Выше нагрузка, сложнее масштабирование, больше внимания к кодекам и серверным ресурсам.

Приложение -> HLS -> HTTP-хранилище -> сайт

Схема возможная, но чаще интересна как эксперимент или как очень узкий частный случай. Приложение слишком много берет на себя. Для долговременной жизни такой подход обычно проигрывает более классическим вариантам.

Сравнение нагрузки

Если смотреть только на вход из приложения, то RTMP и SRT обычно легче, чем HLS. Они передают один непрерывный поток. HLS как входной путь заставляет приложение или промежуточный узел постоянно создавать и публиковать сегменты, обновлять плейлист и выполнять множество файловых и сетевых операций.
Если смотреть на выход к зрителю, то HLS обычно легче для сервера, чем WebRTC. HLS лучше масштабируется и спокойнее живет при большом числе зрителей. WebRTC дает лучшую задержку, но на выходе обычно дороже по серверной нагрузке.
Если добавить перекодирование H.265 в H.264, все становится тяжелее независимо от выбранного транспорта. В этот момент главный вопрос уже не «RTMP или SRT», а «кто будет декодировать и кодировать заново и на каком железе».

Что меняется, если зритель смотрит не в веб-плеере, а в мобильном приложении

Вот здесь начинается совсем другая жизнь. Если зритель смотрит видео в собственном мобильном приложении, часть ограничений браузера просто исчезает. Появляется больше свободы в выборе кодеков и протоколов. Нативное приложение может лучше использовать системные декодеры и не упираться в те же рамки, что веб-плеер.
Это значит, что для мобильного клиента иногда можно обойтись без части серверной перекодировки, которая обязательна для сайта. Например, поток в H.265 может быть терпим или даже удобен для нативного приложения, тогда как веб-плееру пришлось бы давать H.264. Для сервера это огромная разница. Там, где веб-сценарий требует тяжелой перекодировки, мобильный клиент иногда позволяет отдать поток ближе к исходному виду.
Но и тут не надо впадать в крайности. Если пытаться тащить в мобильное приложение прямой RTSP или RTP через интернет, старые сетевые проблемы никуда не денутся. Поэтому серверный узел посередине все равно обычно полезен. Просто для мобильного клиента можно делать более легкую и менее болезненную схему, чем для браузера.

Что выбирать на практике

Если нужен универсальный и спокойный вариант для сайта, чаще всего лучший выбор это RTMP или SRT на вход и HLS на выход. Если сеть хорошая и хочется попроще, RTMP вполне годится. Если сеть сложная, удаленная или нестабильная, лучше SRT. Для сайта HLS обычно остается самым разумным форматом.
Если нужна минимальная задержка, лучше смотреть в сторону SRT или RTMP на вход и WebRTC на выход. Но надо заранее понимать, что серверная часть станет тяжелее, а требования к железу и сети вырастут.
Если входной поток в H.265, а выход нужен в универсальный веб-плеер, лучше очень внимательно посчитать, где и как будет происходить перекодирование. Если можно избежать массовой серверной перекодировки, лучше избежать. Если нельзя, значит проект надо считать уже как систему с серьезной медианагрузкой, а не как простую веб-службу.
Если есть собственное мобильное приложение, его надо рассматривать отдельно. Не как младшего брата веб-плеера, а как самостоятельного клиента с другими возможностями. Это часто позволяет сделать архитектуру легче, дешевле и надежнее.

Итог

Универсального идеального протокола для всех задач не существует. RTP и RTSP удобны внутри мира устройств, но неудобны как конечный ответ для сайта. RTMP прост и хорош как входной протокол. SRT надежнее на сложной сети и часто лучше подходит для передачи с приложения на сервер. HLS остается самым спокойным форматом для массового просмотра через сайт. WebRTC выигрывает там, где важна низкая задержка. H.265 хорош как кодек, но в веб-мире часто приводит к вопросам совместимости и перекодировки. А наличие собственного мобильного клиента может резко изменить баланс в пользу более легкой серверной схемы.
Хорошая архитектура начинается не с любви к какому-то одному протоколу, а с честного ответа на три вопроса. Как приложение публикует поток. Что сервер должен сделать с этим потоком. И кто именно будет его смотреть. Когда эти три вопроса разложены по местам, выбор становится намного проще, а система перестает напоминать загадочную коробку, которую страшно открыть, потому что потом не соберешь обратно.