Что такое MPEG-DASH
MPEG-DASH — технология нового поколения, позволяющая вещать адаптивный видео-поток. Данные разбиваются на фрагменты и передаются клиенту по протоколу HTTP. Это позволяет надежно передавать видео через существующую HTTP-инфрастуктуру, преодолевать прокси-сервера, а также безболезненно переносить проблемы с сетью, изменения сетевых адресов итд.
DASH — Dynamic Adaptive Streaming over HTTP. Стандарт DASH ISO/IEC 23009-1:2012 был разработан группой MPEG в 2011 годуТехнология MPEG-DASH в целом аналогична другой известной технологии HLS (HTTP Live Streaming), разработанной компанией Apple и широко используемой на мобильных устройствах с iOS и Android. Поток представлен в виде небольших по длительности фрагментов и плейлиста (манифеста), содержащего метаданные потока и ссылки на фрагменты.
В HLS плейлист хранится в формате m3u8 (расширение m3u), а фрагменты — в MPEG-TS (часть стандарта MPEG-2). В MPEG-DASH плейлист (манифест) хранится в XML, а фрагменты могут иметь как формат MPEG-TS, так и ISO BMFF (проще говоря, mp4). На практике поддержка MPEG-TS клиентами ограничена, так что ориентироваться приходится на более современный mp4.
В чем же состоит преимущество MPEG-DASH? Главное преимущество в том, что поддержка этой технологии сегодня активно внедряется в браузеры, что дает возможность вещать видео без использования тяжелого и порядком надоевшего flash. Кроме того, MPEG-DASH поддерживается новыми моделями телевизоров в рамках стандарта HbbTV.
Далее я расскажу о самой технологии и опишу, как настроить live вещание в браузере с помощью nginx-rtmp-module и dash.js.
Манифест
Манифест MPEG-DASH — это XML документ. Его спецификация приведена в стандарте ISO/IEC 23009-1:2012. Манифест имеет довольно сложный формат, он поддерживает периоды, сдвижки времени, описание потоков, различные способы нумерации фрагментов. Для живого вещания потока с постоянным аудио и видео каналами, нам достаточно лишь ограниченного набора возможностей:
- характеристики видео — размеры, fps, кодек, ширина потока
- характеристики аудио — частота, кодек, ширина потока
- ссылки на актуальные аудио и видео фрагменты
- ссылки на инициализирующие фрагменты потоков
Пример манифеста
<?xml version="1.0"?>
<MPD
type="dynamic"
xmlns="urn:mpeg:dash:schema:mpd:2011"
availabilityStartTime="2013-11-27T12:40:35+04:00"
availabilityEndTime="2013-11-27T12:41:08+04:00"
minimumUpdatePeriod="PT5S"
minBufferTime="PT5S"
timeShiftBufferDepth="PT0H0M0.00S"
suggestedPresentationDelay="PT10S"
profiles="urn:mpeg:dash:profile:isoff-live:2011">
<Period start="PT0S" id="dash">
<AdaptationSet
segmentAlignment="true"
maxWidth="768"
maxHeight="576"
maxFrameRate="24">
<Representation
id="video"
mimeType="video/mp4"
codecs="avc1.42c028"
width="768"
height="576"
frameRate="24"
sar="1:1"
startWithSAP="1"
bandwidth="641000">
<SegmentTemplate
presentationTimeOffset="0"
timescale="1000"
media="mystream-$Time$.m4v"
initialization="mystream-init.m4v">
<SegmentTimeline>
<S t="0" d="5888"/>
<S t="5888" d="6760"/>
<S t="12648" d="6000"/>
<S t="18648" d="8680"/>
<S t="27328" d="6545"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet
segmentAlignment="true">
<AudioChannelConfiguration
schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
value="1"/>
<Representation
id="audio"
mimeType="audio/mp4"
codecs="mp4a.40.2"
audioSamplingRate="48000"
startWithSAP="1"
bandwidth="125000">
<SegmentTemplate
presentationTimeOffset="0"
timescale="1000"
media="mystream-$Time$.m4a"
initialization="mystream-init.m4a">
<SegmentTimeline>
<S t="0" d="5888"/>
<S t="5888" d="6760"/>
<S t="12648" d="6000"/>
<S t="18648" d="8680"/>
<S t="27328" d="6545"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
Фрагменты
Фрагменты MPEG-DASH имеют формат mp4. Однако, это не совсем те mp4, которыми мы обычно пользуемся, это фрагментированные mp4. Обычный mp4 файл состоит из двух основных частей — метаданные и данные. Метаданные хранятся атоме
moov
, а данные — в атоме mdat
. Метаданные позволяют для каждого семпла узнать его таймстамп, длительность, размер, смещение относительно начала файла итд. Кроме того, в moov
хранится информация о кодеках и блок параметров кодеков, без которых невозможно декодирование потока.Фрагментированные mp4 устроены иначе. Атом
moov
хранится в отдельном инициализирующем фрагменте и содержит лишь общую информацию о потоке — параметры кодеков, размеры видео, частота дискретизации аудио итд. Каждый фрагмент, в свою очередь, состоит из двух атомов — moof
и mdat
. Атом метаданных фрагмента moof хранит информацию о семплах, находящихся в этом фрагменте. Формат moof существенно отличается от moov. Кроме того, в отсутствие параметров кодека фрагмент не может быть проигран как независимый mp4-файл.MPEG-DASH на сервере
Начиная с версии 1.0.8 в nginx-rtmp-module реализована поддержка вещания живых потоков в MPEG-DASH. Происходит это аналогично вещанию в HLS. В указанной директории создаются dash-фрагменты, а также файл манифеста. В процессе вещания старые фрагменты удалятся, новые появляются, плейлист обновляется.
Для сборки nginx с nginx-rtmp-module указываем его в
--add-module
./configure --add-module=/path/to/nginx-rtmp-module ...
После сборки настраиваем MPEG-DASH
rtmp {
server {
listen 1935;
# генерация dash-манифеста и фрагментов в /tmp/dash
application myapp {
live on;
dash on;
dash_path /tmp/dash;
}
}
}
...
http {
server {
listen 8080;
# отдача манифеста и фрагментов
location /dash {
root /tmp;
add_header Cache-Control no-cache;
}
}
}
Вот как выглядит срез MPEG-DASH потока с именем
mystream
# инициализирующие фрагменты
mystream-init.m4a
mystream-init.m4v
# текущие фрагменты
# формат имени: mystream-TIME.mp4X
# где TIME-таймстамп первого семпла
mystream-0.m4a
mystream-0.m4v
mystream-5888.m4a
mystream-5888.m4v
mystream-12648.m4a
mystream-12648.m4v
mystream-18648.m4a
mystream-18648.m4v
mystream-27328.m4a
mystream-27328.m4v
# манифест (плейлист)
mystream.mpd
# временные файлы для будущих фрагментов
mystream-raw.m4a
mystream-raw.m4v
MPEG-DASH в браузере
Основной инструмент, с помощью которого в настоящий момент реализуется проигрывание MPEG-DASH в браузерах — это плеер dash.js, являющийся референсной реализацией MPEG-DASH клиента и разрабатываемый организацией DASH Industry Forum. Плеер треует от браузера поддержки Media Source Extensions.
В настоящий момент плеер хорошо работает со статичным видео, однако с проигрыванием живых потоков у неего все еще есть определенные проблемы. Так, для поддержки live-вещаний в Chrome мне пришлось немного доработать плеер. Модифицированная версия лежит в бранче
live
моего форка проекта. Авторы плеера обещали в следующей версии полностью решить проблему с живыми вещаниями.Скачиваем и устанавливаем dash.js из форка
# скачаем dash.js в /var/www
cd /var/www
git clone https://github.com/arut/dash.js.git
cd dash.js
git checkout live
Открываем в редакторе baseline.html и находим строчку со стандартным урлом
url = "http://dash.edgesuite.net/envivio/dashpr/clear/Manifest.mpd",
Заменяем на наш урл
url = "http://localhost:8080/dash/mystream.mpd".
Добавляем локейшен в nginx для отдачи содержимиго dash.js, включая тестовую страницу
location /dash.js {
root /var/www;
}
Теперь запускаем вещание с именем mystream
ffmpeg -re -i ~/Videos/sintel.mp4 -c:v libx264 -profile:v baseline -c:a libfaac -ar 44100 -ac 2 -f flv rtmp://localhost/myapp/mystream
Далее заходим в браузер на страницу
http://localhost:8080/dash.js/baseline.html
. Здесь, вероятно, придется подождать несколько секунд пока не будет создан манифест вещания и обновить страницу.Браузеры
Для работы MPEG-DASH через dash.js браузер должен поддерживать Media Source Extensions API. Ситуация с поддержкой этих расширений постоянно улучшается, однако все еще не идеальна.
- Chrome (в т.ч. мобильный начиная с Android 4.2) — поддерживается в текущей версии
- IE — поддерживается с версии 11 начиная с Windows 8
- Firefox — не поддерживается. Разработчики обещают поддержку Media Source Extensions в ближайшие месяцы
- Safari — не поддерживается. Однако, Safari — единственный десктопный браузер, поддерживающий HLS.