image

Apple HTTP Live Streaming — широко распространенная технология для доставки видео на мобильные устройства, которая делает ставку на простоту, универсальность и проходимость. В качестве протокола доставки используется самый простой, доступный и проверенный протокол Интернета HTTP, что позволяет доставить видео практически на любое устройство или ПО в сети.

Ниже под катом рассматривается альтернатива — Websocket Streaming для iOS Safari и подробно описывается процесс тестирования.

Выигрывая в универсальности, технология HLS уступает в скорости доставки и отображения видео. Видеопоток разбивается на фрагменты (chunks), которые скачиваются по HTTP как обычные файлы, буферизуются и собираются в видео на стороне плеера. Основным недостатком является большая задержка воспроизведения видео — 5 и более секунд.

Если у вас система видеонаблюдения или воспроизведение предзаписанного видео, для вас неважны 5-10 секунд задержки. Например, если на видео открывается вид парковки, на которой ничего не происходит, то 10 секунд разницы не имеют значения, разве что увидеть ту же картинку на 10 секунд позже.

Аналогично с предзаписанным видео: 10 секунд буферизации ни на что не повлияют.

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

16+
Другой пример — видеочат с 'моделью'. Клиент пишет в чат 'bb, show me your tits' и совсем не ожидает того, что заказанная услуга придет не мгновенно… Последний случай особенно вопиющ, по мнению наших коллег, специализирующихся на таких видеочатах.


Вот как выглядит HLS-плеер на iOS Safari:

image

Видео занимает весь экран и нет возможности этому помешать. HLS плеер запускается отдельно от браузера, и в нем проигрывается видеопоток. Такое отображение вполне удобно для просмотра видео — включил и смотришь.

Неудобства возникают в том случае, когда от web-приложения требуется некоторая интерактивность. К подобным приложениям могут предъявляться следующие требования:
  • воспроизведение видео непосредственно на HTML-странице в браузере;
  • на этой же странице могут быть размещены другие элементы, например, чат.

В основном, к таким web-приложениям относятся вебинары, видеочаты и трансляции с возможностью одновременного обсуждения в чате (например, спортивное событие).

На первый взгляд, самое простое решение — сделать iOS приложение для такой задачи, например, трансляция+чат и отправить пользователей скачивать приложение. Однако, как показывает практика, не все пользователи любят/умеют делать дополнительные телодвижения: заходить на App Store, озадачиваться настройками безопасности, скачивать приложение, запускать его и, наконец, смотреть трансляцию. Гораздо проще и короче в этом случае выглядит путь “клик по ссылке в Safari” — “просмотр трансляции прямо в браузере”.

Итак, имеем два требования для iOS Safari:
  1. видео должно воспроизводиться с минимальной задержкой;
  2. видео должно воспроизводиться прямо в браузере средствами 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.

image

Заходим на 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.
Логин и пароль были заданы во время установки.

image

Разрешаем подключения в настройках live > Incoming Security

По умолчанию RTMP-Publishing разрешен только по паролю. Разрешаем публиковать потоки всем желающим — опция ‘no authentication required’. Так будет проще тестировать, а позже всегда успеем закрыть доступ.

image

Качаем 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.

image

Открываем sample.mp4 файл в Wirecast

Добавляем ролик в Wirecast, просто выбрав его в файловой системе.

image

Запускаем воспроизведение sample.mp4 в Wirecast

Чтобы поставить ролик на воспроизведение, нужно нажать кнопку с изображением правой стрелки, которая находится прямо под зайцем. См. скриншот ниже.

image

Настраиваем Output Settings

Теперь задаем настройки кодирования. С этими настройками видео будет перекодировано и отправлено в сеть по протоколу RTMP.

Кодируем под мобильные устройства H.264 + AAC, задаем разрешение 320x240.

image

Настраиваем адрес RTMP-севрера

Здесь указываем адрес дроплета, на котором установлена Wowza. Имя потока: myStream.

image

Начинаем вещание потока

Нажимаем кнопку ‘Stream’ чтобы начать процесс перекодирования видео и отправку RTMP-потока на сервер. В правом верхнем углу появляется зеленый индикатор соединения.

image

Открываем админку Wowza в iOS Safari, приложение live

Если открыть админку не в iOS Safari, то при попытке получить УРЛы для воспроизведения по HLS будет выдана ошибка ‘Ваше устройство не поддерживает HLS’ или что-то похожее, поэтому заходим в админку в iOS Safari, выбираем приложение ‘live’ и кликаем по кнопке ‘Test Players’.

image

image

Кликаем по HLS-урлу и начинаем воспроизведение в Apple iPhone Safari

Никакого плеера там не оказалось, просто HTTP URL, с которого можно забрать видео по HLS. iOS Safari браузер открывает этот URL и включает внутренний HLS Player на воспроизведение видео. Получаем по HLS ролик, который стримит Wirecast в режиме Live.

Отметим, что задержка воспроизведения составляет около 25 секунд. Наверняка, это где-то можно тюнить, но ‘из коробки’ имеем то, что имеем.

image

Таким образом получаем следующую схему вещания HLS:

Схема достаточно простая: отправляем ролик по RTMP и раздаем по HLS.

image

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.

