HTML5 Audio — cостояние дел. Часть 1

http://html5doctor.com/html5-audio-the-state-of-play/
  • Перевод
(Написано в мае 2012 специалистом по фронтенду и особенно, по медиаформатам, разработчиком нескольких опенсорсных проектов и happyworm.com и отражает современное состояние дел с поддержкой браузерами новых медиатегов и форматов. --прим. перев.)

Это продолжение моей (автора, Марка Боаса) статьи 2009 года "Native Audio in the browser" (англ., и дополненной в октябре 2010 --прим. перев.), которая объясняет основы работы аудио в HTML5. Возможно, стоит почитать сначала её, если вы хотите почувствовать работу тега <audio> и связанного с ним API. (Есть русский перевод, но в варианте от 2009 года.)

Теперь, через 2.5 года, пришло время посмотреть, как идут дела. При том, что многие продвинутые аудио API активно разрабатываются, улучшается воодушевляющая нас нативная браузерная поддержка звука — самое время вернуться в увлекательный мир тега <audio>.

Хороший способ понять, как идут дела — посмотреть несколько примеров использования, что мы увидим далее.

Как же нам начать? Есть несколько понятий, которые надо освоить для подготовки. Давайте сначала разберёмся в типах MIME.

■ Типы MIME


● Серверная часть



Их называют ещё интернет медиа-типами — это один из способов сделать так, чтобы ваша система знала, как работать с медиаданными.

Прежде всего, сервер должен быть настроен для правильной поддержки MIME-типов. В случае Apache это означает, что в .htaccess имеются строки:
# AddType TYPE/SUBTYPE EXTENSION
AddType audio/mpeg mp3
AddType audio/mp4 m4a
AddType audio/ogg ogg
AddType audio/ogg oga
AddType audio/webm webma
AddType audio/wav wav

Совет: Не делайте gzip-сжатие медиафайлов на сервере. Большинство форматов уже сжаты, и есть некоторая поддержка для остальных. Кроме того, в запасном решении с флешем, он не поддерживает сжатия медиаданных.

● Клиентская часть



При описании источников данных в коде или разметке можно указать MIME-тип, который позволит браузеру определить данные правильно.

Самый надежный способ описать аудио HTML5 — примерно такой:
<audio>
   <source src="elvis.mp3" type='audio/mpeg; codecs="mp3"'>
   <source src="elvis.oga" type='audio/ogg; codecs="vorbis"'>
   <!-- здесь - добавить запасные варианты тегов -->
</audio>

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

Вместе с адресом данных в атрибуте src указан атрибут type. Он не обязателен, но помогает браузеру узнать MIME-тип и кодеки для отдаваемого файла до того как он его загрузит. Если его нет, браузер пытается узнать тип из файла возможными способами.
Замечание: можно пропустить в атрибуте название кодека, но для надежности и эффективности я рекомендую помогать браузеру, давая максимум возможной информации.
Отлично. Теперь мы знаем, как определить адрес файла, и браузер преспокойно выберет первый поддерживаемый им формат. А можем ли мы подать файл динамически?

● Заранее узнать тип аудио поможет .canPlayType (наверное)


К счастью, API показывает, поддерживается ли данный формат файла в браузере. Но вначале — краткое описание того, как мы управляем тегом <audio>.

Если объект Audio описывается в HTML, доступ к объекту можно получить через DOM:

var audio = document.getElementsByTagName('audio')[index];

или, если определён id,
var audio = document.getElementById('my-audio-id');

Как вариант, объект создаётся полностью на Javascript.
var audio = new Audio();

Если есть объект Audio, то есть доступ к его методам и свойствам. Для проверки поддержки форматов используют метод canPlayType с параметром — текстовым значением MIME-типа.
audio.canPlayType('audio/ogg');

Можно даже явно указать кодек:
audio.canPlayType('audio/ogg; codecs="vorbis"');


canPlayType возвращает одно из 3 значений:
1) probably,
2) maybe, или
3) "" (пустая строка).
Смысл получения этих странных типов истекает из общей странности ситуации, в которой находятся кодеки, пока мы судим о них по типу. Без реальной попытки воспроизведения браузер может только догадываться о применимости кодека.

Итого, для проверки поддержки делаем:
var audio = new Audio();
    var canPlayOgg = !!audio.canPlayType
        && audio.canPlayType('audio/ogg; codecs="vorbis"') != "";


Здесь проверяется что canPlayType поддерживается ("!!" просто превращает объект строки в логический тип) и затем проверяется, что canPlayType нашего формата — не пустая строка. (Как-то нелогично с первой частью. Наверное, автор забыл упомянуть, что может вернуть undefined? --прим. перев.)

■ Поддержка различных кодеков в браузере


