Что плеер стриминга делает от начала до конца

Автор: Николай СапуновОбновлено: август 202628 мин чтения
Содержание статьи +

TL;DR

Плеер видеостриминга – это не просто «тег <video> плюс кнопка Play». Это миниатюрная распределённая система, работающая прямо в браузере: семь подсистем одновременно взаимодействуют с CDN, декодером, буфером, модулем DRM и эндпоинтом телеметрии. Вот эти семь подсистем: – небольшой текстовый манифест, который плеер загружает первым; – загрузчик, скачивающий медиафайлы небольшими порциями; – контроллер адаптивного битрейта, выбирающий следующий уровень качества; – менеджер буфера, передающий эти порции браузеру; – конвейер декодирования, функционирующий внутри браузерного медиа-движка; – мост DRM, разблокирующий зашифрованные сегменты; – слой телеметрии, отправляющий события ребуферизации в вашу аналитику.

Два веб-стандарта – Media Source Extensions (MSE) и Encrypted Media Extensions (EME) – обеспечивают связь между JavaScript-частью и нативной частью браузера, а тонкий слой новых API (Managed Media Source в iOS Safari, MSE-in-Workers в Chrome, WebCodecs для низкоуровневого доступа) кардинально меняет архитектуру каждой из подсистем уже в 2026 году.

Прочитайте эту статью сначала, а затем переходите к разбору конкретных плееров – hls.js, Shaka Player, dash.js, Video.js v10 – с единым словарём в голове.

Зачем это нужно

Когда зритель говорит «видео не работает», он почти всегда имеет в виду, что отказала одна из семи подсистем: манифест не распарсился, загрузчик сегментов словил таймаут, ABR-логика выбрала не ту рендицию, буфер опустел, декодер отверг кодек, рукопожатие DRM упало или телеметрия молча проглотила событие – и об этом никто не узнал. Если вы поставляете видео хоть в каком-то масштабе, вы будете читать этот стек-трейс, заводить под него Jira-тикет и объяснять его клиенту – поэтому семь имён должны быть у вас в голове. Статья написана для продакт-менеджеров, основателей и маркетинговых лидеров, которым нужно говорить с инженерами о проблемах плеера, не теряясь, и для инженеров, только вступающих в команду плеера, которым нужна карта до того, как они начнут разбираться в деталях. Никаких предварительных знаний о стриминговых протоколах не требуется. К концу вы научитесь смотреть на исходники любого open-source плеера и понимать, какой файл отвечает за какую подсистему.

Плеер – это конечный автомат, а не кнопка

Многие читатели приходят с моделью: плеер – это кнопка Play. Нажми – пошло видео, нажми ещё раз – встало. Эта модель неверна полезным образом: она описывает контракт перед пользователем, но прячет семь подсистем, которые этот контракт реализуют.

Лучше думать так: плеер стриминга – это конечный автомат, который по несколько секунд за раз подтягивает медиа из интернета, передаёт эти фрагменты встроенному в браузер видео-движку и реагирует на события вроде «дай ещё» и «я сломался». У самого браузерного видео-движка есть пять состояний готовности, описанных в стандарте WHATWG HTML: HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA. Задача плеера – последовательно переводить движок из одного состояния в следующее и ни в коем случае не допускать отката назад. Когда движок откатится с HAVE_FUTURE_DATA обратно в HAVE_CURRENT_DATA, именно в этот момент зритель увидит спиннер, а в дашборде аналитики зафиксируется событие ребуферизации.

Остальная часть статьи – это экскурсия по семи подсистемам, которые обеспечивают работу плеера. Эти подсистемы универсальны: любой браузерный плеер построен из этих семи блоков, независимо от того, работает ли он с HLS, MPEG-DASH, CMAF или Media over QUIC. Имена JavaScript-файлов в hls.js, Shaka Player, dash.js и Video.js v10 могут отличаться – но принцип работы семи компонентов остаётся одинаковым.

