Адаптивне потокове відео за допомогою Dash.js у React


HTML <video>
є фактичним елементом, до якого ми звертаємося для вбудовування відеоконтенту, але він має свої обмеження. Наприклад, він лінійно завантажує відеофайл через HTTP, що призводить до зниження продуктивності, особливо для великих відео, які відтворюються на повільніших з'єднаннях. Але за допомогою адаптивного потокового передавання з бітрейтом ми можемо розділити відео на кілька сегментів з різним бітрейтом та роздільною здатністю.
Нещодавно мені доручили створити відеоролики, які потрібно було плавно відтворювати в повільній мережі або на низькопродуктивних пристроях. Я почав з нативного HTML5. <video>
тег, але швидко наштовхується на перешкоду — він просто не працює, коли з’єднання повільне або пристрої мають недостатню потужність.
Після деяких досліджень я виявив, що адаптивна потокова передача даних – це саме те рішення, яке мені було потрібно. Але ось що засмучує: знайти вичерпний посібник для початківців було дуже важко. Ресурси на MDN та інших веб-сайтах були корисними, але їм бракувало вичерпного посібника, який я шукав.
Ось чому я пишу цю статтю: щоб надати вам покрокове керівництво, яке я шкода, що не знайшов. Я поєднаю написання скриптів FFmpeg, кодування відеофайлів та реалізацію відеоплеєра, сумісного з DASH ( Dash.js ), за допомогою прикладів коду, які ви можете використовувати.
Вихід за межі нативного HTML5 <video>
Тег
Ви можете запитати, чому не можна просто покладатися на HTML <video>
елемент. Для цього є вагома причина. Давайте порівняємо різницю між рідним <video>
елемент та адаптивне потокове відео в браузерах.
Прогресивне завантаження
Під час прогресивного завантаження ваш браузер лінійно завантажує відеофайл із сервера через HTTP та починає відтворення, якщо буферизує достатньо даних. Це поведінка за замовчуванням. <video>
елемент.
Під час відтворення відео перевірте вкладку мережі у вашому браузері, і ви побачите кілька запитів із 206 Partial Content
код стану.
Якщо сервер або браузер не підтримує запити діапазону, весь відеофайл буде завантажено одним запитом, повертаючи 200 OK
код стану. У такому разі відтворення відео може розпочатися лише після завершення завантаження всього файлу.
Проблеми? Якщо у вас повільне з’єднання під час спроби переглянути відео високої роздільної здатності, вам доведеться довго чекати, перш ніж почнеться відтворення.
Адаптивна потокова передача бітрейту
Замість того, щоб відтворювати один відеофайл, потокове передавання з адаптивним бітрейтом (ABR) розділяє відео на кілька сегментів з різним бітрейтом та роздільною здатністю. Під час відтворення алгоритм ABR автоматично вибирає сегмент найвищої якості, який можна вчасно завантажити для плавного відтворення, залежно від вашого мережевого підключення, пропускної здатності та інших можливостей пристрою. Він постійно налаштовується, щоб адаптуватися до змінних умов.
Ця магія відбувається завдяки двом ключовим технологіям браузера:
- Розширення джерела медіа (MSE)
Це дозволяє передавати об'єкт MediaSource доsrc
атрибут у<video>
, що дозволяє надсилати кілька об'єктів SourceBuffer , які представляють відеосегменти.
- API медіа-можливостей
Він надає інформацію про можливості декодування та кодування відео вашим пристроєм, що дозволяє ABR приймати обґрунтовані рішення щодо того, яку роздільну здатність забезпечувати.
Разом вони забезпечують основну функціональність ABR, обслуговуючи відеофрагменти, оптимізовані для обмежень вашого пристрою, в режимі реального часу.
Протоколи потокової передачі: MPEG-DASH проти HLS
Як згадувалося вище, для адаптивної потокової передачі медіафайлів відео розділяється на фрагменти з різним рівнем якості в різні моменти часу. Нам потрібно спростити процес адаптивного перемикання між цими сегментами в режимі реального часу. Для досягнення цього потокова передача ABR спирається на певні протоколи. Два найпоширеніші протоколи ABR:
- MPEG-DASH,
- Пряма трансляція HTTP (HLS).
Обидва ці протоколи використовують HTTP для надсилання відеофайлів. Отже, вони сумісні з веб-серверами HTTP.
Ця стаття зосереджена на MPEG-DASH. Однак, варто зазначити, що DASH не підтримується пристроями чи браузерами Apple, як згадувалося у статті Mux .
MPEG-DASH
MPEG-DASH забезпечує адаптивну потокову передачу через:
- Файл опису медіапрезентації (MPD)
Цей XML-файл маніфесту містить інформацію про те, як вибирати та керувати потоками на основі адаптивних правил. - Сегментовані медіафайли
Відео- та аудіофайли поділяються на сегменти з різною роздільною здатністю та тривалістю за допомогою кодеків та форматів, сумісних з MPEG-DASH.
На стороні клієнта відеоплеєр, сумісний із DASH, зчитує файл MPD та постійно контролює пропускну здатність мережі. На основі доступної пропускної здатності плеєр вибирає відповідний бітрейт та запитує відповідний відеофрагмент. Цей процес повторюється протягом усього відтворення, забезпечуючи плавну та оптимальну якість.
Тепер, коли ви розумієте основи, давайте створимо наш адаптивний відеоплеєр!
Кроки для створення адаптивного бітрейт-плеєра потокового відео
Ось план:
- Перекодуйте відео MP4 в аудіо- та відеоверсії з різною роздільною здатністю та бітрейтом за допомогою FFmpeg.
- Згенеруйте MPD-файл за допомогою FFmpeg.
- Обслуговувати вихідні файли з сервера.
- Створіть відеоплеєр, сумісний з DASH, для відтворення відео.
Встановлення FFmpeg
Для користувачів macOS встановіть FFmpeg за допомогою Brew, виконавши таку команду у своєму терміналі:
Генерація аудіовідтворення
Далі запустіть наступний скрипт, щоб витягти аудіодоріжку та закодувати її у форматі WebM для сумісності з DASH:
-i "input_video.mp4"
: Визначає вхідний відеофайл.-vn
: Вимикає відеопотік (вихід лише аудіо).-acodec libvorbis
Використовує кодек libvorbis для кодування аудіо.-ab 128k
: Встановлює бітрейт аудіо на 128 кбіт/с ."audio.webm"
: Визначає вихідний аудіофайл у форматі WebM.
Генерація відеовізуалізацій
Запустіть цей скрипт, щоб створити три відеоверсії з різною роздільною здатністю та бітрейтом. Найбільша роздільна здатність має відповідати розміру вхідного файлу. Наприклад, якщо вхідне відео має роздільну здатність 576×1024 з частотою 30 кадрів на секунду (fps), скрипт генерує версії, оптимізовані для вертикального відтворення відео.
-c:v libvpx-vp9
Використовує libvpx-vp9 як відеокодер VP9 для WebM.-keyint_min 150
і-g 150
: Встановіть інтервал ключових кадрів 150 кадрів (приблизно кожні 5 секунд при 30 кадрах/с). Це дозволяє перемикати бітрейт кожні 5 секунд.-tile-columns 4
і-frame-parallel 1
Оптимізуйте продуктивність кодування за допомогою паралельної обробки.-f webm
: Визначає вихідний формат WebM.
У кожному виконанні:
-an
: Виключає аудіо (вихід лише відео).-vf scale=576:1024
: Масштабує відео до роздільної здатності 576x1024 пікселів.-b:v 1500k
: Встановлює бітрейт відео на 1500 кбіт/с .
Як вихідний формат обрано WebM, оскільки вони менші за розміром та оптимізовані, але широко сумісні з більшістю веббраузерів.
Згенерувати файл маніфесту MPD
Об’єднайте відео та аудіодоріжку у файл маніфесту MPD, сумісний із DASH, виконавши наступний скрипт:
-f webm_dash_manifest -i "…"
: Визначає входи, між якими відеоплеєр ASH динамічно перемикатиметься залежно від стану мережі.-map 0 -map 1 -map 2 -map 3
Включає всі відео (0, 1, 2) та аудіо (3) у фінальний маніфест.-adaptation_sets
Групує потоки в набори адаптації:id=0,streams=0,1,2
: Групує відеоверсії в один набір адаптацій.id=1,streams=3
: Призначає аудіодоріжку окремому набору адаптації.
Отриманий файл MPD ( input_video_manifest.mpd
) описує потоки та забезпечує адаптивну потокову передачу бітрейту в MPEG-DASH.
Після виконання цих кроків у вас буде:
- Три відеоверсії (
576x1024
,480x854
,360x640
), - Одна аудіодоріжка, і
- Файл маніфесту MPD.
Оригінальне відео input_video.mp4
також слід зберегти, щоб використовувати як резервне джерело відео надалі.
Обслуговувати вихідні файли
Ці вихідні файли тепер можна завантажити до хмарного сховища (наприклад, AWS S3 або Cloudflare R2) для відтворення. Хоча їх можна обслуговувати безпосередньо з локальної папки, я наполегливо рекомендую зберігати їх у хмарному сховищі та використовувати CDN для кешування ресурсів для кращої продуктивності. Як AWS, так і Cloudflare підтримують запити HTTP-діапазону одразу після встановлення.
Створення відеоплеєра, сумісного з DASH, у React
Ніщо так не допомагає зрозуміти, як все працює, як реальний приклад. Існують різні способи реалізації відеоплеєра, сумісного з DASH, але я зосереджуся на підході з використанням React.
Далі створіть компонент під назвою <DashVideoPlayer />
та ініціалізувати екземпляр Dash MediaPlayer , вказавши його на MPD-файл під час монтування компонента.
Функція зворотного виклику ref виконується після монтування компонента, а всередині функції зворотного виклику, playerRef
посилатиметься на фактичний екземпляр Dash MediaPlayer та буде пов’язаний зі слухачами подій. Ми також включаємо оригінальну URL-адресу MP4 у <source>
елемент як резервний варіант, якщо браузер не підтримує MPEG-DASH.
Якщо ви використовуєте маршрутизатор програм Next.js , не забудьте додати ‘use client’
директива для ввімкнення гідратації на стороні клієнта, оскільки відеоплеєр ініціалізується лише на стороні клієнта.
Ось повний приклад:
Результат
Спостерігайте за змінами у відеофайлі, коли мережеве з’єднання змінюється з Fast 4G на 3G за допомогою Chrome DevTools. Роздільна здатність перемикається з 480p на 360p, показуючи, як оптимізовано відтворення для більшої чи меншої доступної пропускної здатності.
Висновок
Ось і все! Ми щойно реалізували робочий відеоплеєр, сумісний з DASH, у React, щоб налаштувати потокову передачу відео з адаптивним бітрейтом. Знову ж таки, переваги цього пов'язані з продуктивністю . Коли ми використовуємо потокову передачу ABR, ми запитуємо відео меншими фрагментами, що дозволяє швидше відтворювати його, ніж якби нам спочатку потрібно було повністю завантажити відеофайл. І ми зробили це таким чином, що підтримує кілька версій одного й того ж відео, що дозволяє нам відображати найкращий формат для пристрою користувача.
Для підготовки контенту ми дослідили статті, присвячені сучасним підходам у створенні сайтів, UX/UI дизайну та просуванню в Google: