Эта история началась около 1,5 лет назад. Это связано с воспроизведением музыки в различных браузерах и платформах, на которых они запускаются.
Полный «боли и страданий» путь осознания того, что, казалось бы, легкая задача может оказаться не такой уж легкой, а «мелкие» детали, которым в самом начале не придаешь значения, могут повлиять на все.
Мелкие подробности для самых любопытных :) 1. Загрузка данных о каждом следующем треке из сети.
2. Каждый аудиоэлемент: new Audio() или требуется разрешение пользователя — настраиваемое действие на странице.
Фон
Наверное, каждый, кто хоть раз в жизни писал аудиоплеер для браузеров, сталкивался с проблемой кроссбраузерности и кроссплатформенности.Итак, работая над новым MVP, я столкнулся с различными функциями, касающимися воспроизведения звука в браузерах.
Все началось с необходимости сделать плавное сведение (кроссфейд) двух треков при воспроизведении - это первая особенность.
Наша команда хотела менять треки, как на радио.
И вторая особенность — каждый последующий трек запрашивается из сети.
Исследовать
Тогда почти все наши проекты использовали библиотеку Sound Manager 2. Почти сразу понимаешь, что одновременное воспроизведение двух аудиофайлов на мобильных устройствах не везде работает одинаково! В Chrome (версия ~62) для ПК треки воспроизводились как положено.На мобильных устройствах (тоже в Chrome) воспроизведение треков работало, но только при активном экране.
Когда экран был заблокирован, следующий трек после воспроизводимого в данный момент не воспроизводился.
Что касается iOS/macOS, воспроизведение работало аналогичным образом.
Более подробную информацию можно получить здесь – раздел «Один аудиопоток».
Так началось путешествие за три моря в поисках крупиц информации об особенностях работы браузеров со звуком.
Хорошо, я пробую решение с помощью веб-аудио без использования каких-либо библиотек.
Да, эта технология предназначена для других целей: синтеза, обработки звука, игр и т. д., а не просто воспроизведения треков.
Но ради эксперимента пришлось попробовать, так как он позволяет объединять звуки из разных источников в один вывод звука — колонки/наушники/динамик телефона/и т.д. Есть ребята, которые целенаправленно занимаюсь исследованием возможности воспроизведения звука на мобильных устройствах с использованием API веб-аудио.
После реализации стали понятны некоторые нюансы.
Во-первых, вам нужно дождаться полной загрузки всей трассы.
При медленном интернет-соединении будут заметны паузы из-за того, что второй трек может не успеть загрузиться к моменту окончания первого трека.
Полной загрузки можно избежать, если использовать кучу HTML5 Audio-тегов, которые будут выступать в качестве источников звука для Web Audio, но в этом случае снова становится невозможным одновременное воспроизведение двух звуков.
Во-вторых, если скачивать трек по сети фрагментами и декодировать их программно, это увеличивает нагрузку на процессор.
Это было приемлемо для ПК, но критично для мобильных устройств.
В-третьих, были проблемы с декодированием.
Если бы клиенту пришли фрагменты файлов mp3/ogg/wav, то эти куски спокойно бы декодированный и воспроизведено.
Но если браузер получал куски mp4-файла, выполнявшего роль контейнера для HE-AAC, то их невозможно было декодировать.
Это в некоторой степени касается и браузера Opera, в котором воспроизведение MP3-файлов нестабильно от версии к версии - то воспроизводит, то выдает ошибку, что этот формат не поддерживается.
В-четвертых, название трека не отображалось/менялось на заблокированном экране на планшете с родным аудиоплеером (на iPad), в т.ч.
при переключении между треками.
Возможно, из-за того, что для тестов использовался iPad с 9 версией iOS — другого устройства на тот момент не было.
В результате на этом этапе нам пришлось отказаться от Web Audio. Тем не менее, кроссфейд не для браузеров; стандартные музыкальные композиции в хорошем качестве весят довольно много.
Поскольку мы отказываемся от кроссфейда, мы реализуем простое постепенное появление и затухание в начале и конце музыкальной дорожки соответственно.
Код на предпоследнем шаге был немного изменен и протестирован.
В результате тестов выявились различные нюансы (представлены в таблице).
Все это с использованием библиотеки Sound Manager 2.
Добавляем логирование всех событий, чтобы определить момент перехода между треками и понять, в какой момент они перестают воспроизводиться.
Активация вкладки В браузере Safari 9+ звук не всегда появляется при активации вкладки.
Исходя из этого, можно предположить, что выполнение JS в фоновом режиме ограничивается или поток выполнения полностью остановлен (события и таймеры ).
Однако позже выяснится, что отчасти это был правильный вывод. Ниже мы рассмотрим еще один нюанс, связанный с воспроизведением треков и пониманием того, почему не появляется звук.
Ремарк Для работы с прогрессом (прогрессбаром), например, его отрисовкой для трека, хорошо использовать requestAnimationFrame вместо setInterval/setTimeout. Вы можете избежать накопительного эффекта при деактивации (фоновой вкладки) и последующей активации вкладки и ее временной заморозки, связанной со всеми расчетами и перерисовкой состояния прогресса.
В этот же момент возник вопрос: а как насчет автопроигрывания треков на ПК и мобильных устройствах?
Под автовоспроизведением мы подразумеваем автоматический запуск воспроизведения трека без каких-либо действий пользователя при загрузке страницы.Что касается Сафари автоматическое воспроизведение при загрузке страницы то это невозможно, нужно взаимодействие с пользователем со страницей, как на мобильные устройства .
Это касается обоих видеоконтент , так аудиоконтент .
Итак, на тот момент было следующее:
- Нельзя (не желательно) воспроизводить два и более звуков одновременно;
- для псевдо «автовоспроизведения» трека необходимо разрешение пользователя — первое взаимодействие, в дальнейшем оно получило название «Продать палец устройству»;
- в фоновом режиме (фоновая вкладка/экран блокировки) JS (все зависит от браузера): или полностью замерзает; или подлежит регулированию; или работает так же, как и при активной вкладке;
- Можно автоматически запустить воспроизведение без звука, но непонятно зачем (для аудиоконтента)?
- Где-то вдалеке начинает маячить мысль, как же сделать так, чтобы JS продолжал выполняться в фоновом режиме?
Несмотря на то, что на GitHub было рассмотрено множество вопросов с описанием проблем при воспроизведении треков в различных браузерах, всё же была надежда, что мы докопаемся до сути: почему это не работает и как заставить это работать.
Как оказалось, нет. Несколько примеров кода с видеодемонстрацией работы библиотек:
- Звуковой менеджер 2 - страницы GitHub , репозиторий GitHub , видео: macOS Сафари 12 ; iOS Сафари 10 когда экран разблокирован
- Ревун Ревущий v2.0.9 — страницы GitHub , репозиторий GitHub , видео: macOS Сафари 12 , iOS Сафари 10 Ревущий v2.0.15 — страницы GitHub , репозиторий GitHub , видео: macOS Сафари 12 Ревун v2.1.1 - страницы GitHub , репозиторий GitHub , видео: macOS Сафари 12 , iOS Сафари 10
Для macOS запись видео производилась без звука, поэтому нужно смотреть на индикатор громкости - изображение динамика, на вкладке.В чем причина того, что эти библиотеки не работают? Выше я написал: «На фоновой вкладке JS либо полностью зависает, либо ограничивается» .Больше видеопримеров доступно в репозитории.
В интерактивном примере для Howler v2.1.1 иногда можно услышать несколько звуков одновременно, это связано с добавлением пула аудиоэлементов, разблокированных пользователем (это должно быть исправлено в будущих версиях библиотеки).
Итак, здесь возникает еще один момент: библиотеки в коде используют создание новых аудиообъектов с помощью new Audio().
Если они создаются динамически, т.е.
если существующий аудиообъект не используется, и пользователь никак не взаимодействует с сайтом, вкладка неактивна или экран заблокирован, то некоторые браузеры могут решить, что им не следует воспроизводить звук из этого аудиоэлемента до тех пор, пока вкладка снова не станет активной или пользователь не сделает что-нибудь.
- или действие.
Пример теста для страницы GitHub И в репозитории на github используя новый Audio().
Видео: macOS Сафари 12 ; iOS Сафари 10 с разблокированным экраном.
Похоже, универсального инструмента не существует и нужно искать какое-то другое компромиссное решение.
Потом садимся с ребятами из команды и обсуждаем, что же действительно важно в работе аудиоплеера? Потому что эксперименты можно продолжать бесконечно, но нам нужно двигаться вперед. Сначала были выявлены важные моменты, которые мешали нам добиться желаемого результата:
- в браузере Safari на macOS треки не воспроизводятся, когда вкладка неактивна;
- нет возможности слушать музыку в фоновом режиме (при заблокированном экране) на смартфонах под управлением iOS и Android; Хотелось бы избежать агрессивного перенаправления пользователей на мобильное приложение (в будущем), поскольку предыдущий опыт показывает, что достаточно большая часть пользователей не желает устанавливать мобильное приложение;
- Плеер некорректно работает с динамическим плейлистом, т.е.
когда заранее неизвестно, какой будет следующий трек.
- обеспечить работу плеера в фоновом режиме – в разных браузерах и на разных платформах;
- позволить пользователю выбирать, что использовать: слушать музыку на сайте или в мобильном приложении;
- предоставить возможность использовать плеер (или подход) в различных будущих проектах.
На этом этапе различные библиотеки уже не использовались; все исследования проводились с использованием HTML5 Audio. В результате был найден вариант с помощью преданные работники .
Это решение вновь не позволило iOS победить — воспроизведение в фоновом режиме не работает, но в Android (Chrome, Opera, Safari) оно работало.
Пример теста HTML5 Audio + Dedicated Workers на страницах гитхаба И в репозитории на github .
При инициализации Worker запрашиваются данные о текущем треке.
Также воркёр отправляет сигнал на получение статуса прогресса — как долго воспроизводится трек — из основного потока и на основе этих данных решает, когда запрашивать данные о следующем треке из сети.
Также в то время был протестирован следующий пример ( страницы GitHub , репозиторий на github ), когда аудиотег HTML5 встроен в DOM (видео: macOS Сафари 12 , iOS Сафари 10 ) и его SRC просто заменяется при переключении между треками.
На сегодняшний день этот пример работает в macOS 12 Safari. К сожалению, на данный момент нет возможности проверить работоспособность этого примера на macOS в версиях Safari 10 и 11, но на тот момент этот пример не работал во время тестов ( политики автозапуска , ограничения автозапуска ).
Подводя итог, для iOS и macOS браузер Safari не считает новый экземпляр аудиоэлемента активируемым пользователем, если он был создан в фоновом режиме внутри события, например, ajax, setTimeout, onended. Далее, что касается воспроизведения треков в iOS Safari и iOS Chrome, то оказалось возможным воспроизводить треки в фоновом режиме (при заблокированном экране) только с помощью Х.
Л.
С.
.
Для платформ iOS и macOS этот формат является стандартным, а трансляция поддерживается операционной системой.
Собственная реализация также доступна для Android Chrome и Edge. А для ПК в Chrome можно использовать программные обработчики, например, hls.js , Битмовин Плеер и т. д.
К ссылка на репозиторий github Доступен пример кода, охватывающий простейший вариант использования — простое воспроизведение потока воспроизведения, сгенерированного на сервере, без возможности перемотки назад, переключения на следующий трек и т. д. Примеры представлены с использованием: тега audio, тега video, тега video. библиотека hls.js и плеер от Bitmovin. Для запуска требуется Node.js.
выводы
Первый пункт, к сожалению, из-за всего разнообразия браузеров не существует универсального решения, которое позволило бы одинаково хорошо слушать музыку в браузерах везде.Везде есть свои ограничения и, как показывает практика, с ними можно вполне комфортно жить.
Второй момент — иногда стоит как можно быстрее проверить крайние случаи, например, нативную реализацию.
Найдите какой-то минимально приемлемый набор требований и быстро проверьте его работоспособность, а не взяв за основу какую-либо библиотеку.
Это даст лучшее понимание того, как эти библиотеки организованы внутри и почему определенные функции работают или не работают. В противном случае можно довольно далеко забежать в проекте и потом понять, что что-то идет не так.
И может оказаться, что отказ от библиотеки обойдется довольно дорого.
Значительную часть кода придется переписать.
Третий момент, обязательно обратите внимание на аудиторию вашего сервиса — из каких браузеров и операционных систем приходят ваши пользователи.
Это довольно легко отследить с помощью различных метрик и систем мониторинга ошибок.
Такой подход позволит вам понять, какие платформы и браузеры важно поддерживать, а на поддержку каких не нужно тратить силы.
И наконец
Объявляю небольшой конкурс, связанный с воспроизведением музыки на iOS с использованием технологии HLS. Описание можно посмотреть на ссылка на гитхаб .Теги: #браузеры #разработка веб-сайтов #JavaScript #HTML #фронтенд-разработка #исследования #node.js #node js #m3u8 #html5 audio
-
Как Запустить Python Через Sas?
19 Oct, 24 -
7Приложение, Диаграмма №7
19 Oct, 24 -
Согласие Внутри Команды
19 Oct, 24 -
Сумасшедший Киви
19 Oct, 24 -
Linux Все Еще Не Торт
19 Oct, 24 -
Мультизагрузка Файлов, Версия N
19 Oct, 24 -
Реализация Целочисленного Бпф На Плис
19 Oct, 24