Skip to content

Профили устройств

Не каждое устройство зрителя играет каждую дорожку стрима. Приставка не справляется с 720p60, телевизор не играет HEVC, плеер на webOS ломается на субтитрах. Профиль устройства прячет от такого устройства лишние дорожки и не трогает остальных зрителей.

Профиль — именованная запись с тремя частями:

  • как узнать устройство — по User-Agent, заголовку запроса или параметру адреса;
  • где профиль действует — режимы выдачи и стримы;
  • какие дорожки оставить — ограничения видео, аудио и субтитров.

Набор профилей один на весь кластер. Его хранит central и доставляет каждому стримеру вместе с остальной конфигурацией; решение принимает тот стример, к которому пришёл зритель, без обращения к central.

Профиль только сужает: убирает дорожки и никогда не добавляет. Это не средство допуска — зритель, подделавший заголовок, получит тот набор, который положен этому заголовку, а «4K только премиуму» решает политика допуска.

Как устроен профиль

Раздел консоли Профили устройств показывает профили в том порядке, в котором стример их перебирает. Карточка профиля открывается щелчком.

Раздел профилей: порядок перебора, профиль только по адресу и профиль, который стример не применил

В заголовке карточки:

  • имя профиля и его адрес p/<имя>/;
  • порядок, например порядок 10, а у профиля без условий — пометка только по адресу;
  • пометка изменён, если в профиле есть несохранённые правки.

Новый профиль заводит кнопка Добавить профиль: в окне Новый профиль задайте имя и нажмите Добавить профиль. Имя профиля — строчные латинские буквы, цифры и знаки ., _, -, до 64 символов, первая — буква или цифра. Имя входит в адрес p/<имя>/ (см. адреса под профилем). Профилей не больше 64: когда их 64, кнопка Добавить профиль недоступна. Новый профиль, как и любая правка, вступает в силу только после Сохранить (см. правку).

Как узнать устройство

Профиль выбирается, если совпало хотя бы одно условие:

  • User-Agent содержит — подстрока в заголовке User-Agent, регистр не важен: Roku совпадёт с Roku/DVP-14.5.
  • Заголовки запроса — имя заголовка и подстрока его значения, регистр не важен ни у имени, ни у значения. Так узнают устройство по заголовку, который ставит ваш middleware (X-CDN-DEV-MODEL: 4800X), или по готовому классу от CDN (CloudFront-Is-SmartTV-Viewer: true, X-UA-Device). Встроенной базы устройств у стримера нет.
  • Параметры адреса — имя параметра и список значений через запятую. Параметр совпал, если его значение целиком и с учётом регистра равно одному из значений: ?device_profile=arris совпадёт со значением arris, но не arris-4205 и не Arris. Значения пишутся раскодированными: + в адресе — это пробел, поэтому ?p=S10+ совпадёт со значением S10 (с пробелом), а значение S10+ — только с ?p=S10%2B.

Запрос без User-Agent с условием по User-Agent не совпадает.

Профиль без единого условия помечен только по адресу: стример выбирает его, только если адрес сам называет профиль (см. адреса под профилем).

Где действует

  • Порядок — у профилей с условиями обязателен и уникален: стример перебирает их по возрастанию и берёт первый подходящий. У профиля без условий не действует.
  • Режимы выдачи — на каких запросах профиль действует. По умолчанию — все три режима.
  • Теги стримов и Имена стримов — на каких стримах профиль действует: стрим входит, если несёт хотя бы один из тегов или назван по имени. Пусто — все стримы. Имён на все профили вместе — не больше 1000, область на многих стримах задавайте тегом.

Режимы выдачи:

  • Прямой эфир — запрос живого потока;
  • Архив — запрос с from;
  • Отмотка — адрес rewind/<секунды>/.

Теги стримов вводятся по одному: напишите тег и нажмите Enter. Тег — латинские буквы, цифры и знаки _, ., -, до 40 символов. Консоль проверяет тег сразу: тег другого вида в список не попадает, а под полем появляется ошибка. Тег, который уже есть в списке, второй раз не добавляется.

Какие дорожки оставить

Ограничения сгруппированы по типу дорожки, и каждая группа судит только дорожки своего типа:

  • Видео — Кодеки или Кроме кодеков, Ширина, Высота, Частота кадров.
  • Аудио — Кодеки или Кроме кодеков, Языки или Кроме языков, переключатель Не отдавать аудио.
  • Субтитры — Языки или Кроме языков, переключатель Не отдавать субтитры.