image

В нашем случае это 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.

image

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


image

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


image

Подключаемся к серверу через 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

На странице есть область отображения видео, две кнопки и область отображения текущих статусов воспроизведения.

image

Начинаем воспроизведение

Нажимаем ‘Play’ для того чтобы начать воспроизведение. Видим, что внутренний плеер iOS не подключается и видео воспроизводится непосредственно в теле HTML-страницы. Контролы ‘Play’ и ‘Pause’, а также блок статусов остаются на своих местах.

image

image

Так выглядит видео, растянутое на весь экран пальцами:

image

Если открыть ту же страницу в Google Chrome и применить Developer Tools, то можно увидеть HTML5 canvas — элемент, в который происходит отрисовка видео.

image

Если копнуть глубже и заглянуть во вкладку ‘Network’, можно увидеть множество Websocket Binary Frames, прилетающих с высокой скоростью, — это и есть тот видеопоток, который мы видим на HTML5 Canvas — элементе.

image

Задержка воспроизведения кардинально отличается от HLS и составляет всего около 3 секунд. Картинку видно четко. Артефакты отсутствуют. Аудио и видео отыгрывают синхронно без видимых недостатков.

В результате имеем следующую следующую схему вещания:

image

Интересно было бы также провести тесты расхода батареи. Есть основания полагать, что при VoW батарея садится быстрее, чем при штатном использовании HLS-плеера, хотя бы потому, что при HLS возможен аппаратный декодинг видео, а в VoW-плеере видео декодируется с помощью JavaScript.

В качестве итога нарисуем табличку различий данных технологий вещания.

image

Под сложностью настройки здесь понимается ввод дополнительного звена (WCS-сервер) и сам VoW-Player, что соответственно увеличивает время и сложность настройки системы.

Ниже оставляю демо-урлы с роликом про зайца для желающих протестировать самостоятельно.

HLS (iOS Safari)

VoW (IOS Safari, Windows Google Chrome)

Бесперебойную работу урлов не гарантирую.

Отдельная благодарность зайцу Big Buck Bunny. Без него не вышло бы такого красочного повествования.

image

Комментарии (14)


  1. drakmail
    05.05.2015 21:03
    +1

    Забавно, в свое время делал такую штуковину с нуля, в качестве сервера был костыль на node.js, звук и видео получал через getUserMedia, кодировал через собранную через emscripten библиотеку для AAC. При сиабильном соединеннии всё было волшебно, на нестабильном — сильно проигрывало hls :) хотя это было всё в виде прототипа на поиграться.


  1. Ivan_83
    06.05.2015 00:33
    +3

    1. HLS имеет несколько преимуществ:
    а) его очень легко проксировать и кешировать
    б) контент на сервере шифруется ОДИН раз

    2. Задержка зависит от очень многих параметров, и часть из них кроется в реализации самого плеера.
    Некоторые плееры требуют наличия кешированных данных чтобы начать воспроизведение, другие играют сразу то что есть.
    То как быстро приедут данные от сервера клиенту — сильно зависит от настроек tcp на сервере и клиенте, даже на идеальном канале.


    1. kostyl
      06.05.2015 18:43
      -1

      Еще одно приемущество, что HLS поддерживается искаробки AVPlayer-ом


  1. aloneunix
    06.05.2015 09:27

    Я правильно понял, что таким образом можно лайв-стримы транслировать на страницу без использования Flash? Только придётся еще ffmpeg прицепить, чтобы конвертировать RTMP в RTSP поток (пробежался по документации WCS4 — про поддержку RTMP ничего не нашел).


    1. sema_semin Автор
      06.05.2015 10:09

      Да, статья про Live-стримы без Flash. Просто ролик используется в качестве источника стрима. Можно было бы с таким же успехом использовать web-камеру если бы не странный баг Wirecast.

      Выше на схемке видно, что Wowza занимается конвертацией RTMP в RTSP, а WCS4 раздает этот RTSP-поток уже по Websockets. Кстати, похожее можно реализовать в связке ffmpeg+nodejs, но там с аудио возникли проблемы.


  1. erlyvideo
    06.05.2015 10:16

    вы в каком именно кодеке и с каким битрейтом на клиента перегоняете?


  1. Makaveli
    06.05.2015 14:09
    +4

    Зачем фоткать телефон, когда можно сделать скриншот экрана нажав Power+Home?


  1. aylarov
    06.05.2015 18:20

    Все это криво, в будущем все будут использовать html5-demos.appspot.com/static/media-source.html


    1. nwalker
      08.05.2015 16:44

      Который, как и HLS, chunked, то есть, zero-latency все равно не будет.


      1. aylarov
        08.05.2015 16:46

        Zero-latency будет только на WebRTC, только вам понадобится слишком мощный сервер, так как DTLS-шифрование для sRTP потока.


        1. Ogra
          08.05.2015 17:55

          DTLS используется только для передачи SRTP ключей.


          1. aylarov
            08.05.2015 17:57

            Да, но в самом sRTP все пакеты шифруются.


            1. 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.

              Wiki


              1. aylarov
                09.05.2015 11:48

                Погоняйте по sRTP видео, и потом поймете почему сейчас для этого используют что-нибудь попроще :)