(Статья специалиста по фронтенду и медиатегам Марка Боаса (Mark Boas) от 8 мая 2012. Перевод заключительной части. Начало дало понять, что придётся попотеть, прежде чем освоить всю кухню, а ведь это ещё развивается… Не ждите коротких рецептов.)
Содержание первой части:
■ Типы MIME
● Серверная часть
● Клиентская часть
■ Заранее узнать тип аудио поможет .canPlayType (наверное)
■ Текущая поддержка кодеков в браузерах
■ Форматы контейнеров и расширения файлов
■ Мы имеем тег <audio> и не боимся его использовать!
■ Буферизация, поиск и интервалы воспроизведения
● Атрибут buffered
● Объект TimeRanges
  ● Атрибуты seeking и seekable
Поиск в контексте медиафайла — это заглядывание вперёд или назад в медиафайл. Обычно это происходит, когда ещё не закончена полная буферизация файла. Атрибут seeking используется для указания на то, что произошло событие "seeked". true означает, что часть файла ещё не загружена.
Напомним, что свойство buffered говорит, какие части были загружены, что часто используется как индикатор готовности воспроизведения. Если браузер поддерживает, то может иметь смысл использовать атрибут seekable, чтобы определить, какая часть файла подгружена.
seekable возвращает объект TimeRanges — интервалы, которые готовы для немедленного воспроизведения. Он использует технологию, известную как «byte-range-запросы», позволяющую запрашивать часть данных не строго по окончанию HTTP-запросов, а раньше, пока ещё идут запросы. Другими словами, мы не должны иметь все данные, чтобы начать проигрывать медиа. Примеры:
Обратите внимание, что участки воспроизведения в состоянии "seekable" отличны от участков в состоянии "buffered". Они не могут быть тем и другим одновременно.
Буферизация и поиск данных могут дать полезную информацию, но это было бы слишком просто, если бы не несколько моментов.
1. Предзагрузка не поддерживается в умеренно старых браузерах (Opera 10 / Firefox 3.6).
2. Атрибут buffered не всегда поддерживается (Blackberry PlayBook).
3. Не все HTML5-браузеры поддерживают byte-range-поиск, например, Safari / Windows. В этом случае остаётся поиск по загруженному содержимому, как это делает Flash.
Если вы хотите дать пользователям наилучшее решение, делайте тест заложенных возможностей.
Я упомянул об атрибуте preload в предыдущей статье (англ.). Он принимает 3 возможных значения:
1. none — ничего не предзагружает. Ждите события play перед загрузкой чего-либо.
2. metadata — предзагружает только метаданные. Получает начало и конец файла через запрос интервала и определяет длительность воспроизведения.
3. auto — предзагружает весь файл. Получает начало и конец файла, а затем переходит снова к загрузке от начала файла.
Когда заходит речь о предзагрузке, помните, что это — просьба или пожелание браузеру о том, как вы хотите видеть процесс предзагрузки. Браузеры не обязаны её выполнять, поэтому могут работать по-разному.
Надо заметить, что есть свойство played, сообщающее, были ли воспроизведены интервалы полностью.
В основе API аудио- и видеоинтерфейсов лежит полный набор событий. Полный список имеется в WhatWG версии спецификации.
Установка обработчиков медиа-событий позволяет легко отслеживать изменения состояния контролов. Например, это полезно для обновления показа времени воспроизведения при каждом событии timeupdate.
Краткий список частоиспользуемых событий:
Некоторые другие события:
И снова HTML5 Media Event Inspector ведёт себя дружественно.
Вы можете протестировать поддержку браузера с помощью areweplayingyet.org. Стоит посмотреть код и тесты, чтобы понять механизм происходящего.
Потоковое аудио — это общее требование к медиа-конторолу. До недавнего времени в этой области господствовали флеш-технологии Adobe. Хорошо известны проприетарные серверные технологии. Одна из ведущих — Real Time Messaging Protocol (RTMP) от Adobe. Тем не менее, современные браузеры поддерживают только потоковое воспроизведение на протоколе HTTP, а что-либо похожее на флеш требует выполнения RTMP-потоков.
Сейчас браузеры, если поддерживают, то только SHOUTcast и Icecast серверы, которые воспроизводят аудио через HTTP. SHOUTcast проприетарен и воспроизводит только файлы MP3 и AAC, а Icecast открыт и поддерживает Ogg Vorbis, MP3 и AAC.
Поскольку спецификации аудио развиваются, есть несколько несоответствий в браузерных реализациях, которые стоит иметь в виду. Они обычно проявляются в старых браузерах.
До недавнего времени метод load сообщал браузеру об изменении медиафайла и заставлял контрол измениться. Сейчас он выполняет сброс элемента и начинает выборку и загрузку нового ресурса с нуля.
Таким образом, для старых браузеров типа Firefox 3.6, чтобы изменить источник информации, нужно не только изменить значение в методе, но и выполнить команды:
Для кроссбраузерных решений полезно знать, какие браузеры поддерживают W3C документацию и в какой степени и как от неё отклоняются.
iOS и Blackberry игнорируют атрибут autoplay и медиаэлемент изменения громкости, а Android поддерживает autoplay, но не имеет элемента громкости.
По сути, на Blackberry и IOS автозапуск отключён, поскольку обе системы требуют пользовательского разрешения «пнуть» их. Это неудачный побочный эффект: любое проигрывание аудио страдает необходимой задержкой интерактивности.
Чтобы сгладить эти неудобства, вы можете познакомиться с отличной статьёй доктора Remy Sharp об исправлении аудио-спрайтов в iOS (англ.).
Особо досаждает разработчикам всего (особенно игр), кроме самых простых приложений, невозможность некоторых браузеров (снова видим парочку: iOS и BlackBerry) играть несколько дорожек одновременно.
Safari (5+) опирается на настройки Quicktime. Это редко бывает проблемой, если используется Windows.
Internet Explorer (9+) использует кодеки операционной системы. Так как он работает только на Windows, к счастью, это почти всегда так.
Для веб-аудио уточняются некоторые новые возможности и новое API, поэтому давайте посмотрим на ближайшее будущее.
Отметим пару будущих функций: playbackRate и defaultPlaybackRate. Они изменяют скорость и направление воспроизведения — для быстрой перемотки вперед и назад функции, или, возможно, позволит пользователям настроить скорость слушания, чтобы прослушивать больше подкастов в день.
● audio.playbackRate возвращает 1 при нормальной скорости и действует как множитель скорости. Например, установка playbackRate 2 удвоит скорость, при установке его в -1, будет игра в обратном направлении.
● audio.defaultPlaybackRate — скорость медиа по умолчанию после паузы, рестарта или события этого рода.
Если мы хотим сейчас сослаться на часть медиафайла, мы, чаще всего, должны загрузить хотя бы часть файла, которая на самом деле не нужна. Предложения W3C для медиа-фрагментов были созданы, чтобы решить этот вопрос и другие, например, поиск области видео или просто связанные тексты (аудиотеги, надписи) треков. Для аудио мы сможем сказать с помощью параметров URI, какие части хотим загрузить.
Когда дело дошло до продвинутого аудио, Mozilla впервые ввела в бой начальное экспериментальное Audio Data API для Firefox. Это должно помочь работе с аудио на JavaScript и создать платформу для низкоуровневых разработок.
Чтобы не отстать, Google выпустила Web Audio API для Chrome и выдвинула его как предложение W3C. Web Audio API — это высокоуровневая реализация, которая использует подход к объектам аудио как к аудио-нодам и предоставляет множество полезных функций.
Обе реализации отражают желание разработчиков делать с аудио больше — создавать, управлять, анализировать и смешивать аудио на лету. По сути, мы в один прекрасный день можем оказаться в состоянии сделать в браузере то, что можем делать сейчас лишь в нативных приложениях ОС.
Так что, хотим мы работать с продвинутым аудио в браузере? Хорошо, две отдельных реализации уже есть. Если хотим писать приложения на базе API, нужно делать сторонние кросс-библиотеки, чтобы абстрагироваться от различий.
Появилось и довольно новое Mozilla MediaStream обработки API, которое использует другой подход с возможностью управлять аудио- и видео-потоками как на высоком, так и на низком уровне.
На самом деле, с использованием современных API, пользуясь скоростью современных движков JavaScript, мы можем даже написать декодеры для неподдерживаемых кодеков. В настоящее время мы имеем JSMad декодер MP3 и декодер без потерь Alac.js. Видимо, FLAC и AAC в потоке. Есть надежда, то, что в будущем нам не придется беспокоиться о поддержке форматов в браузере.
Для интересующихся современным интернет-аудио я писал о различиях в подходах и различных библиотеках для кроссбраузерных решений в статье "HTML5 Audio API: как низко можем мы идти?" (англ.).
Хорошая новость — то, что заинтересованные стороны договариваются, идёт общение в рабочей группе W3C по аудио. Похоже, всё идет к реализации идей единого аудио API, который стремительно приближается к публикации в виде веб-стандарта.
Хотя браузерные реализации текущей спецификации HTML5 аудио улучшаются, есть еще несколько проблем, мешающих созданию полноценного кроссбраузерного решения. Вам нужно знать ограничения браузеров и платформ, таких как iOS. Проблемы, будем надеяться, исчезнут.
Есть хорошие новости с фронта «продвинутого аудио»: новый стандарт создается, мы близки к получению единой спецификации для работы создателей браузеров. В то же время, есть библиотеки JavaScript, которые помогут преодолеть разрыв между существующими реализациями.
Есть и признаки того, что мы можем видеть конец зависимостей различных браузеров от кодеков. Opera Mobile уже поддерживает форматы MP3 там, где его поддерживает ОС, и похоже, что Mozilla тоже может себе это позволить. Если это становится возможно для мобильных браузеров, скорее всего, настольные браузеры последуют примеру.
Многое меняется и многое уже достигнуто. Неровности реализаций сглаживаются, принимаются стандарты, и мы видим основу очень интересных новых технологий.
Будущее интернет-аудио выглядит блестящим!
Содержание первой части:
■ Типы MIME
● Серверная часть
● Клиентская часть
■ Заранее узнать тип аудио поможет .canPlayType (наверное)
■ Текущая поддержка кодеков в браузерах
■ Форматы контейнеров и расширения файлов
■ Мы имеем тег <audio> и не боимся его использовать!
■ Буферизация, поиск и интервалы воспроизведения
● Атрибут buffered
● Объект TimeRanges
  ● Атрибуты seeking и seekable