Рис. 1. Семь подсистем видеостримингового плеера. Любой open-source плеер 2026 года реализует все семь; имена файлов могут отличаться, но суть работы остаётся одинаковой.

Подсистема 1 – Загрузчик манифеста

Прежде чем плеер сможет скачать хотя бы один байт видео, ему нужно получить небольшой текстовый файл – манифест, своего рода «телефонную книгу» всех доступных качеств и сегментов контента. Два формата манифеста доминируют в открытом вебе: плейлист .m3u8 от HTTP Live Streaming (HLS) и Media Presentation Description .mpd от MPEG-DASH. Оба стандарта описаны в нормативных документах – IETF RFC 8216 для HLS и ISO/IEC 23009-1 для DASH.

Типичный multi-variant HLS-плейлист – это десяток строк обычного текста. Он перечисляет доступные рендиции – так плеер называет одно качество, например «1080p, 5 Мбит/с, H.264» – и указывает на media playlist каждой рендиции, в котором уже лежат URL сегментов. Типичный DASH MPD – пара килобайт XML, делающих то же самое более структурированно: верхний Period, по одному AdaptationSet на тип медиа (видео, аудио, субтитры) и по одному Representation на каждую рендицию внутри.

Работа загрузчика манифеста на первый взгляд кажется простой – скачать текстовый файл, распарсить и передать структуру дальше. На практике это один из самых частых источников сбоев в продакшене по одной причине: манифест – единственный объект во всём конвейере, чья потеря фатальна. Если плеер не может получить манифест, фоллбэка нет – воспроизведение просто не начнётся. Поэтому в загрузчике реализовано больше всего повторных попыток, агрессивных заголовков cache-buster и логики «попробовать пять CDN параллельно» в продакшен-стеках. Каждый плеер устанавливает таймаут на загрузку манифеста (обычно 10–20 секунд) и настраиваемую политику повторных попыток с экспоненциальным бэк-оффом.

Для live-стримов загрузчик работает не разово – он работает вечно. Каждые несколько секунд плеер обновляет манифест, чтобы узнать о новых сегментах на live-грани. Low-Latency HLS добавляет в плейлист подсказку «blocking reload», которая просит сервер удерживать соединение открытым до появления следующей части – но базовый цикл обновлений остаётся одинаковым во всех live-форматах.

Подсистема 2 – Загрузчик сегментов

После того как манифест распарсен, плеер знает URL каждого медиа-сегмента шоу. Загрузчик сегментов – это слой, который фактически скачивает эти сегменты. Сегмент – короткий фрагмент видео, обычно 2–6 секунд для трансляции в реальном времени и 10 секунд для VOD, упакованный в ISO Base Media File Format (fragmented MP4) или MPEG-2 Transport Stream. Загрузчик выполняет один HTTPS-запрос на каждый сегмент.

Два проектных решения определяют хороший загрузчик: параллелизм и приоритеты запросов. Наивный загрузчик скачивает сегменты строго последовательно; продакшен-версия одновременно обрабатывает 2–3 сегмента, чтобы кривая зависимости пропускной способности от задержки выглядела разумно. Логика приоритетов определяет, что загружать в первую очередь: на старте – самый низкобитрейтный первый сегмент, чтобы воспроизведение началось как можно быстрее, а затем – более высокобитрейтный второй сегмент, чтобы использовать сеть, параметры которой уже были измерены первым запросом.

Загрузчик – это ещё и место, где добавляется Common Media Client Data (CMCD): небольшой набор пар «ключ-значение», который плеер прикрепляет к каждому запросу сегмента и который сообщает CDN, что сейчас делает плеер – какая это сессия, какая длина буфера, какой битрейт он использует, является ли запрос первым после запуска. CMCD описан в CTA-5004 и существенно расширен в CTA-5004-A (CMCDv2, февраль 2026). Это одно из самых дешёвых улучшений надёжности стриминг-продукта: локально плеер ничего не выигрывает, но теперь каждая строка лога CDN содержит контекст, необходимый инженеру incident-response для анализа ребуферизации в продакшене.

Подсистема 3 – Контроллер ABR

Adaptive bitrate (ABR) – алгоритм, который перед загрузкой каждого сегмента определяет, какую версию контента запросить следующей. Задача формулируется просто, но реализация остаётся одной из самых вариативных частей любого плеера. Даже незначительные изменения в логике ABR могут повлиять на rebuffer ratio и средний битрейт – и эти изменения становятся измеримыми в A/ B-тестах на миллионе сессий. Поэтому в любой серьёзной стриминговой команде либо настраивают стандартный ABR, либо разрабатывают собственный.

В продакшене используются четыре семейства ABR. Throughput-основанные алгоритмы оценивают текущую пропускную способность сети и выбирают самую высокую версию видео, битрейт которой не превышает доступную полосу – это самый простой подход, который до сих пор остаётся стандартным во многих плеерах. Buffer-основанные алгоритмы игнорируют пропускную способность и ориентируются только на уровень заполнения буфера; алгоритм BOLA, представленный Spiteri и соавторами в 2016 году, является открытой референсной реализацией. Гибридные алгоритмы комбинируют оба подхода: семейство Model Predictive Control (MPC) и режим «DYNAMIC» в dash.js – типичные примеры. Нейросетевые / обучаемые алгоритмы – Pensieve, Comyco, Kairos – обучают небольшую RL-политику на наборе трассировок сессий и применяют её в качестве ABR-стратегии; они уже используются в продакшене несколькими крупными провайдерами.

У каждого ABR-алгоритма одинаковый вход – поток недавних длительностей загрузок и текущий уровень буфера. У каждого алгоритма одинаковый выход – целочисленный индекс в списке рендиций. Контроллеру не нужно «знать» о кодеках, контейнерах или транспорте – это чистая функция, преобразующая состояние сети и буфера в решение о качестве. Поэтому ABR можно заменить одним файлом в любом крупном open-source плеере.

В контроллере же сосредоточена и большая часть продакшен-тюнинга. Типичный продукт поставляется с двумя-тремя оверрайдами: ограничение максимальной рендер-качества на сотовых сетях, стабилизация рендера на первых трёх сегментах, чтобы избежать мигания низкого качества в начале воспроизведения, и переход в buffer-основный режим, когда воспроизведение стабилизируется. Ничего подобного нет в опубликованных статьях об алгоритмах – это устный фольклор команд, тестирующих плеер на реальной аудитории.

Рис. 2. Контур обратной связи ABR. Контроллер анализирует пропускную способность и уровень буфера, выбирает качество потока, а следующая загрузка замыкает цикл через несколько секунд.

Подсистема 4 – Менеджер буфера и исходный буфер

Когда сегмент скачан, плеер сталкивается с проблемой: тег <video> в браузере не может «принять кусок MP4». Он умеет проигрывать готовый файл через атрибут src, а стриминговый плеер собирает файл постепенно, по частям, в памяти, по мере воспроизведения. Эту проблему решает Media Source Extensions (MSE) – спецификация W3C (на момент написания – Working Draft от 4 ноября 2025 года, последняя формальная Recommendation – от 17 ноября 2016 года), предоставляющая JavaScript API для добавления байтов в медиа-конвейер браузера.

В MSE два объекта. MediaSource – JavaScript-прокси для медиапотока браузера: вы создаёте его, привязываете к тегу <video> через video.src = URL.createObjectURL(mediaSource), и тег воспринимает его как настоящий источник видео. SourceBuffer – JavaScript-обработчик буфера готового к декодированию медиа внутри браузера: вы вызываете sourceBuffer.appendBuffer(arrayBuffer) с байтами скачанного сегмента, и браузер парсит, декодирует и добавляет их в воспроизводимую таймлайн.

Менеджер буфера – это часть кода плеера, отвечающая за то, какие сегменты загружать, в каком порядке и когда удалять устаревшие. Live-плеер обычно хранит в SourceBuffer около тридцати секунд видео, а VOD-плеер – одну–две минуты. Если пользователь перематывает за пределы текущего окна воспроизведения, менеджер сбрасывает буфер и начинает загрузку заново с новой точки перемотки.

