Какой бывает HTML5-стриминг (и почему mp4-стриминга не существует)

Нередко клиенты спрашивают, умеет ли наш сервер «mp4-стриминг в HTML5». В 99% случаев спрашивающий не понимает о чём говорит. В этом сложно винить клиентов: из-за путаницы с терминами, технической сложности и большого разнообразия вариантов стриминга запутаться очень легко.

В этой статье мы расскажем, какой бывает HTML5-стриминг, какие варианты хорошие, и почему, чёрт побери, нельзя говорит «mp4-стриминг». html5-video-logo

Термины

HTML5-видео — это когда вы вставляете в веб-страницу тег <video> и указываете ему какой-то src. HTML5-стриминг — это то же HTML5-видео, но когда в src не готовый файл, а постоянно обновляющийся видеопоток. Ролик на Ютубе — это HTML5-видео, трансляция в Твитче — HTML5-стриминг.

Тегу <video> неважно, как видеопоток формируется и передаётся, и сможет ли браузер его проиграть. Главное, чтобы в src была ссылка на какой-то видеопоток. Говоря техническим языком, спецификация ничего не говорит о том, какие протоколы, транспорты и кодеки поддерживаются в HTML5-видео.

Протокол — это то, как два участника видеосвязи (почти всегда это клиент и сервер) обмениваются данными с целью получения данных. Клиентом называют того, кто приходит к серверу и инициирует сессию связи. Видеопоток может течь от сервера к клиенту (тогда это обычное проигрывание) или от клиента к серверу (тогда это публикация). Даже когда гигантский шкаф, жрущий электричество как многоквартирный дом, приходит к маленькой IP-камере, то она будет сервером, а этот шкаф клиентом.

Протокол обычно подразумевает хотя бы команду Play (начать проигрывание), но иногда есть и расширенные варианты: пауза, продолжение, публикация, перемотка и т. п.

Примеры протоколов: RTSP, RTMP, HTTP, HLS, IGMP.

Транспорт, или транспортный контейнер, или контейнер — это то, как сжатое видео упаковывается в байты для передачи от одного участника к другому (по какому-то протоколу).

Примеры контейнеров: MPEG-TS, RTMP, RTP.

Обратите внимание, что RTMP оказался и в протоколах, и в транспортах. Это потому, что в описании RTMP есть спецификация и того, что должны слать друг другу стороны, чтобы видео потекло (т. е. протокол), и того, как упаковывать видео (т. е. транспорт). Так бывает не всегда. Например в протоколе RTSP видео упаковывается в транспорт RTP.

Кодек — многозначный термин. Здесь он означает способ сжать сырое видео. Разница между кодеком и транспортом в том, что кодек — это про подготовку видео, а транспорт — про передачу видео по протоколу. Видео, сжатое одним кодеком, можно пересылать по разными протоколам и разными транспортами. Большинство видеостриминговых серверов не залезают глубже кодированного видео и оперируют только протоколами и транспортами.

Примеры кодеков: h264, aac, mp3.

Из-за того, что термин многозначный, возникает путаница с названиями. Например, H.264 — это стандарт того, как упаковать поток огромных сырых видеокадров в очень мало > байтов, libx264 — это библиотека для сжатия по этому стандарту, а ещё есть одноимённый софт под Винду, который умеет декодировать h264 и проигрывать его на экране.

codec-protocol-transport

Итак, в спецификации HTML5 не описаны протоколы, транспорты и кодеки. Поэтому авторы браузеров сами выбирают, что поддерживать, а под «HTML5-стримингом» подразумевают разные вещи.

При этом есть комбинации, которые поддерживаются значительной частью браузеров. Рассмотрим самые перспективные.

HLS

hls-logo

HLS — это h264-видео и aac- или mp3-аудио, упакованное в транспорт MPEG-TS. Поток разбивается на сегменты, описанные в m3u8-плейлистах, и раздается по HTTP. HLS поддерживает мультибитрейтные потоки, Live/VOD. Вариант очень простой, но в то же время имеет много деталей, из-за чего на разных устройствах работает по-разному.

Разработали HLS в Эппле, поэтому изначально он работал только в Сафари на Айос и Маке. До сих пор даже Сафари на Винде не умеет играть HLS. Тем не менее, сейчас HLS умеют проигрывать все телевизионные приставки и даже почти все устройства на Андроиде.

Но не всё гладко. Производители сторонних плееров плюнули на стандарт Эппла в части донесения разных аудиодорожек и добавили проигрывание всего что есть в обычном MPEG-TS: mpeg2 video, mpeg2 audio и т. п. Из-за этого приходится отдавать разные форматы плейлистов для разных плееров.

MPEG-DASH

mpeg-dash-logo

MPEG-DASH — обычно это h264/h265-видео и aac-аудио, упакованное в транспорт mp4, или vp8/vp9, упакованное в WebM, хотя стандарт и не привязан к конкретным кодекам, протоколам и транспортам. Как и в HLS, поток может разбиваться на сегменты, но это необязательно. Вместо плейлистов — MPD-манифест в XML.

MPEG-DASH во многом похож на HLS. Возможно, он даже популярнее, ведь такие гиганты как Ютуб и Нетфликс уже несколько лет используют его как основной способ раздачи контента.

MPEG-DASH хорош тем, что в большинстве браузеров работает нативно, через MSE (о том, что это такое, — чуть ниже). Для него даже нет реализации на Флеше — это честный, бескомпромиссный HTML5.

