Недавно одна клиентка попросила меня создать доступный видеоплеер, и одна из функций, которые она очень хотела иметь, — это описания аудио . Аудио описания предназначены для людей, которые являются слепыми или имеют слабое зрение, предоставляя дополнительную устную информацию для описания важных визуальных деталей.
Традиционно аудио-описанные видео должны быть сделаны специально, с аудио, закодированным в отдельной дорожке одного видеофайла. Для кодирования этих звуковых дорожек требуется довольно специализированное оборудование для редактирования видео, что поднимает планку для большинства производителей контента за пределы практического уровня.
Весь аудио-описанный контент, который я видел в Интернете, выглядит следующим образом. Например, BBC iPlayer имеет выбор такого контента , но видеоплеер не дает вам контролировать относительную громкость, и вы не можете отключить аудио-описания — вы можете смотреть только отдельные описанные или неописанные версии программы.
Введите HTML5
Спецификация видео HTML5 действительно предоставляет объект audioTracks
Но его поддержка браузера практически отсутствует — на момент написания этой функции поддерживает только IE10 .
В любом случае, что хотел мой клиент, это аудио описания в отдельном файле , которые можно было добавить к видео без необходимости создания отдельной версии, и которые было бы легко сделать без специального программного обеспечения. И конечно, это должно было работать в приличном диапазоне браузеров.
Поэтому моей следующей мыслью было использование MediaController , который является функцией аудио и видео HTML5, которая позволяет синхронизировать несколько источников. Однако поддержка браузера для этого одинаково скудна — на момент написания этой функции поддерживает только Chrome.
Но вы знаете — даже без этой поддержки, очевидно, не проблема запустить два медиа-файла одновременно, это всего лишь случай их синхронизации . Итак, можем ли мы использовать существующие, широко реализованные функции, чтобы сделать эту работу?
Видео События
Видео API предоставляет ряд событий, которые мы можем подключить, что должно позволить синхронизировать воспроизведение аудио с событиями из видео:
- Событие
"play"
- Событие
"pause"
-
"ended"
-
"timeupdate"
Это событие "timeupdate"
Частота, с которой он стреляет, не указана, и на практике она значительно варьируется — но, как грубое общее среднее значение, она составляет 3-5 раз в секунду, что достаточно для наших целей.
Я видел подобный подход, когда пытались синхронизировать два видеофайла , но он не особенно успешен, потому что даже крошечные расхождения очень очевидны. Но описания аудио, как правило, не должны быть настолько точными в синхронизации — задержка в 100ms
Поэтому все, что нам нужно сделать, это использовать имеющиеся у нас видео события, чтобы заблокировать аудио и видео воспроизведение вместе:
- Когда видео воспроизводится, воспроизводите аудио.
- Когда видео приостановлено, приостановите воспроизведение звука.
- Когда видео заканчивается, приостановите видео и аудио вместе.
- Когда время обновится, установите время звука, соответствующее времени видео, если они отличаются.
После некоторых экспериментов я обнаружил, что наилучшие результаты достигаются при сравнении времени в целых секундах, например:
if(Math.ceil(audio.currentTime) != Math.ceil(video.currentTime))
{
audio.currentTime = video.currentTime;
}
Это кажется нелогичным, и изначально я предполагал, что нам потребуется столько точности, сколько предоставляют данные, но, похоже, это не так. Протестировав его, используя буквальную аудиокопию саундтрека видео (т. Е. Звук и видео воспроизводят идентичный звук), легко услышать, хорошая или плохая синхронизация. Экспериментируя на этой основе, я получил гораздо лучшую синхронизацию при округлении цифр, чем нет.
Итак, вот последний сценарий. Если браузер поддерживает MediaController
var video = document.getElementById('video');
var audio = document.getElementById('audio');
if(typeof(window.MediaController) === 'function')
{
var controller = new MediaController();
video.controller = controller;
audio.controller = controller;
}
else
{
controller = null;
}
video.volume = 0.8;
audio.volume = 1;
video.addEventListener('play', function()
{
if(!controller && audio.paused)
{
audio.play();
}
}, false);
video.addEventListener('pause', function()
{
if(!controller && !audio.paused)
{
audio.pause();
}
}, false);
video.addEventListener('ended', function()
{
if(controller)
{
controller.pause();
}
else
{
video.pause();
audio.pause();
}
}, false);
video.addEventListener('timeupdate', function()
{
if(!controller && audio.readyState >= 4)
{
if(Math.ceil(audio.currentTime) != Math.ceil(video.currentTime))
{
audio.currentTime = video.currentTime;
}
}
}, false);
Обратите внимание, что сам MediaController
"mediagroup"
<video mediagroup="foo"> ... </video>
<audio mediagroup="foo"> ... </audio>
Если бы мы это сделали, то в Chrome он работал бы без JavaScript. Он синхронизировал бы медиаисточники, но пользователь не мог бы контролировать звук (включая невозможность его выключить), потому что браузер не знал бы, что представляет собой аудио . Это тот случай, когда было бы лучше закодировать звук в видео, потому что тогда он мог бы появиться в объекте audioTracks
Но так как у нас нет данных audioTracks
Поэтому, если сценарии недоступны, звук просто не будет воспроизводиться.
Вот заключительная демонстрация , которая будет работать в любой последней версии Opera, Firefox, Chrome, Safari или IE9 или более поздней версии:
Конечно, это просто демонстрационная демонстрация концепции — здесь нет начального обнаружения функций, и она имеет только основные элементы управления, предоставляемые собственным атрибутом "controls"
Для правильной реализации потребовались бы пользовательские элементы управления, чтобы обеспечить (среди прочего) кнопку для включения и выключения звука и отдельные ползунки громкости. Интерфейс также должен быть доступен для клавиатуры, чего нет в родных элементах управления некоторых браузеров. И он должен был бы правильно обрабатывать буферизацию — так как это происходит, если вы просмотрите точку, в которой видео было предварительно загружено, аудио будет продолжать воспроизводиться свободно до тех пор, пока видео не загрузится достаточно для его синхронизации.
Могу также упомянуть, что сами описания вряд ли соответствуют профессиональным стандартам! Это мой голос, который вы можете услышать, записать и преобразовать с помощью Audacity . Но, как бы то ни было, я думаю, что это эффективная демонстрация того, насколько низок технический барьер для входа при таком подходе. Мне не нужно было редактировать видео, и я сделал звук через час с помощью бесплатного программного обеспечения.
В качестве доказательства концепции я бы сказал, что это было довольно успешно — и я уверен, что мой клиент будет очень доволен!