Посмотрим, как поддерживаются кодеки в современных браузерах.
Кодеки десктопных браузеров:
Десктопные версии Номер Поддержка кодеков
Internet Explorer 9.0+ MP3, AAC
Chrome 6.0+ Ogg Vorbis, MP3, WAV (начиная с Chrome 9)
Firefox 3.6+ Ogg Vorbis, WAV
Safari 5.0+ MP3, AAC, WAV
Opera 10.0+ Ogg Vorbis, WAV
Кодеки мобильных:
Мобильные браузеры Версия Поддержка кодеков
Opera Mobile 11.0+ Device-dependent
Android 2.3+ Device-dependent
Mobile Safari (iPhone, iPad, iPod Touch) iOS 3.0+ MP3, AAC
Blackberry 6.0+ MP3, AAC
Хорошая новость — в том, что на момент написания статьи около 80% браузеров поддерживают HTML5 Audio.

Плохая новость — до сих пор нет договорённости об универсальной поддержке какого-либо кодека, поэтому сервер должен поддерживать и MP3, и Ogg Vorbis, чтобы максимально полно поддержать HTML5 Audio в браузерах.
Забавно: Android 2.2 поддерживает <video>, но не <audio>. Чтобы воспроизводить аудио, нужно использовать тег <video>.

● Контейнеры, форматы и расширения файлов (и снова эти MIME-типы)



Выше я упоминал об известных аудиоформатах, но технически мы должны работать с их форматом контейнера. (Контейнер может содержать более одного формата — например, MP4 может содержать AAC и AAC+.)
Container Format(s) File Extensions MIME Type Codec String
MP3 MP3 .mp3 audio/mpeg mp3
MP4 AAC, AAC+ .mp4, .m4a, .aac audio/mp4 mp4a.40.5
OGA/OGG Ogg Vorbis .oga, .ogg audio/ogg vorbis
WAV PCM .wav audio/wav 1

● Мы имеем <audio> и не боимся его использовать!



Ладно, мы кое-как запустили аудио-теги — и это работает. Что ещё хотелось бы сделать? Сейчас в каждом браузере элементы работают немного по-разному из-за настроек по умолчанию. Хочется немного подогнать их к единому виду. Для этого есть несколько свойств элемента <audio>.

Несколько самых используемых атрибутов:
Свойство Описание Возвращаемое значение
currentTime позиция курсора проигрывателя double (секунды)
duration длительность воспроизведения double (секунды); только чтение
muted заглушен ли звук boolean
paused остановлено ли воспроизведение boolean
volume уровень громкости double (от 0 до 1)
Использовать их крайне просто. Например:
var audio = new Audio();
var duration = audio.duration;

Переменной duration присвоено значение длительности (в секундах) аудиоклипа.

■ Буферизация, поиск и временны́е диапазоны


Ситуация на этом фронте улучшается, разработчики браузеров начинают делать основную часть спецификации.

API даёт нам атрибуты buffered и seekable, когда хотим узнать, какая часть медиафайла была буферизована или предзагружена для воспроизведения без задержек. Они оба возвращают объект TimeRanges, который есть список интервалов — числа начала и конца.

● Атрибут buffered



Возвращает интервалы полностью загруженных участков файла. Небольшой пример:
// возвращает объект TimeRanges буферизованного файла
var buffered = audio.buffered;
// выделяет время в секундах из сохранённого объекта TimeRange
var bufferedEnd = audio.buffered.end();


● Объект TimeRanges



The TimeRanges object contains data on the parts on buffered media in the form of one or more — you guessed it — time ranges. A TimeRanges object consists of these properties:

Содержит данные о частях буферизованных участков медиафайла (один или более — сколько успело буферизоваться) и имеет свойства:

  length — число интервалов,
  start(index) — начальное время указанного интервала,
  end(index) — конечное время указанного интервала
    (отсчитывается от начала воспроизведения).
Забавно: По умолчанию размерность времени в JS Audio API — секунды, хотя традиционные функции в JS используют миллисекунды.
------------------------------------------------------ //пример
|=============|                    |===========|     |
------------------------------------------------------
0             5                    15          19    21

Таким образом, в этом примере:
    audio.buffered.length //returns 2
    audio.buffered.start(0) //returns 0
    audio.buffered.end(0) //returns 5
    audio.buffered.start(1) //returns 15
    audio.buffered.end(1) //returns 19
    audio.buffered.end() //returns 19

В каких случаях может быть больше одного буферизованного интервала? Пользователь кликает впереди, на небуферизованном участке шкалы на блоке проигрывателя. Объект начинает новую буферизацию от точки клика, и возникают 2 интервала буферизации.
Совет: Большинство аудио-проигрывателей позволяет перемещаться на новые позиции файла во время загрузки, выполняя ряд запросов на сервер. В Apache множественный доступ к файлу разрешён по умолчанию, но надо убедиться в этом для сервера с неизвестными настройками.
Заметим, что если пользователь активно переключает точку воспроизведения, буферизация имеет мало смысла. Некоторые браузеры могут прочитать конец файла, чтобы установить длительность записи, почти сразу создавая 2 интервала буфера. Поэтому прогресс-бар в проигрывателе несколько сложнее обычного контрола прогресс-бара с 1 интервалом.

Вы можете проверить TimeRanges вашего браузера с помощью этого удобного HTML5 Media Event Inspector.

● Атрибуты seeking и seekable