Определенно, MPEG-DASH — самый настоящий HTML5-стриминг, за ним будущее.

MSE

Когда стало ясно, что Флеш всё-таки умрёт (после сотни ложных похорон), ребром встал вопрос о том, что придёт ему на смену. Хорошо было бы получить в браузерах возможность проигрывать видео по качеству и удобству близко к тому, что умеет Флеш (а он это делает всё-таки хорошо).

Во Флеше давно появился очень удобный механизм для универсального проигрывания разных вариантов — appendBytes. Суть в том, что пользовательский код сам как хочет скачивает кадры сжатого видео, упаковывает в оговоренный контейнер (с Флешем это flv) и засовывает в видеопроигрыватель. Т. е. протокол и транспорт реализуются в пользовательском коде, запускаемом в браузере.

MSE (Media Sources Extensions) — это расширение спецификации HTML5, которое позволяет делать то же, что делает appendBytes во Флеше. К сожалению, MSE намного сложнее как в понимании, так и в реализации.

MPEG-DASH, созданный на его базе, ещё хитрее, поэтому работать с ними то ещё удовольствие: тонны XML, парсинг бинарных контейнеров в Яваскрипте, непродуманные на этапе дизайна вопросы нарезки на сегменты — всё как мы любим, всё что нужно для единой безглючной реализации во всех браузерах.

Интересно, что MSE работает не только с MPEG-DASH, но и с HLS. Существует реализация hls.js, которая скачивает HLS-плейлисты, скачивает MPEG-TS-сегменты, перепаковывает их в нужный для MSE формат и играет через MSE. Эппл даже сделала шаг в сторону совместимости с MPEG-DASH — использование mp4-контейнеров в HLS.

К концу 2017 года Флеш скорее всего умрёт окончательно, и уже сегодня можно смело начинать проект с MPEG-DASH.

WebRTC

webrtc-logo

Во Флеше была сделана годная попытка в одной технологии реализовать и риалтайм-общение, и массовый броадкастинг. К сожалению, в HTML5 так не вышло. Для просмотра трансляций у нас есть MSE, а для видеозвонков — WebRTC.

WebRTC — это SIP в браузере: способ организовать аудио- и видеоканал и канал данных между двумя браузерами при посредничестве сервера.

Технология не предназначена для стриминга, но в принципе может и его, так что было бы неправильно забыть про него. WebRTC тоже считается HTML5, потому что вроде как ничего кроме Яваскрипта в браузере не требует. Зато требует наличия последних версий обоих популярных браузеров, а с Эджем пока вообще не совместимо.

Путаницу в понимании WebRTC вносит его использование в торрент-доставке телевидения. Суть в том, что браузеры через WebRTC организуют сеть каналов данных, а дальше по этой сети раздаются HLS- или MSE-сегменты видео, а проигрывание происходит через Флеш или MSE. Т. е. WebRTC — для доставки, MSE — для проигрывания. Важно не путать это с использованием WebRTC для проигрывания видео.

Так что там с mp4-стримингом?

Любой современный браузер скорее всего сможет по протоколу HTTP запросить файл, упакованный в транспорт mp4 и содержащий внутри видео, сжатое кодеком h264/aac. И даже попытаться проиграть его. Это самый удобный, понятный и стандартный вариант проигрывания файлов. Лежит себе файлик на диске, nginx его отдает. Код, проигрывающий mp4 в браузерах достаточно хорош. Например, он умеет даже скачивать куски видео по необходимости (в отличие от Флеш-плеера, который скачивает видео целиком).

Вокруг h264 сложилось немало шумихи по поводу его «закрытости» и «несвободности». Так что есть «открытая» альтернатива, которую форсит Гугл — видеокодеки vp8 и vp9, упакованные в транспорт WebM. WebM — это подмножество транспорта mkv (a. k. a. Матрёшка), который очень похож на mp4 по сути, но отличается от него своей «бинарностью».

Именно отсюда растут ноги у такого явления как «mp4-стриминг», который устроен как WebM. Дело в том что в обычном mp4 в самом начале указывается размер всего контейнера. Поэтому, если мы хотим отдать по обычному mp4 прямой эфир, у нас ничего не получится. А чтобы всё-таки получилось и можно было создавать mp4 без фиксированного конца, придуман следующий ход: сначала пишется mp4 без кадров, а потом в конце подписываются блоками по несколько секунд фрагменты с кадрами. Это называется mp4 fragmented, или mp4 streaming.

По сути это никакой не стриминг, а костыль, позволяющий создать его видимость. Mp4 — отличный формат для скачивания видео, но негодный для стриминга, так что про него можно просто забыть и никогда не использовать термин «mp4-стриминг».

Выводы

  • Хорошие варианты HTML5-стриминга: MPEG-DASH и HLS. Они подходят и для мобильных устройств, и для ПК, и для приставок.
  • Флеш всё-таки умрет, и MSE уже сейчас занимает его место.
  • WebRTC — HTML5 технология, в первую очередь, для общения, а не для телевизионного вещания.
  • Не приносите в веб старые кодеки и не пытайтесь доставлять mp2video и mp2audio по HLS, даже если ваш плеер это умеет.
  • Никогда не говорите «mp4 стриминг». Пожалуйста.

Популярные статьи