В менеджере буфера реализуется и обработка пропусков (gap-handling). У сегментов иногда возникают пропуски в один кадр – из-за бага в пакетировщике или из-за границ у энкодера – и наивный плеер может бесконечно ждать видео, которого не будет. В любом менеджере буфера для продакшена есть правило: «если currentTime не обновляется N секунд, а следующий sample находится в пределах K миллисекунд – перейти вперёд»; конкретные значения констант – небольшая, но тщательно отлаженная часть кода каждого плеера.

Одно обновление 2026 года стоит выделить отдельно. Chrome 108 и выше позволяют использовать MSE внутри dedicated Worker: парсинг сегментов и буферная арифметика переносятся с главного UI-потока, и воспроизведение 4K больше не конкурирует с JavaScript страницы за ресурсы CPU. Спецификация W3C MSE добавила объект MediaSourceHandle, который пересекает границу Worker и привязывается к <video> через video.srcObject на главном потоке. Плееры, освоившие Worker-реализацию MSE, фиксируют заметное снижение количества ребуферизаций на более слабых ноутбуках.

Второе обновление 2026 – Managed Media Source (MMS) от Apple, появившееся в Safari 17.0 на iPad и Mac и в Safari 17.1 на iPhone. MMS сохраняет API-интерфейс MSE, но передаёт решение о пропускной способности и управлении памятью браузеру: браузер может запросить у плеера приостановить загрузку или удалить старые сегменты, если ухудшится состояние батареи, памяти или сети. Переход на новую версию ненавязчивый: плеер проверяет наличие MMS, а на других браузерах автоматически переключается на классический MSE, и одна кодовая база работает энергоэффективно на любом устройстве Apple.

Подсистема 5 – Конвейер декодирования

Менеджер буфера сам не декодирует видео – он передаёт байты браузеру, а уже браузерный медиа-движок берёт на себя дальнейшую обработку. Конвейер декодирования – это цепочка компонентов внутри браузера, преобразующая MP4-сегмент в пиксели на экране: демультиплексор, разделяющий аудио и видео; видео-декодер, превращающий сжатые кадры в необработанные; аудио-декодер, преобразующий сжатые сэмплы в необработанные; рендерер, отправляющий кадры в GPU; и тактовый генератор, синхронизирующий аудио и видео.

Для разработчика стриминг-плеера конвейер декодирования в основном невидим: байты поступают через MSE, пиксели выводятся на элементе <video> – всё, что происходит между ними, обрабатывает браузер. То, что действительно важно для разработчика плеера, – это поддержка кодеков, которая различается в зависимости от браузеров и операционных систем и меняется чаще, чем кажется большинству команд. Логика запуска плеера запрашивает у браузера список поддерживаемых кодеков (MediaSource.isTypeSupported('video/mp4; codecs="avc1.640028,mp4a.40.2"')), выбирает рендеринги, строки кодеков которых соответствуют требованиям, и молча отбрасывает остальные.

В конвейере декодирования важную роль играет аппаратное ускорение. На современных устройствах с аппаратным декодером H.264, HEVC или AV1 браузер направляет байты на кремниевую часть, которая обрабатывает 4K@60fps, используя менее 5 % CPU. Без аппаратной поддержки – как это типично для AV1 на старых ноутбуках в 2026 году – браузер переключается на программный декодер, и загрузка CPU достигает 100 %. Это одна из самых частых проблем в продакшене, которая выглядит как «баг плеера», но на самом деле связана с отсутствием нужных аппаратных кодеков; единственное решение – исключить AV1-рендиции из манифеста для устройств без соответствующей поддержки.