● Атрибуты seeking и seekable
Поиск в контексте медиафайла — это заглядывание вперёд или назад в медиафайл. Обычно это происходит, когда ещё не закончена полная буферизация файла. Атрибут seeking используется для указания на то, что произошло событие "seeked". true означает, что часть файла ещё не загружена.
Забавно: все современные браузеры, кроме Safari / Windows, имеют атрибут seekable, означающий, что событие seeking никогда не произойдёт, чтобы пользователь мог перейти непосредственно к желаемой части программы. Событие seeked не появляется, что раздражает некоторых, считающих, что "seeking==true" должно быть всегда раньше события seeked. |
seekable возвращает объект TimeRanges — интервалы, которые готовы для немедленного воспроизведения. Он использует технологию, известную как «byte-range-запросы», позволяющую запрашивать часть данных не строго по окончанию HTTP-запросов, а раньше, пока ещё идут запросы. Другими словами, мы не должны иметь все данные, чтобы начать проигрывать медиа. Примеры:
var isSeeking = audio.seeking; // в плеере можно сделать "поиск"?
// Есть интервалы seekable, значит, есть участки для "поиска"
var isSeekable = audio.seekable && audio.seekable.length > 0;
// Время в секундах, после которого участок медиа не загружен
var seekableEnd = audio.seekable.end();
Замечание: интервалы могут ввести в заблуждение. audio.seekable.end() на самом деле, указывает конечную точку последнего интервала, а не конечную точку всего медиафайла. На практике, однако, этого достаточно, так как браузер либо дает ряд запросов, либо нет. Если окажется, что запросов не было, audio.seekable будет равносильно audio.buffered, что даст правильное указание конца интервалов в файле. |
Забавно: На практике создаётся только один TimeRanges-объект в свойстве seekable. В браузерах, поддерживающих запросы интервалов, TimeRanges-объект простирается от нуля до конца времени воспроизведения, в неподдерживающих — TimeRanges растёт от нуля до конца по мере загрузки. |
1. Предзагрузка не поддерживается в умеренно старых браузерах (Opera 10 / Firefox 3.6).
2. Атрибут buffered не всегда поддерживается (Blackberry PlayBook).
3. Не все HTML5-браузеры поддерживают byte-range-поиск, например, Safari / Windows. В этом случае остаётся поиск по загруженному содержимому, как это делает Flash.
Если вы хотите дать пользователям наилучшее решение, делайте тест заложенных возможностей.
● Замечание о предзагрузке
Я упомянул об атрибуте preload в предыдущей статье (англ.). Он принимает 3 возможных значения:
1. none — ничего не предзагружает. Ждите события play перед загрузкой чего-либо.
2. metadata — предзагружает только метаданные. Получает начало и конец файла через запрос интервала и определяет длительность воспроизведения.
3. auto — предзагружает весь файл. Получает начало и конец файла, а затем переходит снова к загрузке от начала файла.
Забавно: мобильный Safari игнорирует атрибут preload, который всегда в нём равен "none". |
● Успешно воспроизведённое
Надо заметить, что есть свойство played, сообщающее, были ли воспроизведены интервалы полностью.
var played = audio.played; // возвращает объект TimeRanges
Замечание: если просуммировать все интервалы audio.played, то получим долю прослушанного аудио, что может быть полезно для сбора метрик. |
■ Медиа-события
В основе API аудио- и видеоинтерфейсов лежит полный набор событий. Полный список имеется в WhatWG версии спецификации.
Установка обработчиков медиа-событий позволяет легко отслеживать изменения состояния контролов. Например, это полезно для обновления показа времени воспроизведения при каждом событии timeupdate.
Краткий список частоиспользуемых событий:
Событие |
Описание |
---|---|
durationchange |
Обновлён атрибут duration |
ended |
Воспроизведение остановлено по достижению конца |
pause |
Воспроизведение было остановлено (обратите внимание на отсутствие события stop) |
play |
Файл начал проигрываться |
timeupdate |
Текущая позиция воспроизведения изменилась (обычно каждые 250 мс) |
volumechange |
Значение изменилось |
Совет: Android (по крайней мере, 2.3) не всегда порождает событие ended. Ладно, скажем так, он иногда создаёт одно для приличия, но вообще, вы должны создать своё собственное событие, захватывая событие pause при достижении конца медиафайла и сравнение audio.currentTime с audio.duration. Или же можете сушать событие pause и убедиться, что audio.currentTime равно нулю. Чтобы быть абсолютно уверенным, надо проделывать то и другое. |
Событие |
Описание |
---|---|
canplay |
Файл может быть воспроизведен, но, возможно, потребуется пауза, пока он загружается. |
canplaythrough |
При имеющемся темпе скачивания предполагается, что файл может быть проигран от начала до конца без перерыва. |
progress |
Браузер показывает состояние проигрывания (обычно каждые 250 мс) |
Вы можете протестировать поддержку браузера с помощью areweplayingyet.org. Стоит посмотреть код и тесты, чтобы понять механизм происходящего.
■ Потоковое воспроизведение
Потоковое аудио — это общее требование к медиа-конторолу. До недавнего времени в этой области господствовали флеш-технологии Adobe. Хорошо известны проприетарные серверные технологии. Одна из ведущих — Real Time Messaging Protocol (RTMP) от Adobe. Тем не менее, современные браузеры поддерживают только потоковое воспроизведение на протоколе HTTP, а что-либо похожее на флеш требует выполнения RTMP-потоков.
Сейчас браузеры, если поддерживают, то только SHOUTcast и Icecast серверы, которые воспроизводят аудио через HTTP. SHOUTcast проприетарен и воспроизводит только файлы MP3 и AAC, а Icecast открыт и поддерживает Ogg Vorbis, MP3 и AAC.
Поток |
AAC |
MP3 |
Ogg Vorbis |
Встроенная поддержка |
---|---|---|---|---|
Icecast |
Да |
Да |
Да |
Да |
SHOUTCast |
Да |
Да |
Нет |
Да |
RTMP |
Да |
Да |
Нет |
Нет (требуется Flash) |
■ Эволюция спецификаций (или «Ти диви! Воно ще й рухається!»)
Поскольку спецификации аудио развиваются, есть несколько несоответствий в браузерных реализациях, которые стоит иметь в виду. Они обычно проявляются в старых браузерах.
● Метод load
До недавнего времени метод load сообщал браузеру об изменении медиафайла и заставлял контрол измениться. Сейчас он выполняет сброс элемента и начинает выборку и загрузку нового ресурса с нуля.
Таким образом, для старых браузеров типа Firefox 3.6, чтобы изменить источник информации, нужно не только изменить значение в методе, но и выполнить команды:
var audio = new Audio();
audio.setAttribute("src","mynew.mp3"); audio.load(); // требуется для старых браузеров
● Когда браузеры вернутся к официальной документации?
Для кроссбраузерных решений полезно знать, какие браузеры поддерживают W3C документацию и в какой степени и как от неё отклоняются.
● Автовоспроизведение и громкость
iOS и Blackberry игнорируют атрибут autoplay и медиаэлемент изменения громкости, а Android поддерживает autoplay, но не имеет элемента громкости.
По сути, на Blackberry и IOS автозапуск отключён, поскольку обе системы требуют пользовательского разрешения «пнуть» их. Это неудачный побочный эффект: любое проигрывание аудио страдает необходимой задержкой интерактивности.
Чтобы сгладить эти неудобства, вы можете познакомиться с отличной статьёй доктора Remy Sharp об исправлении аудио-спрайтов в iOS (англ.).
● Одновременное воспроизведение нескольких аудиотегов
Особо досаждает разработчикам всего (особенно игр), кроме самых простых приложений, невозможность некоторых браузеров (снова видим парочку: iOS и BlackBerry) играть несколько дорожек одновременно.
● Зависимость от ОС
Совет: несмотря на ограниченное использование такого способа разработчиками, вы можете установить другие, не встроенные в ОС кодеки, как, например, Ogg Vorbis, и браузеры, использующие кодеки операционной системы, должны начать поддерживать их. |
Internet Explorer (9+) использует кодеки операционной системы. Так как он работает только на Windows, к счастью, это почти всегда так.
■ Что нового?
Для веб-аудио уточняются некоторые новые возможности и новое API, поэтому давайте посмотрим на ближайшее будущее.
● Изменение шага
Отметим пару будущих функций: playbackRate и defaultPlaybackRate. Они изменяют скорость и направление воспроизведения — для быстрой перемотки вперед и назад функции, или, возможно, позволит пользователям настроить скорость слушания, чтобы прослушивать больше подкастов в день.
● audio.playbackRate возвращает 1 при нормальной скорости и действует как множитель скорости. Например, установка playbackRate 2 удвоит скорость, при установке его в -1, будет игра в обратном направлении.
● audio.defaultPlaybackRate — скорость медиа по умолчанию после паузы, рестарта или события этого рода.
● Медиа-фрагменты
Если мы хотим сейчас сослаться на часть медиафайла, мы, чаще всего, должны загрузить хотя бы часть файла, которая на самом деле не нужна. Предложения W3C для медиа-фрагментов были созданы, чтобы решить этот вопрос и другие, например, поиск области видео или просто связанные тексты (аудиотеги, надписи) треков. Для аудио мы сможем сказать с помощью параметров URI, какие части хотим загрузить.
■ Расширенное аудио API: будущий звук в браузерах
Когда дело дошло до продвинутого аудио, Mozilla впервые ввела в бой начальное экспериментальное Audio Data API для Firefox. Это должно помочь работе с аудио на JavaScript и создать платформу для низкоуровневых разработок.
Чтобы не отстать, Google выпустила Web Audio API для Chrome и выдвинула его как предложение W3C. Web Audio API — это высокоуровневая реализация, которая использует подход к объектам аудио как к аудио-нодам и предоставляет множество полезных функций.
Обе реализации отражают желание разработчиков делать с аудио больше — создавать, управлять, анализировать и смешивать аудио на лету. По сути, мы в один прекрасный день можем оказаться в состоянии сделать в браузере то, что можем делать сейчас лишь в нативных приложениях ОС.
Так что, хотим мы работать с продвинутым аудио в браузере? Хорошо, две отдельных реализации уже есть. Если хотим писать приложения на базе API, нужно делать сторонние кросс-библиотеки, чтобы абстрагироваться от различий.
Появилось и довольно новое Mozilla MediaStream обработки API, которое использует другой подход с возможностью управлять аудио- и видео-потоками как на высоком, так и на низком уровне.
На самом деле, с использованием современных API, пользуясь скоростью современных движков JavaScript, мы можем даже написать декодеры для неподдерживаемых кодеков. В настоящее время мы имеем JSMad декодер MP3 и декодер без потерь Alac.js. Видимо, FLAC и AAC в потоке. Есть надежда, то, что в будущем нам не придется беспокоиться о поддержке форматов в браузере.
Для интересующихся современным интернет-аудио я писал о различиях в подходах и различных библиотеках для кроссбраузерных решений в статье "HTML5 Audio API: как низко можем мы идти?" (англ.).
Хорошая новость — то, что заинтересованные стороны договариваются, идёт общение в рабочей группе W3C по аудио. Похоже, всё идет к реализации идей единого аудио API, который стремительно приближается к публикации в виде веб-стандарта.
■ Заключение
Хотя браузерные реализации текущей спецификации HTML5 аудио улучшаются, есть еще несколько проблем, мешающих созданию полноценного кроссбраузерного решения. Вам нужно знать ограничения браузеров и платформ, таких как iOS. Проблемы, будем надеяться, исчезнут.
Есть хорошие новости с фронта «продвинутого аудио»: новый стандарт создается, мы близки к получению единой спецификации для работы создателей браузеров. В то же время, есть библиотеки JavaScript, которые помогут преодолеть разрыв между существующими реализациями.
Есть и признаки того, что мы можем видеть конец зависимостей различных браузеров от кодеков. Opera Mobile уже поддерживает форматы MP3 там, где его поддерживает ОС, и похоже, что Mozilla тоже может себе это позволить. Если это становится возможно для мобильных браузеров, скорее всего, настольные браузеры последуют примеру.
Многое меняется и многое уже достигнуто. Неровности реализаций сглаживаются, принимаются стандарты, и мы видим основу очень интересных новых технологий.
Будущее интернет-аудио выглядит блестящим!