Поля одной секции влияют друг на друга:

  • заполненное поле Кодеки выключает Кроме кодеков, и наоборот: оба списка в одной секции central не примет;
  • так же заполненное поле Языки выключает Кроме языков, и наоборот;
  • включённый переключатель Не отдавать аудио или Не отдавать субтитры убирает все дорожки этого типа и прячет остальные поля секции.

Дорожка остаётся, если проходит все заданные ограничения своей группы; внутри одного ограничения достаточно совпасть с любым значением. Ширина, высота и частота кадров пишутся через запятую — точными значениями и диапазонами; у диапазона может не быть одной из границ:

1080, 720          ровно 1080 или ровно 720
..720              не больше 720
720..              не меньше 720
480..1080          от 480 до 1080 включительно
..30               не больше 30 кадров в секунду
25, 29.97          частота целым или десятичным числом, через точку
30000/1001         частота дробью

Дорожку, у которой ограниченное свойство неизвестно (нет частоты кадров, нет языка), ограничение не убирает: судить не о чем. Языки сравниваются по стандартному тегу: eng в описании дорожки и en в профиле — один язык; und («не определён») считается отсутствием языка.

Профиль без единого ограничения выбирается, но ничего не убирает.

Карточка профиля: условия, область и ограничения дорожек

Как выбирается профиль

Стример выбирает профиль на каждом запросе HLS master playlist (fMP4 и MPEG-TS, с LL-HLS и без) и DASH-манифеста во всех режимах выдачи:

  • Прямой эфир;
  • Архив;
  • Отмотка.

Выбор идёт так:

  1. Если адрес содержит сегмент профиля p/<имя>/ — выбран названный профиль, условия не проверяются.
  2. Иначе стример перебирает профили с условиями по возрастанию порядка и берёт первый, у которого совпало условие, а режим выдачи и стрим входят в его область.

На запрос действует ровно один профиль: ограничения разных профилей не складываются. Если профиль не выбран, зритель получает полный набор дорожек — ровно тот плейлист, что и без профилей.

Из master убранная дорожка исчезает вместе со своим вариантом или рендишеном; группа аудио или субтитров, в которой ничего не осталось, исчезает целиком. Если профиль убрал аудиодорожку по умолчанию, ею становится первая оставшаяся дорожка той же группы: группа — это дорожки одного кодека (см. звук разных кодеков).

Звук разных кодеков в HLS

HLS master собирает аудиодорожки в группы по кодеку. У стрима с AAC и AC-3 master даёт плееру две аудиогруппы, aac и ac3, и каждое качество видео — в паре с каждой из них. Плеер без декодера AC-3 пропускает варианты группы ac3 и играет AAC, а не теряет стрим целиком.

Профиль, у которого в секции Аудио в поле Кодеки выбран только aac, убирает AC-3 целиком: в master не остаётся ни группы ac3, ни её вариантов.

Плеер предлагает зрителю языки той группы, которую играет. Язык, который есть только в AC-3, плеер без декодера AC-3 не увидит.

Адреса под профилем

Решение принимается один раз, на master playlist, и дальше передаётся в адресе. Master, для которого профиль выбран по условиям, ведёт плеер на дочерние плейлисты под сегментом профиля:

/playback/v/<стрим>/index.m3u8                     запрос плеера
/playback/v/<стрим>/p/<профиль>/variant/v2/...     куда ведёт master

Плейлисты, части и сегменты под p/<профиль>/ на заголовки и параметры запроса не смотрят и одинаковы для любого зрителя этого адреса. Плейлист дорожки, которую профиль убрал, под p/ отвечает 404. Без сегмента профиля плейлист дорожки отдаётся любому зрителю: условия проверяются только на master.

Адрес с сегментом профиля можно поставить плееру и напрямую — так выбирает профиль витрина или middleware, которые знают устройство сами:

/playback/v/<стрим>/p/<профиль>/index.m3u8
/playback/v/<стрим>/p/<профиль>/Manifest.mpd
/playback/v/<стрим>/p/<профиль>/ts/index.m3u8
/playback/v/<стрим>/p/<профиль>/rewind/600/index.m3u8

Профиль, которого стример не знает (удалён, переименован или стример ещё не применил правку), или чья область не покрывает запрос, ничего не убирает: адрес под ним отдаёт полный набор, без ошибки.

Заголовок посредника и редирект. Когда central проксирует запрос, он передаёт стримеру заголовки плеера. Когда central отвечает редиректом на публичный адрес стримера, заголовок, который поставил посредник перед central (CDN, middleware), до стримера не доходит: плеер его не повторяет. В такой схеме выбирайте профиль адресом p/<профиль>/.

Адреса Flussonic