Маленький, но растущий класс плееров полностью обходит MSE и использует API WebCodecs, декодируя кадры в JavaScript по отдельности и отображая их в <canvas>. WebCodecs (опубликован как W3C Candidate Recommendation Snapshot) необходим в двух случаях: при live-стриминге с задержкой менее секунды, где буферизация, навязанная MSE, слишком затратна, и в приложениях, требующих покадрового доступа к декодированным пикселям – например, редактирование в браузере, применение ИИ-эффектов или screen-шейр с кодированием прямо в WebTransport-аплоад. Для массового воспроизведения HLS или DASH MSE остаётся оптимальным решением – WebCodecs требует слишком много ресурсов ради слишком малой выгоды.

Подсистема 6 – Мост DRM

Если контент защищён, у плеера есть шестая задача – убедить браузерный Content Decryption Module (CDM), что данной сессии разрешено расшифровывать сегменты. Для этого используется механизм – API W3C Encrypted Media Extensions (EME).

EME – это не DRM. Это стандартизированный канал сообщений между JavaScript-плеером и нативным CDM браузера, а также небольшой конечный автомат для запросов лицензий. CDM браузера – Widevine в Chrome, Firefox и Edge, FairPlay в Safari, PlayReady в legacy Edge и Windows – представляет собой закрытый бинарник, который выполняет фактическую расшифровку внутри песочницы; задача плеера – передавать сообщения между CDM и вашим сервером лицензий.

Пять шагов EME-сессии выглядят просто и удивительно стабильно в реализации: navigator.requestMediaKeySystemAccess(keySystem, configurations) спрашивает у браузера, есть ли у него CDM, способный работать с нужным плееру кодеком, контейнером и DRM; createMediaKeys() создаёт сессию CDM; setMediaKeys() привязывает её к тегу <video>; generateRequest() формирует payload запроса лицензии, который плеер отправляет на сервер лицензий методом POST; ответ передаётся обратно в CDM, и начинается расшифровка. Каждый из этих шагов описан в рекомендации W3C EME.

Сложность в продакшене – не в EME API, а в матрице из трёх DRM-систем на каждое устройство в мире. У одного только Widevine три уровня безопасности (L1, L2, L3), определяющие, сможет ли браузер проиграть защищённый стрим в 4K, 1080p или только в 480p – а уровень зависит от устройства, которым владеет пользователь. FairPlay обязателен в iOS Safari для любого защищённого контента. PlayReady обязателен на Xbox и на множестве платформ smart TV. Современный OTT-плеер обязан поддерживать все три системы, запрашивать их в правильном порядке и корректно отображать понятную ошибку, если ни одна из них недоступна.

DRM – тема для целого блока статей (Блок 9, 9.1–9.5). В этой статье ключевая позиция такова: мост DRM расположен между менеджером буфера и конвейером декодирования, перехватывая каждый добавляемый буфер непосредственно перед декодером, чтобы нешифрованные байты никогда не покидали песочницу CDM.

Рис. 3. Пятишаговый поток лицензии Encrypted Media Extensions. Плеер выступает в роли ретранслятора. CDM – граница доверия.

Подсистема 7 – Телеметрия и восстановление после сбоев

У седьмой подсистемы самый прямой эффект на выручку клиента, и именно её большинство команд недостроят в первую очередь. Телеметрия – это слой, который отслеживает каждое событие, генерируемое шестью предыдущими подсистемами (сегмент скачан, сегмент упал, уровень буфера изменился, ABR переключил рендицию, запрос лицензии завершён, декодер выдал ошибку, воспроизведение остановилось) и в реальном времени передаёт их в аналитическую платформу.

Четыре главные метрики: video startup time (сколько прошло от клика пользователя до первого кадра), rebuffer ratio (доля времени просмотра, проведённая в спиннере), playback failure rate (доля сессий, в которых первый кадр так и не появился) и exit-before-video-start (доля пользователей, ушедших ещё до того, как они нажали Play). Mux Data, Conviva, Bitmovin Analytics, Datazoom и NPAW выставляют эти четыре как заголовочные плитки своих дашбордов, потому что любое исследование оттока зрителей за последние пятнадцать лет показывает их как четыре самых предиктивных переменных для удержания.

