Apple HTTP Live Streaming — широко распространенная технология для доставки видео на мобильные устройства, которая делает ставку на простоту, универсальность и проходимость. В качестве протокола доставки используется самый простой, доступный и проверенный протокол Интернета HTTP, что позволяет доставить видео практически на любое устройство или ПО в сети.
Ниже под катом рассматривается альтернатива — Websocket Streaming для iOS Safari и подробно описывается процесс тестирования.
Выигрывая в универсальности, технология HLS уступает в скорости доставки и отображения видео. Видеопоток разбивается на фрагменты (chunks), которые скачиваются по HTTP как обычные файлы, буферизуются и собираются в видео на стороне плеера. Основным недостатком является большая задержка воспроизведения видео — 5 и более секунд.
Если у вас система видеонаблюдения или воспроизведение предзаписанного видео, для вас неважны 5-10 секунд задержки. Например, если на видео открывается вид парковки, на которой ничего не происходит, то 10 секунд разницы не имеют значения, разве что увидеть ту же картинку на 10 секунд позже.
Аналогично с предзаписанным видео: 10 секунд буферизации ни на что не повлияют.
Другое дело, когда какое-либо событие транслируется в реальном времени, например, вебинар, где ведущий получает вопросы от зрителей и отвечает на них. Здесь дополнительная задержка может вызвать некоторый дискомфорт.
Вот как выглядит HLS-плеер на iOS Safari:
Видео занимает весь экран и нет возможности этому помешать. HLS плеер запускается отдельно от браузера, и в нем проигрывается видеопоток. Такое отображение вполне удобно для просмотра видео — включил и смотришь.
Неудобства возникают в том случае, когда от web-приложения требуется некоторая интерактивность. К подобным приложениям могут предъявляться следующие требования:
- воспроизведение видео непосредственно на HTML-странице в браузере;
- на этой же странице могут быть размещены другие элементы, например, чат.
В основном, к таким web-приложениям относятся вебинары, видеочаты и трансляции с возможностью одновременного обсуждения в чате (например, спортивное событие).
На первый взгляд, самое простое решение — сделать iOS приложение для такой задачи, например, трансляция+чат и отправить пользователей скачивать приложение. Однако, как показывает практика, не все пользователи любят/умеют делать дополнительные телодвижения: заходить на App Store, озадачиваться настройками безопасности, скачивать приложение, запускать его и, наконец, смотреть трансляцию. Гораздо проще и короче в этом случае выглядит путь “клик по ссылке в Safari” — “просмотр трансляции прямо в браузере”.
Итак, имеем два требования для iOS Safari:
- видео должно воспроизводиться с минимальной задержкой;
- видео должно воспроизводиться прямо в браузере средствами HTML5.
Оптимальным решением была бы поддержка технологии WebRTC. Действительно, применение технологии WebRTC решило бы проблему задержки и позволило бы играть поток прямо в браузере так, как это работает, например, в Android Chrome. К сожалению, поддержки WebRTC нет в iOS Safari и перспективы такой поддержки на данный момент весьма туманны.
Как обычно, когда нет поддержки от официального производителя, есть альтернативы,
одна из которых — доставка видео на iOS Safari по протоколу Websockets и отрисовка этого видеопотока средствами браузера.
Websockets — в данном случае единственный доступный в iOS Safari протокол, способный обеспечить быструю доставку видеопотока. Протокол работает на основе TCP как и HTTP, но, в отличие от последнего, гораздо лучше подходит для передачи потоковых данных в силу того, что бинарные данные передаются внутри уже установленного соединения и нет лишних HTTP заголовков при их передаче.
В настоящей статье мы сравним классический подход с использованием HLS c вещанием того же живого потока по Websocket на iOS Safari, для этого настроим и протестируем обе технологии.
Браузер iOS Safari выбран не случайно. IE и Mac Safari поддерживают Flash, Chrome, FF и Opera поддерживают WebRTC. И только iOS-устройства ограничены использованием HLS, альтернатива которому рассматривается в настоящей статье.
Стриминг видео через Websocket назовем VoW (Video over Websockets), а плеер, который этот поток играет, — VoW-Player.
Подробно опишем тестирование HLS и VoW, включая установку всего необходимого инструмента.
HLS — Apple HTTP Live Streaming
Создаем два дроплета
Для чистоты эксперимента используем два разных виртуальных сервера Centos 6.5 64 bit, 1 GB RAM на digitalocean.
Заходим на oracle.com, скачиваем, распаковываем и устанавливаем JDK
Oracle JDK можно скачать здесь.
Можно было бы установить и RPM, но простое копирование папки тоже работает.
tar -xvzf jdk-8u45-linux-x64.tar.gz
mkdir /usr/java
mv jdk1.8.0_45 /usr/java
ln -sf /usr/java/jdk1.8.0_45 /usr/java/default
ln -sf /usr/java/default/bin/java /usr/bin/java
java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
Качаем Wowza
Wowza будет принимать RTMP-поток и отдавать его как HLS. Скачиваем с сайта wowza.com. После этого нужно будет получить бесплатную лицензию разработчика.
Устанавливаем Wowza
Установщик спросит логин и пароль администратора, которые позже можно будет использовать для входа в админку.
chmod +x WowzaStreamingEngine-4.1.2.tar.bin
./WowzaStreamingEngine-4.1.2.tar.bin
Запускаем Wowza
Сам сервер и административный интерфейс запускаются отдельно.
service WowzaStreamingEngine start
service WowzaStreamingEngineManager start
Заходим в админ интерфейс Wowza
После успешного запуска админка доступна на порту 8088.
Логин и пароль были заданы во время установки.
Разрешаем подключения в настройках live > Incoming Security
По умолчанию RTMP-Publishing разрешен только по паролю. Разрешаем публиковать потоки всем желающим — опция ‘no authentication required’. Так будет проще тестировать, а позже всегда успеем закрыть доступ.
Качаем Wirecast Live Encoder
Выбор Wirecast был обусловлен тем, что он хорошо кодирует звук в AAC. Например, FMLE (Flash Media Live Encoder) под Windows 8 такого делать не умеет. FMLE под Mac умеет кодировать AAC, но Mac под рукой не оказалось.
К сожалению, с Wirecast-ом не получилось захватить видео с вебкамеры на Windows 8.1 64 bit, поэтому пришлось стримить видеоролик. Ниже дано описание процесса. На момент написания статьи использовалась версия Wirecast-6.0.4-64-bit.
Качаем sample.mp4 файл из каталога WowzaStreamingEngine/content на сервере
Видеоролик про зайца в формате MPEG4 идет в комплекте с Wowza. Скачиваем его на компьютер, где установлен Wirecast Encoder.
Открываем sample.mp4 файл в Wirecast
Добавляем ролик в Wirecast, просто выбрав его в файловой системе.
Запускаем воспроизведение sample.mp4 в Wirecast
Чтобы поставить ролик на воспроизведение, нужно нажать кнопку с изображением правой стрелки, которая находится прямо под зайцем. См. скриншот ниже.
Настраиваем Output Settings
Теперь задаем настройки кодирования. С этими настройками видео будет перекодировано и отправлено в сеть по протоколу RTMP.
Кодируем под мобильные устройства H.264 + AAC, задаем разрешение 320x240.
Настраиваем адрес RTMP-севрера
Здесь указываем адрес дроплета, на котором установлена Wowza. Имя потока: myStream.
Начинаем вещание потока
Нажимаем кнопку ‘Stream’ чтобы начать процесс перекодирования видео и отправку RTMP-потока на сервер. В правом верхнем углу появляется зеленый индикатор соединения.
Открываем админку Wowza в iOS Safari, приложение live
Если открыть админку не в iOS Safari, то при попытке получить УРЛы для воспроизведения по HLS будет выдана ошибка ‘Ваше устройство не поддерживает HLS’ или что-то похожее, поэтому заходим в админку в iOS Safari, выбираем приложение ‘live’ и кликаем по кнопке ‘Test Players’.
Кликаем по HLS-урлу и начинаем воспроизведение в Apple iPhone Safari
Никакого плеера там не оказалось, просто HTTP URL, с которого можно забрать видео по HLS. iOS Safari браузер открывает этот URL и включает внутренний HLS Player на воспроизведение видео. Получаем по HLS ролик, который стримит Wirecast в режиме Live.
Отметим, что задержка воспроизведения составляет около 25 секунд. Наверняка, это где-то можно тюнить, но ‘из коробки’ имеем то, что имеем.
Таким образом получаем следующую схему вещания HLS:
Схема достаточно простая: отправляем ролик по RTMP и раздаем по HLS.
VoW — Video over Websockets
Устанавливаем JDK на второй дроплет тем же способом, что и для Wowza
tar -xvzf jdk-8u45-linux-x64.tar.gz
mkdir /usr/java
mv jdk1.8.0_45 /usr/java
ln -sf /usr/java/jdk1.8.0_45 /usr/java/default
ln -sf /usr/java/default/bin/java /usr/bin/java
Устанавливаем и настраиваем Web Call Server 4
Скачиваем и устанавливаем WCS4-сервер
wget http://flashphoner.com/download-wcs4-server.tar.gz
tar -xvzf download-wcs4-server.tar.gz
cd FlashphonerWebCallServer-4.0.1212
./install.sh
Установщик спросит два раза IP-адрес.
Нужно указать IP-адрес дроплета оба раза.
IP адрес определяется например командой ifconfig.
В нашем случае это 46.101.139.106.
Получаем бесплатную лицензию и активируем ее после установки
cd /usr/local/FlashphonerWebCallServer-4.0.1212/bin
./activation.sh
Добавляем поддержку AAC-кодека в настройках и RTSP interleave mode
AAC — это mpeg4-generic. ‘Interleave mode’ добавляем на тот случай, если Wowza-сервер был сконфигурирован на работу RTSP через TCP.
mc -e /usr/local/FlashphonerWebCallServer/conf/flashphoner.properties
codecs =opus,alaw,ulaw,g729,speex16,g722,mpeg4-generic,telephone-event,vp8,h264,flv,h263,h263p,mpv
rtsp_interleaved_mode=true
Запускаем сервер
Сервер запускается довольно долго на виртуалке. Ждем 1 минуту. Перед запуском желательно прописать в /etc/hosts IP адрес сервера и имя хоста (hostname). Без этого с запуском могут быть проблемы.
hostname
wcs
service webcallserver start
Устанавливаем и запускаем Apache
Apache будет отдавать страничку с тестовым плеером.
yum install httpd
service httpd start
Разворачиваем пример с VoW Player в web-каталоге
cd /var/www/html/
wget http://flashphoner.com/download-wcs4-client.tar.gz
tar -xvzf download-wcs4-client.tar.gz
Указываем URL подключения к серверу и стрим, который нужно забрать
mc -e /var/www/html/examples/min/vow-player-min.js
Подключаемся к серверу через Websocket:
var url = "ws://46.101.139.106:8080";
Забираем поток с Wowza по RTSP:
var streamName = "rtsp://46.101.139.105:1935/live/myStream";
Открываем плеер в iOS Safari
Открывается простая HTML-страница: 46.101.139.106/examples/min/vow-player-min.html
На странице есть область отображения видео, две кнопки и область отображения текущих статусов воспроизведения.
Начинаем воспроизведение
Нажимаем ‘Play’ для того чтобы начать воспроизведение. Видим, что внутренний плеер iOS не подключается и видео воспроизводится непосредственно в теле HTML-страницы. Контролы ‘Play’ и ‘Pause’, а также блок статусов остаются на своих местах.
Так выглядит видео, растянутое на весь экран пальцами:
Если открыть ту же страницу в Google Chrome и применить Developer Tools, то можно увидеть HTML5 canvas — элемент, в который происходит отрисовка видео.
Если копнуть глубже и заглянуть во вкладку ‘Network’, можно увидеть множество Websocket Binary Frames, прилетающих с высокой скоростью, — это и есть тот видеопоток, который мы видим на HTML5 Canvas — элементе.
Задержка воспроизведения кардинально отличается от HLS и составляет всего около 3 секунд. Картинку видно четко. Артефакты отсутствуют. Аудио и видео отыгрывают синхронно без видимых недостатков.
В результате имеем следующую следующую схему вещания:
Интересно было бы также провести тесты расхода батареи. Есть основания полагать, что при VoW батарея садится быстрее, чем при штатном использовании HLS-плеера, хотя бы потому, что при HLS возможен аппаратный декодинг видео, а в VoW-плеере видео декодируется с помощью JavaScript.
В качестве итога нарисуем табличку различий данных технологий вещания.
Под сложностью настройки здесь понимается ввод дополнительного звена (WCS-сервер) и сам VoW-Player, что соответственно увеличивает время и сложность настройки системы.
Ниже оставляю демо-урлы с роликом про зайца для желающих протестировать самостоятельно.
HLS (iOS Safari)
VoW (IOS Safari, Windows Google Chrome)
Бесперебойную работу урлов не гарантирую.
Отдельная благодарность зайцу Big Buck Bunny. Без него не вышло бы такого красочного повествования.
Комментарии (14)
Ivan_83
06.05.2015 00:33+31. HLS имеет несколько преимуществ:
а) его очень легко проксировать и кешировать
б) контент на сервере шифруется ОДИН раз
2. Задержка зависит от очень многих параметров, и часть из них кроется в реализации самого плеера.
Некоторые плееры требуют наличия кешированных данных чтобы начать воспроизведение, другие играют сразу то что есть.
То как быстро приедут данные от сервера клиенту — сильно зависит от настроек tcp на сервере и клиенте, даже на идеальном канале.
aloneunix
06.05.2015 09:27Я правильно понял, что таким образом можно лайв-стримы транслировать на страницу без использования Flash? Только придётся еще ffmpeg прицепить, чтобы конвертировать RTMP в RTSP поток (пробежался по документации WCS4 — про поддержку RTMP ничего не нашел).
sema_semin Автор
06.05.2015 10:09Да, статья про Live-стримы без Flash. Просто ролик используется в качестве источника стрима. Можно было бы с таким же успехом использовать web-камеру если бы не странный баг Wirecast.
Выше на схемке видно, что Wowza занимается конвертацией RTMP в RTSP, а WCS4 раздает этот RTSP-поток уже по Websockets. Кстати, похожее можно реализовать в связке ffmpeg+nodejs, но там с аудио возникли проблемы.
Makaveli
06.05.2015 14:09+4Зачем фоткать телефон, когда можно сделать скриншот экрана нажав Power+Home?
aylarov
06.05.2015 18:20Все это криво, в будущем все будут использовать html5-demos.appspot.com/static/media-source.html
nwalker
08.05.2015 16:44Который, как и HLS, chunked, то есть, zero-latency все равно не будет.
aylarov
08.05.2015 16:46Zero-latency будет только на WebRTC, только вам понадобится слишком мощный сервер, так как DTLS-шифрование для sRTP потока.
Ogra
08.05.2015 17:55DTLS используется только для передачи SRTP ключей.
aylarov
08.05.2015 17:57Да, но в самом sRTP все пакеты шифруются.
Ogra
08.05.2015 18:29Так там же AES, быстрый сам по себе, да еще и аппаратно-поддерживаемый Intel.
On Intel Core i3/i5/i7 and AMD APU and FX CPUs supporting AES-NI instruction set extensions, throughput can be over 700 MB/s per thread.
Wikiaylarov
09.05.2015 11:48Погоняйте по sRTP видео, и потом поймете почему сейчас для этого используют что-нибудь попроще :)
drakmail
Забавно, в свое время делал такую штуковину с нуля, в качестве сервера был костыль на node.js, звук и видео получал через getUserMedia, кодировал через собранную через emscripten библиотеку для AAC. При сиабильном соединеннии всё было волшебно, на нестабильном — сильно проигрывало hls :) хотя это было всё в виде прототипа на поиграться.