Адрес master по-старому (/<стрим>/index.m3u8?device_profile=arris) уводит на master /streaming/v/<стрим>/index.m3u8 с теми же параметрами, и профиль выбирается как обычно. Адрес одной дорожки (/<стрим>/tracks-v1/index.m3u8) ведёт прямо на её плейлист, без профиля.

Выбор дорожек по номерам Flussonic — параметр filter.tracks и адрес с набором дорожек вроде tracks-v1a1/index.m3u8 — Catena не выполняет: номера дорожек у неё другие, и зритель получает полный набор. Заведите профиль под это устройство; счётчик device_profile_track_numbers_total (см. диагностику) покажет, сколько таких запросов профилем не закрыто.

DASH

В DASH решение тоже принимается на манифесте: профиль убирает Representation с неподходящими дорожками, а AdaptationSet без единой Representation выпадает целиком. Манифест, выбранный по условиям, оставляет адреса сегментов в корне стрима; манифест под p/<профиль>/ ссылается на сегменты под тем же сегментом профиля.

Живой DASH-манифест плеер перечитывает, и каждое перечитывание выбирает профиль заново — по действующей редакции профилей. Правка профиля посреди просмотра может убрать Representation, которую плеер играет, и многие плееры на этом останавливаются. Радикальную правку делайте новым профилем (см. правку).

У DASH нет отмотки: профиль, который действует только на Отмотке, на манифест не влияет.

Пустой результат

Если после отбора не осталось ни одной дорожки ведущего типа — видео, а у стрима без видео — аудио, — стример отвечает на master 400 с кодом device_profile_empty и пишет предупреждение в журнал. Полного набора зритель не получит: это ровно то, от чего профиль прятал устройство. Только аудио стриму с видео тоже не отдаётся: плеер устройства такой master за видео не примет.

Так же отвечает и адрес p/<профиль>/: его увидит витрина, которая этот адрес поставила. Исправляется пустой результат областью профиля (теги, режимы) или более мягкими ограничениями.

Правка, удаление и переименование

Удаляет профиль кнопка Удалить в карточке, переименовывает — Переименовать. Новый профиль, удаление и переименование, как и правка полей, вступают в силу только после Сохранить: до этого они есть только в форме. Кнопка Отмена сбрасывает все несохранённые правки вместе с недописанными полями.

Кнопка Сохранить отправляет только изменённые поля. Если профили правили параллельно, форма покажет конфликт; ваши правки остаются в форме — Показать актуальное перечитает документ без ваших правок, Перенести мои правки применит их к актуальной версии. Результат остаётся в форме несохранённым: проверьте его — например, профиль, который другой оператор удалил, а вы правили, вернётся только с вашими полями — и сохраните. Пока в форме есть недописанное поле (граница, которая не разобралась, условие без имени или значения, повтор имени), Сохранить недоступна.

Правка доходит до стримеров без рестарта и без пересчёта размещения. Плеер HLS читает master редко, поэтому правка, скрывшая дорожку, которую он играет, приведёт к 404 на её плейлист, и плеер переключится на другую. В DASH живой манифест перечитывается, и правка действует сразу. Поэтому:

  • мелкая правка (сузить диапазон, добавить кодек в Кроме кодеков) — правьте профиль;
  • радикальная правка (убрать целое качество, сменить кодек) — заведите профиль с новым именем и переведите на него условия или адреса витрины.

Переименование — это удаление и создание. Плееры, открывшие поток под прежним именем, получат полный набор дорожек, пока не перечитают master. Удаление работает так же: адрес под удалённым профилем отдаёт всё.

Если профиль не действует

Стример может не применить профиль, если central записал значение, которого версия стримера не знает. Остальные профили и вся конфигурация стримера при этом применяются. Где это видно:

  • в разделе Профили устройств — пометка Не применён на стримерах в заголовке карточки: имена стримеров, причина в скобках и путь до поля, например e1 (parse) video.codecs[1]; имя ведёт на страницу стримера. В раскрытой карточке — тексты отказов, которые прислали стримеры;
  • на странице стримера — блок рядом с ошибкой применения конфигурации: имя профиля, причина, путь до поля и сообщение;
  • в API — поле rejected_profiles в GET /central/api-v4/nodes/stats;
  • в метриках стримера — device_profile_rejected{reason}.

Причины:

  • parse — поле не разобралось: незнакомое значение или тип;
  • invalid — профиль разобрался, но не прошёл проверку;
  • limit — профиль сверх 64.