Разумная цель по rebuffer ratio – меньше 1%; ниже 0,5% – уровень, которого добивается хорошо настроенный продукт; всё, что выше 3%, считается критическим – с таким показателем команда должна реагировать как на инцидент в продакшене. Арифметика простая, но в первый раз стоит её разобрать вслух. Если пользователь смотрит 45-минутный эпизод и в сумме перебуферивается на 60 секунд, отношение составляет 60 / (45 × 60), то есть 60 / 2700, то есть 0.022, то есть примерно 2,2%. 2,2% – это вдвое больше верхнего допустимого порога; команда, как и ожидалось, увидит рост exit rate на таких сессиях.

Половина подсистемы, отвечающей за восстановление, – это небольшой набор автоматических повторных попыток, которые плеер выполняет перед тем, как сдаться и показать красный экран ошибки. Типичные действия: повторная загрузка манифеста с экспоненциальной задержкой, если первая попытка провалилась; повторная попытка загрузки упавшего сегмента до N раз; пересоздание MediaSource и повторная привязка к <video>, если состояние буфера стало неконсистентным; пропуск одного кадра, если currentTime длится две секунды; переключение на следующий доступный CDN-URL, если текущий возвращает 5xx. Ничего из этого не описано ни в одной спецификации – это накопленная продакшен-опыт каждой команды, которая когда-либо дежурила во время трансляции Super Bowl.

Нативный плеер против JavaScript-плеера: когда какой выигрывает

Семь подсистем описывают работу JavaScript-плеера в браузере. Существует и вторая, более простая форма, также используемая в продакшене: нативный плеер, который передаёт URL манифеста встроенному в операционную систему видеоконвейеру и позволяет системе выполнить всю работу.

Хрестоматийный пример – iOS Safari: присвоение URL HLS-манифеста атрибуту src тега <video> запускает в фоне AVPlayer, и реализация Apple сама обрабатывает загрузчик манифеста, загрузчик сегментов, ABR, менеджер буфера, конвейер декодирования, DRM-мост (через FairPlay) и даже большую часть телеметрии. JavaScript-плеер сводится к «указать src, повесить пару обработчиков событий, нарисовать кастомный интерфейс поверх». Нативный плеер выигрывает по расходу батареи, по задержке первого кадра (конвейер декодирования Apple быстрее любого JS-плеера) и по поддержке AirPlay, которую MSE-плеер воспроизвести не сможет.

Нативный плеер также проигрывает в трёх конкретных аспектах. Он поддерживает только протоколы, которые понимает операционная система: HLS в iOS Safari, HLS и DASH в Android, но ни один из них – на платформах smart-TV, где ещё не реализован нужный кодек. Он предоставляет очень ограниченную информацию о своём внутреннем состоянии: интеграция Mux Data с нативным iOS-плеером предлагает меньше метрик, чем аналогичная интеграция с сессией Shaka Player. И он развивается в ритме релизов Apple, а не в вашем: исправление бага в нативном HLS-движке может появиться только через 6–12 месяцев.

Выбор в 2026 году редко сводится к «JavaScript-плеер везде» или «нативный плеер везде». Большинство продакшен-стеков используют оба варианта: hls.js или Shaka в Safari – только если доступен MSE и команда хочет более точного контроля, иначе – нативный HLS; Shaka Player в Chrome на Android; ExoPlayer на Android TV; AVPlayer на tvOS; кроссплатформенный нативный плеер на каждой ОС smart TV. Решение по платформе зависит от поддержки MSE, покрытия кодеками, требований к телеметрии и готовности команды поддерживать порт плеера.

iOS Safari, Managed Media Source и история про энергопотребление

Долгое время iOS Safari вообще не поддерживал MSE – поэтому в каждом видео-стеке 2010-х в итоге появлялся «iOS-путь», отдающий URL манифеста HLS нативному плееру, и «всё остальное», на котором работал hls.js или Shaka. Safari 17.0 на iPad и Mac в сентябре 2023 года и Safari 17.1 на iPhone в октябре 2023 года это изменили – но с ограничением: iOS Safari предоставляет Managed Media Source, а не классический MSE.

