Реализация HLS/DASH потокового видео в мобильном приложении
Представьте: приложение в production, а пользователи жалуются на постоянные задержки и низкое качество. Мы сталкивались с этим десятки раз и выработали надёжную архитектуру плеера. Когда мобильное приложение показывает видео, а пользователь сидит в метро с нестабильным LTE — обычный MP4-файл превращается в пиксельную кашу и бесконечную буферизацию. Решение — адаптивный стриминг по протоколам HLS (HTTP Live Streaming) и DASH (Dynamic Adaptive Streaming over HTTP). Плеер загружает манифест (.m3u8 для HLS, .mpd для DASH), который описывает сегменты видео разного битрейта. Динамически переключая качество в зависимости от пропускной способности сети, мы добиваемся воспроизведения без задержек даже при плохом соединении.
Наш опыт разработки видеоплееров под ключ — 5+ лет и более 20 реализованных проектов для iOS и Android. Мы гарантируем стабильность воспроизведения на устройствах с низкой скоростью интернета. Свяжитесь с нами, чтобы оценить ваш проект — мы подберём оптимальный стек под ваши требования.
HLS vs DASH: что выбрать
| Параметр | HLS | DASH |
|---|---|---|
| Нативная поддержка iOS | Да (AVFoundation) | Нет (нужна сторонняя библиотека) |
| Нативная поддержка Android | Нет (нужен ExoPlayer) | Нет (нужен ExoPlayer) |
| Задержка (стандарт) | 6–30 с | 2–10 с |
| Low-Latency | LL-HLS: ~2 с | LL-DASH: ~1–3 с |
| DRM поддержка | FairPlay (iOS), Widevine | Widevine, PlayReady |
На практике: если аудитория iOS-dominant и нет DRM — HLS без сторонних библиотек. Если кросс-платформа и нужна минимальная задержка — DASH через ExoPlayer. Документация ExoPlayer: https://exoplayer.dev
Почему AVPlayer выигрывает у сторонних плееров на iOS?
AVPlayer встроен в систему — он использует аппаратный декодинг и автоматически управляет буфером. Для HLS это лучший выбор по производительности. AVPlayer даёт выигрыш в скорости запуска в 2–3 раза по сравнению с самописными решениями на сторонних SDK. Пример инициализации:
let asset = AVURLAsset(url: hlsURL, options: [ "AVURLAssetHTTPHeaderFieldsKey": ["Authorization": "Bearer \(token)"] ]) let item = AVPlayerItem(asset: asset) player = AVPlayer(playerItem: item) Мониторинг буферизации — KVO на item.isPlaybackLikelyToKeepUp и item.loadedTimeRanges. Когда isPlaybackLikelyToKeepUp == false — показываем спиннер, при true — скрываем.
Предзагрузка следующего видео: создаём AVPlayerItem заранее, добавляем в AVQueuePlayer — первый сегмент следующего видео начнёт загружаться в фоне.
Важно: AVPlayer поддерживает LL-HLS начиная с iOS 12. Для включения низкой задержки установите playerItem.preferredForwardBufferDuration = 1.0. Это уменьшает буфер до 1 секунды, но увеличивает риск прерывания. Мы рекомендуем такое значение только для стабильных сетей.
Как ExoPlayer справляется с HLS и DASH на Android?
ExoPlayer — рекомендованная библиотека Google. Она умеет автоматически выбирать источник по расширению URL. Пример кода:
val player = ExoPlayer.Builder(context).build() // HLS val hlsItem = MediaItem.Builder() .setUri("https://example.com/stream.m3u8") .build() // DASH val dashItem = MediaItem.Builder() .setUri("https://example.com/manifest.mpd") .build() player.setMediaItem(hlsItem) player.prepare() player.play() Для кастомных заголовков:
val dataSourceFactory = DefaultHttpDataSource.Factory() .setDefaultRequestProperties(mapOf("Authorization" to "Bearer $token")) val hlsSource = HlsMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(uri)) Адаптивный битрейт
По умолчанию ExoPlayer использует AdaptiveTrackSelection — переключает качество на границах сегментов (обычно каждые 2–10 с). Настройка минимального качества:
val trackSelector = DefaultTrackSelector(context) trackSelector.parameters = trackSelector.buildUponParameters() .setMaxVideoSizeSd() // не выше 480p на слабых устройствах .build() На iOS — AVPlayerItem.preferredPeakBitRate = 2_000_000 ограничивает верхний битрейт, полезно для экономии трафика до 40%.
Как настроить Low-Latency HLS?
Low-Latency HLS (LL-HLS) уменьшает задержку до 2 секунд за счёт частичных сегментов и HTTP/2 push.
- На iOS: установите
playerItem.preferredForwardBufferDuration = 1.0иplayer.automaticallyPreservesTimeOffsetFromLive = true. - На Android (ExoPlayer 2.12+): создайте
LiveConfigurationсtargetOffsetMs = 2000и передайте вMediaItem.Builder().setLiveConfiguration(...). - Убедитесь, что CDN поддерживает partial segments (например, AWS MediaTailor или Akamai LL-HLS).
- Протестируйте на реальных устройствах — воспроизведение должно начинаться за ~2 секунды.
| Параметр | LL-HLS | LL-DASH |
|---|---|---|
| Задержка | 2–3 с | 1–3 с |
| Поддержка iOS | Да (iOS 12+) | Нет |
| Поддержка Android | ExoPlayer 2.12+ | ExoPlayer 2.12+ |
| Сложность реализации | Средняя | Высокая |
Обработка ошибок сети
Сеть нестабильна — сегмент не загрузился, манифест вернул 403, CDN дал 5xx. ExoPlayer повторяет запросы автоматически с экспоненциальной задержкой (DefaultLoadErrorHandlingPolicy). Кастомная политика:
class RetryPolicy : DefaultLoadErrorHandlingPolicy() { override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo) = if (loadErrorInfo.errorCount < 5) 1000L * loadErrorInfo.errorCount else RETRY_DELAY_UNSET } На iOS: AVPlayerItem.status == .failed → player.currentItem?.error — читаем NSError, показываем кнопку «Повторить». Важно: после ошибки сбросьте AVPlayerItem и создайте новый, иначе повторная попытка может не сработать.
Что входит в работу
- Анализ требований и выбор протокола (HLS/DASH)
- Разработка плеера с ABR, кэшированием и DRM (FairPlay/Widevine)
- Интеграция аналитики (буферизация, ошибки)
- Документация по API и инструкция по деплою
- Тестирование на реальных устройствах с разной скоростью сети
- Поддержка после релиза (1 месяц)
Типичные ошибки при интеграции DRM
- Неверная настройка
AVAssetResourceLoaderDelegateдля FairPlay — отсутствие сертификата SPC. - Для Widevine на Android — не указана лицензия в
MediaItem.Builder().setDrmConfiguration(...). - Забывают проверить поддержку DRM на устройстве: на Android —
DrmSessionManager, на iOS —AVAssetResourceLoadingRequest.
Сроки ориентировочно
HLS-плеер на одной платформе с ABR и обработкой ошибок — от 2 дней. Кросс-платформенный (iOS + Android) с DASH, DRM и ручным выбором качества — от 4 до 5 дней. Если требуется LL-HLS или специфическая интеграция DRM — срок может быть увеличен на 1–2 дня. Получите консультацию — мы рассчитаем точный срок под ваш проект.
Закажите разработку видеоплеера под ключ: мы гарантируем стабильность и низкую задержку. Оценим ваш проект бесплатно.
Apple HLS Authoring Specification: https://developer.apple.com/documentation/http_live_streaming