Стример версии, которая профилей не знает вовсе, отдаёт все дорожки любому зрителю, а central на правку профиля отвечает успехом. Консоль предупреждает об этом в двух местах:

  • в разделе Профили устройств — общий баннер над списком «Профили не действуют на стримерах, версия которых их не поддерживает…» со ссылками на такие стримеры;
  • на странице стримера — подпись «Профили на стримере не действуют: его версия их не поддерживает…».

Пометка появляется, только когда в документе профилей есть хотя бы один профиль. Отозванным стримерам и стримеру, который после старта ещё не применил конфигурацию, она не ставится.

Страница стримера: профиль, который стример не применил, с причиной и путём до поля

Обновление и откат

  • Заводите профили после обновления всех стримеров. Стример прежней версии не знает адресов p/ и ответит на них 404, если master пришёл с обновлённого стримера, а дочерний плейлист — со старого.
  • Откат central на версию без профилей выключает их на всём кластере до возврата: стримеры получают конфигурацию без профилей. Документ профилей остаётся в базе, и возврат central доставит его без правки.
  • Откат central на одну версию назад доставку не ломает: стримеры получают профили как есть. Поле, которое знает только новая версия, мешает лишь правке, в которой это поле есть: она отвечает 422. Незнакомое значение (например, новый кодек) приводит к 422 на любую правку документа, пока это значение не удалят.
  • После отката central сохраните конфиг каждого стримера любой правкой: стример, который был офлайн во время отката, иначе может остаться с прежней конфигурацией.

Ограничения

  • Частота кадров в архиве не ограничивает: в описании записи её нет, и неизвестное свойство дорожку не убирает. В эфире и при отмотке ограничение работает, высота, ширина и кодек работают и в архиве.
  • Профилей — не больше 64, имён стримов в областях всех профилей — не больше 1000.
  • Профиль действует только на HLS (включая LL-HLS и MPEG-TS) и DASH; выдачу, перечисленную ниже, он не трогает.
  • Формата Flussonic 720p60 нет: высота и частота — независимые ограничения, и «убрать 720p60, оставить 1080p60» одним профилем не выражается.

Выдача, на которую профиль не действует:

  • MSE;
  • MPEG-TS по HTTP;
  • fMP4-поток;
  • MSS;
  • VOD.

Диагностика

Счётчики стримера (Prometheus) по каждому профилю:

Счётчик Что считает
device_profile_checks_total{profile} master и манифесты, где стример сверял условия профиля
device_profile_input_absent_total{profile} из них — запросы без единого заголовка и параметра, названных в условиях
device_profile_selected_total{profile, by} профиль выбран: by="match" — по условиям, by="path" — адресом
device_profile_noop_total{profile} выбран, но ничего не убрал
device_profile_empty_total{profile} ответы 400 пустого результата
device_profile_undescribed_total{profile} плейлисты архива под профилем, где у записи нет описания дорожек и отбор не сработал
device_profile_unknown_total запросы под профилем, которого стример не знает
device_profile_track_numbers_total{covered} запросы с выбором дорожек по номерам Flussonic; covered="false" — профиль их не закрыл

Как читать:

  • checks и input_absent растут вместе, selected — нет. Заголовок или параметр до стримера не доходит: его срезает CDN, прокси или редирект. Выбирайте профиль адресом p/<профиль>/.
  • checks не растёт. До профиля в переборе не доходит: раньше выбирается другой профиль, или запрос не попадает в его режимы и стримы.
  • selected растёт вместе с noop. Профиль выбирается, но у стрима нет дорожек под его ограничения.

Профили через API

Документ профилей — GET и PATCH (JSON Merge Patch) на /central/api-v4/device_profiles. PATCH меняет только названные профили, null под именем удаляет профиль; передайте If-Match с ETag из чтения, чтобы параллельная правка вернулась 412, а не перезаписалась:

curl -X PATCH http://<адрес central>/central/api-v4/device_profiles \
  -H 'Content-Type: application/merge-patch+json' -H 'If-Match: "<etag>"' \
  -d '{
    "roku-4800x": {
      "priority": 10,
      "match": {"headers": {"x-cdn-dev-model": "4800x"}},
      "video": {"fps": [{"max": 30}]}
    },
    "arris": {
      "priority": 20,
      "match": {"query": {"device_profile": ["arris", "arris-4205"]}},
      "video": {"codecs": ["h264"]}
    },
    "webos": {
      "priority": 30,
      "match": {"user_agent": "Web0S"},
      "text": {"exclude_all": true}
    }
  }'

Ошибка в документе возвращается 422 с путём до поля — тем же, что подсвечивает консоль. Стример отдаёт применённые им профили по GET /streamer/api-v4/device_profiles.