Разница важна по одной причине. Классический MSE даёт JavaScript плеера полный контроль над загрузкой, аппендом и эвикцией медиа; плеер может держать на устройстве пользователя две минуты буфера независимо от того, у пользователя 1% батареи или 100%. Managed Media Source инвертирует контроль: браузер ведёт бюджет memoryUsage и эмитит события (startstreaming, endstreaming), сообщающие плееру, когда загружать и когда остановиться. Работу по-прежнему делает плеер – браузер только сигналит намерение – но сигналы достаточно агрессивны, чтобы MMS-плеер на iPhone расходовал измеримо меньше батареи, чем расходовал бы MSE-плеер.

Apple добавила ещё одну возможность, которой MSE никогда не мог обладать: AirPlay поверх MMS. Функция WebKit 2024 года позволяет MMS-плееру передавать защищённый стрим на Apple TV через AirPlay с переоформлением лицензии FairPlay на уровне системы. Классический MSE никогда не мог этого делать: в момент привязки MediaSource к тегу <video> AirPlay отключался. Для любого продукта, который хочет транслировать защищённый контент с iPhone на Apple TV, MMS – единственный доступный путь.

Практический совет 2026 года: сначала выполняйте feature-детект ManagedMediaSource, затем используйте фоллбэк на MediaSource – и пусть один кодовый путь работает везде. hls.js, Shaka и Video.js v10 поставляют такую логику feature-детекта из коробки.

Smart TV: почему «тот же hls.js» там не поедет

Идея архитектуры из семи подсистем универсальна, но её реализации – нет. Smart TV представлены такими платформами, как Samsung Tizen, LG webOS, Roku, Android TV, Amazon Fire TV, Apple tvOS, Hisense Vidaa, а также длинным хвостом региональных решений – каждая из них предоставляет собственный рантайм, поддерживающий своё подмножество веб-стандартов.

Часть из них поставляет полноценный браузер. Samsung Tizen и LG webOS используют форк WebKit с поддержкой MSE и EME, так что JavaScript-плееры вроде hls.js или Shaka там работают с платформенными настройками: меньший буфер, консервативный выбор кодеков, ограниченное использование новых API. Другие платформы – например, Roku – используют доменно-специфичный скриптовый язык (BrightScript) и вообще не запускают JavaScript; плеер на Roku – это компонент Roku SDK, а не JavaScript-библиотека. Android TV использует ExoPlayer – нативную библиотеку на Kotlin/Java, без каких-либо браузерных плееров. tvOS – AVPlayer с нативной обёрткой на Swift.

Импликация для стриминг-продукта: «команда плеера» – редко одна команда. Типичный OTT- или e-learning-стек включает минимум три плеера: веб-плеер на JavaScript для Chrome, Firefox, Edge и Safari; мобильный плеер на ExoPlayer для Android и AVPlayer для iOS; и TV-плеер с платформенной интеграцией на Tizen, webOS, Roku, tvOS, Android TV, Fire TV и Vidaa. У каждой команды – своя матрица кодеков, своя матрица DRM, своя интеграция телеметрии и свой бэклог багов. Семь подсистем – одни и те же; исходные деревья – очень разные.

Что изменилось в 2026 году

Четыре обновления 2026 года стоит выделить отдельно, потому что они меняют возможности плеера.

MSE-in-Workers больше не является экспериментальной опцией. Chrome 108 сделал её стабильной, последний Working Draft MSE (4 ноября 2025) закрепляет паттерн cross-Worker MediaSourceHandle как нормативный, а hls.js, Shaka и dash.js поддерживают его через конфиг-флаг. Перенос парсинга сегментов в Worker заметно снижает нагрузку на главный поток и улучшает rebuffer ratio на менее мощных устройствах.

Common Media Client Data version 2 (CTA-5004-A, февраль 2026) расширяет оригинальный CMCD за счёт более обширного набора ключей и чёткой схемы отчётности по live-краю. Плееры, поддерживающие CMCDv2, передают в свои CDN и аналитические платформы более богатый контекст.