Поиск в контексте медиафайла — это заглядывание вперёд или назад в медиафайл. Обычно это происходит, когда ещё не закончена полная буферизация файла. Атрибут seeking используется для указания на то, что призошло событие "seeked". true означает, что часть файла ещё не загружена.

Продолжение следует...

Примечание на сайте оригинала, html5doctor.com :

Эта статья написана Марком Боасом. Марк разрабатывает / преподает / описывает и продвигает новые и открытые веб-технологии. Сооснователь Happyworm — небольшой вебстудии, разрабатывающей, в частности, jPlayer Media Framework, он раздвигает возможности браузера с помощью HTML5 и JavaScript. Будучи универсалом в сердце, Марк большую часть времени занимается веб-медиа и протоколами реального времени. Любитель всего, относящегося к аудио, он сейчас страстно работает над задачей «сделать что-то новое» в его экспериментах в проекте Hyperaudio. Вы можете следить за твиттером Марка.

Содержание следующей части:

    ● Замечание о предзагрузке
    ● Успешно воспроизведённое
■ Медиа-события
■ Потоковое воспроизведение
■ Эволюция спецификаций (или «Вау, это дело движется!»)
  ● Метод load
  ● Когда браузеры вернутся к официальной документации?
    ● Автовоспроизведение и громкость
    ● Одновременное воспроизведение нескольких аудиотегов
    ● Зависимость от ОС
■ Что нового?
  ● Изменение шага
  ● Медиа-фрагменты
■ Расширенное аудио API: будущий звук в браузерах
■ Заключение
■ Литература

Местные статьи и переводы по теме аудиотегов HTML5:
* Визуализация аудио в HTML5, 7 августа 2011
* Создаем кассетный магнитофон при помощи HTML5 Audio, 13 июля 2012
* Обработка звука через Audio Data API, 30 августа 2010
* HTML5 Audio и Game Development: баги браузеров, проблемы и их решения, идеи, 6 августа 2010
* Освоение HTML5 тега audio, 21 июля 2012
* Проблемы с HTML5 <Audio>, 16 мая 2011
* Using HTML5 audio and video, last mod. 13 Jun 2012
Спасибо ShpuntiK за то, что он обратил внимание на полезность перевода этой статьи.

UPD: Перевод 2-й части.
Поделиться публикацией

Комментарии 15

    –4
    Совет: Не делайте gzip-сжатие медиафайлов на сервере. Большинство форматов уже сжаты, и есть некоторая поддержка для остальных. Кроме того, в запасном решении с флешем, он не поддерживает сжатия медиаданных.

    Не совсем соглашусь, никто не мешает в конфигурации сервера указать какие именно файлы сжимать (с каким расширением).
      +2
      Обожаю хабр. Как на лугу` — минус за минусом (или плюс за плюсом), главное аргументировать не надо.
        0
        Лотерея же
        +1
        А какие, по вашему мнению, медиафайлы надо сжимать gzip-ом?
          0
          *.wav еще не вышли из употребления, да и *.ogg вполне адекватно жмется.
            0
            Специально проверил ogg. Gzip даёт 99,6% compression ratio. Нафиг нужно?
            Непожатый wav в сети — даже не представляю такой сценарий.

            Оттого и минусы.
              0
              Дак надо же сразу объяснять!
        +1
        Вот это уже другое дело :) Полная, хорошая статья об audio, а не просто «обзорчик».
        Спасибо за перевод.
          0
          Забавно: Мобильный Safari игнорирует атрибут preload, который всегда в нём равен «none».

          ЕМНИП, не только Safari, но и некоторые другие мобильные браузеры. Логично, так как пользователь может попасть на трафик не желая того.
            +1
            Забавно: Мобильный Safari игнорирует атрибут preload, который всегда в нём равен «none».

            Обходится запуском видео на долю секунды и последующей остановкой. Аналогичное поведение у Chrome — при preload=auto он скачивает только первую порцию.
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Что ты, это ведь в разы удобнее JS-фреймворков-аудио-движков. Даже тэг свой появился.
                0
                У сервера неправильно прописан MIME тип для ogg (application/octet-stream), из-за этого Firefox не играет (в отличие от Оперы и Хрома). Может автор знает, как это исправить? Отредактировать .htaccess невозможно.

                Пробовал указывать тип как написано здесь — не помогает. Кстати, что за странный способ задания атрибутов:

                type='audio/ogg; codecs=«vorbis»'

                может type=«audio/ogg» codecs=«vorbis»?

                  0
                  Спасибо за статью, прочитал и сразу применил)

                  Написано, что Android 2.2 поддерживает тег <video<, но не <audio<. Чтобы воспроизводить аудио, нужно использовать тег <video<.

                  Использую конструкцию вида <video style=«display:none;» src=«file.pm3»<</video<. Все работает отлично, но меня смущает только то, что ни в одном рассмотреном мной аудиоплеере не используется сег <video<, только <audio<. Есть ли какой-то подвох? Спасибо!
                    0
                    Боже ш ты мой, что такое с форматированием?

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое