Как программно определить, поддерживает ли браузер HTML5 Audio/Video и нужные форматы/кодеки
В продолжение темы работы с аудио и видео в HTML5 хочу остановиться на еще одном важном аспекте — программной вставке аудио и видео через JavaScript, и, если быть точнее, программном (через JavaScript) определении поддержки медиа-элементов и различных форматов и кодеков.
Хотя многие библиотеки добавляют свои обертки, упрощающую эту задачу, важно также понимать, что там происходит внутри.
Определение поддержки аудио и видео
Начнем с простой задачи: как понять, поддерживает ли браузер пользователя вставку аудио- и видео-элементов?
Для решения этой задачи достаточно попытаться создать новый элемент с соответствующим тегом и посмотреть на результат:
var audio = document.createElement("audio");
// audio
/* [object HTMLAudioElement] {
autobuffer : false,
autoplay : false,
buffered : [object TimeRanges],
controls : false,
currentSrc : "",
currentTime : 0,
defaultPlaybackRate : 1,
duration : NaN,
ended : false,
error : null ... }
*/
В случае, если браузер поддерживает аудио или видео-элементы, результатом создания нового элемента, согласно спецификации, должен быть объект типа HTMLAudioElement (HTMLVideoElement для видео).
audio instanceof HTMLAudioElement;// true
(Если браузер поддерживает создание новых элементов, в том числе с произвольным названием, но не умеет поддерживать конкретный тип элемента, то результатом будет объект HTMLUnknownElement. Для старых браузеров это может быть не верно — и результатом будет объект какого-нибудь другого типа или просто Object с некоторыми свойствами, характерными для HTML-элементов.)
На этом этапе должно быть очевидно, что в принципе, достаточно через блок try-catch проверять поддержку браузером объекта HTMLAudioElement или HTMLVideoElement соответственно.
var videoSupported = false;try { HTMLVideoElement;
videoSupported = true;} catch (e) {};videoSupported;// IE9 - true// IE8 - false
Но если вы хотите использовать созданный медиа-элемент дальше, то пример, приведенный в начале, выглядит более практичным вследствие трюка, который мы увидим в следующем разделе.
Определение поддержки формата/кодека
К этому моменту мы уже научились определять, поддерживает ли браузер медиа-элементы. Следующая возникающая проблема — понять, какие кодеки (форматы медиа-файлов) поддерживает браузер.
Напомню, что на сегодня эта картина весьма драматична и единого согласия хотя бы по одному общему формату для “аудио и для видео из коробки”, в общем-то, нет. В случае, если вы вставляете аудио или видео декларативно, вы можете сразу указать альтернативы, переложив задачу выбора на плечи самого браузера.
Чтобы решить эту задачу программно, в медиа-элементах есть специальный метод, общий для аудио и видео (формально, HTMLAudioElement и HTMLVideoElement оба реализуют интерфейс HTMLMediaElement), — canPlayType(), принимающий в качестве параметра строку описания типа медиа-файла.
var support = videoElement.canPlay
Type('video/x-new-fictional-format;codecs="kittens,bunnies"');
Если браузер знает, что он не поддерживает данный формат, например, из-за того, что он не умеет работать с указанным типом контейнера или нужного кодека нет в его списке поддерживаемых кодеков, — он должен вернуть пустую строку.
Пустая строка также возвращается, если в качестве типа указан “application/octet-stream” — общий mime-тип для бинарных файлов.
Если браузер уверен, что он сможет проиграть медиа-файл в заданном формате, он возвращает “probably”. В остальных случаях возвращается “maybe”.
Разница между “probably” и “maybe” может быть неочевидной, особенно с учетом близости значений двух слов (по крайней мере, в русском языке).
На языке спецификации, надо понимать два ключевых момента:
- И “probably” и “maybe” — это вероятностные вещи. Конечно, вы не получите числового выражения от 0 до 1 для каждого из этих значений, но важно понимать, что ни одно из них не равно 1.
- Ключевой момент различия между “probably” и “maybe” заключается в том, что если указан формат и известно, что для этого формата могут быть разные кодеки, но кодек не указан, браузер никогда не должен возвращать “probably” — он вернет “maybe”, так как могут быть комбинации кодеков, которые он не поддерживает.
Например, вот так это выглядит для IE9:
video.canPlayType('video/x-new-fictional-format;codecs="kittens,bunnies"');
// "" video.canPlayType('video/mp4');
// "maybe" video.canPlayType('video/mp4;codecs="avc1.42E01E, mp4a.40.2"');
// "probably" video.canPlayType('video/mp4; codecs="avc1.58A01E, mp4a.40.2"');
// "probably" video.canPlayType('video/mp4; codecs="mp4v.20.8, mp4a.40.2"'); // ""
Важная деталь, о которой важно помнить, заключается также в том, что сервер, который отдает вам медиа-файлы, должен быть корректно настроен, то есть отдавать видео и аудио с правильным mime-type. В противном случае, из соображений безопасности, браузер может блокировать работу с этими файлами.
Например, для IIS это можно проверить в панели управления и добавить недостающие форматы там же или через web.config:
<system.webServer>
<staticContent>
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
<mimeMap fileExtension=".m4v" mimeType="video/m4v" />
<mimeMap fileExtension=".webm" mimeType="video/webm" />
</staticContent>
</system.webServer>
Теперь, возвращаемся к обещанному трюку. Учитывая, что метод canPlayType есть только у медиа-элементов (в отличие от остальных типов элементов), его наличие является хорошим способом определить, что созданный элемент является именно медиа-элементом.
На практике проверку поддержки медиа-элементов и поддержки нужных форматов часто объединяют в общее выражение, которое к тому же оказывается короче, чем длинный поэтапный путь:
var audio = document.createElement("audio");
if (audio != null && audio.canPlayType && audio.canPlayType("audio/mpeg"))
{
audio.src = "audio/sample.mp3";
audio.play();
}
Наконец, давайте посмотрим, как проверка поддержка аудио и видео осуществляется через популярную библиотеку Modernizr. (Для любителей ASP.NET MVC напомню, что она также включена в состав ASP.NET MVC 3.)
Использование Modernizr
Для начала, давайте я приведу внутренний код из библиотеки — исходя из изложенного выше, вам в нем практически все должно быть сходу понятно.
Проверка поддержки аудио-элемента и популярных кодеков:
tests['audio'] = function() {
var elem = document.createElement('audio'), bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"');
bool.mp3 = elem.canPlayType('audio/mpeg;');
bool.wav = elem.canPlayType('audio/wav; codecs="1"');
bool.m4a = elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;');
}
}
catch(e) { } return bool; };
Проверка поддержки видео-элемента и популярных кодеков:
tests['video'] = function() {
var elem = document.createElement('video'), bool = false;
try {
if ( bool = !!elem.canPlayType ) {
bool = new Boolean(bool);
bool.ogg = elem.canPlayType('video/ogg; codecs="theora"');
// Workaround required for IE9, which doesn't
// report video support without audio codec specified.
// bug 599718 @ msft connect
var h264 = 'video/mp4; codecs="avc1.42E01E';
bool.h264 = elem.canPlayType(h264 + '"') || elem.canPlayType(h264 + ', mp4a.40.2"');
bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"');
}
} catch(e) { }
return bool;
};
(Про упоминаемый баг IE9 — надеюсь, в Modernizr это обновят, т.к. в финальной версии IE9 это давно поправлено.;)
Из приведенных примеров должен быть очевиден способ использования библиотеки для определения поддержки аудио/видео и соответствующих кодеков:
if (Modernizr.audio) {
var audio = new Audio();
audio.src = Modernizr.audio.mp3 ? 'background.mp3' :
Modernizr.audio.ogg ? 'background.ogg' :
'background.m4a';
audio.play();
} else {
// Ooops.
}
Другие тонкости использования медиа-элементов HTML5 мы рассмотрим как-нибудь в другой раз ;)
|