WebCodecs теперь широко поддерживается в Chrome, Edge и Firefox; Safari поддерживает VideoDecoder, хотя и не полностью реализует функционал энкодера. Продакшен-плееры на основе WebCodecs пока редки для массового HLS или DASH, но для low-latency live (с задержкой менее 500 мс), редактирования в браузере и любых продуктов, которым нужен покадровый доступ, WebCodecs – это слой, который стоит освоить.

Media over QUIC (MoQ) – протокол, о котором команда разработчиков плееров ещё не задумывалась, но через 12–18 месяцев ему придётся уделить внимание. draft-ietf-moq-transport от IETF MoQ Working Group обновляется примерно каждые два месяца; референсные реализации плееров существуют в Cloudflare moq-rs и Meta. MoQ-совместимая архитектура сохраняет те же семь подсистем, но с двумя изменениями: компонент загрузки манифеста исчезает (вместо него MoQ «пушит» track catalog), а загрузчик сегментов превращается в подписчика на QUIC-поток вместо цикла HTTPS GET. Всё, начиная с подсистемы 3 и далее, остаётся без изменений.

Где здесь Фора Софт

Мы реализовывали плеерные интеграции во всех форматах, описанных в статье: hls.js и Shaka в веб-продуктах, AVPlayer в iOS и ExoPlayer в Android – в мобильном приложении, а также платформенно-нативные оболочки на Tizen, webOS и Roku для OTT-устройств. Команды, работающие с наиболее чистыми стеками, воспринимают семь подсистем как контракт – один ABR-контроллер, один менеджер буфера, один EME-мост – и создают вокруг них платформенные шимы, а не переписывают все семь компонентов с нуля на каждом устройстве. Этот подход мы применяли в OTT-вещании, воспроизведении записей в телемедицине, повторных лекциях в e-learning, интерфейсах просмотра в системах видеонаблюдения и плеерах записанных конференций внутри WebRTC-стеков, где запись затем перекодируется в LL-HLS для воспроизведения.

Типичные ловушки, в одном абзаце

Две ловушки подстерегают каждую новую плеерную команду. Первая – считать, что семь подсистем – это семь JavaScript-классов. Это не так: это семь обязанностей, и в любом продакшен-плеере минимум две из них распределены по нескольким файлам, а минимум одна реализована совместно с браузером. Вторая – относиться к телеметрии как к фиче второй фазы. Без телеметрии вы не узнаете, работают ли подсистемы 1–6, и стоимость её внедрения после запуска неизменно в 10 раз выше, чем при включении в первую же версию плеера. Сделайте седьмую подсистему наравне с остальными шестью с самого первого дня.

Выводы

  • Плеер стриминга состоит из семи подсистем, а не одного компонента: манифест, загрузчик, ABR, буфер, декодер, DRM и телеметрия.
  • Media Source Extensions и Encrypted Media Extensions – два веб-стандарта, которые связывают JavaScript-часть с нативной частью браузера.
  • Managed Media Source в iOS Safari (17.0/17.1, 2023) заменяет классический MSE на устройствах Apple и позволяет использовать AirPlay поверх MSE.
  • ABR – наиболее отлаженная часть любого плеера; в продакшене применяются throughput-based, buffer-based (BOLA), гибридные (MPC) и нейронные алгоритмы.
  • Телеметрия – такие метрики, как время запуска, коэффициент ребуферизации, частота сбоев воспроизведения и доля пользователей, покинувших страницу до начала видео, – позволяет оценить, работают ли остальные шесть подсистем корректно или имеют проблемы.
  • Нативные плееры (AVPlayer в iOS, ExoPlayer в Android, SDK для smart TV) выигрывают по энергопотреблению и интеграции, но уступают по поддержке протоколов и возможности мониторинга.

Что почитать дальше

Строите такую систему?

Подберём параметры кодирования под ваш контент и посчитаем стоимость доставки до старта разработки.