SCTE-35 и сигнализация рекламы в стриминге

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

TL;DR

SCTE-35 – это маленькая машиночитаемая метка внутри видеопотока, которая говорит: «здесь начинается рекламная пауза, и она такой-то длины». Это внутрипотоковый сигнал, который читает любая система серверной вставки рекламы, прежде чем загрузить и вшить ролик, – поэтому SCTE-35 лежит в основе почти любого рекламного потока: live-каналов, бесплатного ТВ с рекламой (FAST) и видео по запросу с рекламой (AVOD). Эта статья объясняет, откуда берётся метка (система автоматизации обращается к энкодеру по SCTE-104), что лежит внутри сообщения (splice_info_section, команды splice_insert и time_signal, и segmentation-дескрипторы, задающие тип перерыва), как метка переносится из вещательного транспортного потока в манифесты HLS и MPEG-DASH и как ad decision server (VAST/VMAP) и ститчер превращают её в настоящую рекламу. Сигнализация сделана верно – паузы срабатывают кадр-в-кадр на любом устройстве; сделана неверно – паузы рвут фразу на полуслове, не срабатывают или прогоняют рекламу через контент, который по договору должен идти чистым.

Почему это важно

Если вы запускаете или строите рекламный стриминг, SCTE-35 – это разница между паузой, которая встаёт ровно, и паузой, которой не случилось вовсе. Это сигнал, связывающий ваш контент с деньгами: серверная вставка рекламы, на которую вы опираетесь, не вставит ролик, пока что-то в потоке не скажет, где перерыв, какой он длины и какого типа. Реклама на connected-TV в США прогнозируется примерно в $37,95 млрд в 2026 году (прогнозы eMarketer/индустрии, 2026), и live, linear и FAST-каналы, которые двигают этот рост, держатся на одном вещательном стандарте. Эта статья – руководство по самой метке: что это, откуда берётся, что несёт и как доходит до плеера, – и спутник к карте монетизации OTT, которая показывает, где рекламный доход стоит среди всех способов заработка платформы.

Одна задача: как поток говорит «здесь реклама»

Начнём с проблемы, ради которой существует SCTE-35. Платформа хочет заменять или вставлять рекламу в точные моменты программы – между иннингами, на границе главы, при возврате с федерального фида на местный. Но само видео – это лишь последовательность картинок и звука; в нём нет встроенного понятия «вот здесь идёт рекламный ролик». Что-то должно точно отметить это место так, чтобы каждая машина дальше по цепочке прочитала его одинаково.

Эта метка – SCTE-35, стандарт сигнализации от Society of Cable Telecommunications Engineers (SCTE), официально называемый Digital Program Insertion Cueing Message; впервые опубликован в 2001 году, последняя редакция – ANSI/SCTE 35 2023r1 от 30 ноября 2023 года. Сообщение SCTE-35 – это крошечный пакет данных, переложенный с аудио и видео, который объявляет о приближающейся точке склейки: где она на таймлайне, выходит ли поток из программы или возвращается в неё и – всё чаще – какого типа эта граница.

Вот аналогия, которую стоит держать в голове. Метка SCTE-35 – это пометка мелом, которую киномонтажёр царапал на плёнке: «режь здесь, вставь рекламу». Плёнка не знает, что такое реклама; пометка делает всё за неё, и любой монтажёр в любой монтажной прочитает её одинаково. SCTE-35 – это та же пометка, только это точная цифровая метка времени, которую машины – энкодеры, пакетайзеры, ad-серверы, ститчеры – читают автоматически и без человека в комнате. Всё остальное в статье – детали о том, как эту пометку пишут, переносят и читают.

Чего метка не делает – так это не содержит саму рекламу. SCTE-35 лишь отмечает возможность; стандарт «определяет внутрипотоковый механизм сообщений для сигнализации возможностей склейки и вставки» и сознательно ничего не говорит о том, что именно вставляется (ANSI/SCTE 35 2023r1, §1.2). Выбор и доставка самого ролика – отдельная работа ad decision server и ститчера, к которым мы вернёмся ниже.

Рисунок 1. Цепочка сигнализации. Система автоматизации запрашивает метку по SCTE-104; энкодер пишет сообщение SCTE-35 в поток; пакетайзер переносит её в манифесты HLS и DASH; ad decision server и ститчер превращают её в рекламу.

Откуда берётся метка: от SCTE-104 к SCTE-35

Метка не появляется по волшебству. В live- или linear-канале она обычно рождается на шаг раньше – в системе автоматизации, плейаут-софте, который ведёт канал и знает расписание. Когда расписание доходит до рекламной паузы, автоматизация отправляет энкодеру запрос отметить перерыв. Этот запрос идёт по родственному стандарту SCTE-104 – интерфейсу обмена между системой автоматизации и оборудованием компрессии/энкодинга.

Разделение ролей чистое и его стоит запомнить. SCTE-104 – это запрос: «вставь перерыв здесь», выданный автоматизацией и привязанный к вещательным часам (по UTC, по timecode VITC или по аппаратному триггеру). SCTE-35 – это исполнение: энкодер получает запрос SCTE-104 и в нужный момент пишет сообщение SCTE-35 в исходящий поток, неся всё, что понадобится системам дальше. Одно – инструкция энкодеру; другое – стойкая метка, которую энкодер оставляет в потоке для всех после себя.

Не каждая метка начинается с SCTE-104. Платформа может вставить SCTE-35 прямо на этапе пакетирования для VOD-ассетов или генерировать метки из out-of-band расписания (об этом – в разделе про SCTE 224 ниже). Но связка SCTE-104 → SCTE-35 – канонический live-путь, и понимание этого объясняет, почему пропавшая или сбитая по времени пауза так часто оказывается проблемой выше по течению – сбоем в запросе автоматизации или его тайминге, а вовсе не в плеере.

Анатомия сообщения SCTE-35

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

Конверт открывается фиксированным идентификатором table_id, значение которого всегда 0xFC (ANSI/SCTE 35 2023r1, §9.6.1) – поэтому инженеры иногда зовут SCTE-35 «таблицей 0xFC». Дальше – несколько служебных полей: protocol_version (сейчас всегда 0), 33-битный pts_adjustment, который держит тайминг метки верным, если поток где-то ре-стемпят, и 12-битный tier для маршрутизации или фильтрации меток. После служебной части идёт главное: splice_command_type, называющий, какую инструкцию несёт сообщение, затем сама команда, затем опциональный список дескрипторов, добавляющих смысл, и наконец контрольная сумма CRC_32, по которой приёмник убеждается, что сообщение дошло целым.

Стандарт определяет шесть типов команд, но на практике важны лишь несколько (ANSI/SCTE 35 2023r1, Table 7):

HexКомандаРоль сегодня
0x00splice_nullHeartbeat / keep-alive; склейки не несёт.
0x04splice_scheduleПланирует склейки заранее; в стриминге редка.
0x05splice_insertКлассическая команда «cue out / cue in» для перерыва.
0x06time_signalТочка во времени, смысл которой задают дескрипторы.
0x07bandwidth_reservationРезервирует полосу; нужна в некоторых спутниковых трактах.
0xFFprivate_commandВендорские, нестандартные нагрузки.

Таблица 1. Типы команд SCTE-35. В современном стриминге вы почти всегда работаете с splice_insert (0x05) и time_signal (0x06); остальное – legacy или нишевое.

Две команды, несущие рекламные паузы, – splice_insert и time_signal – заслуживают отдельного раздела, потому что разница между ними – самое полезное, что стоит понять про SCTE-35.

Рисунок 2. Внутри конверта. `splice_info_section` несёт служебные поля, одну команду склейки (`splice_insert` или `time_signal`), опциональный цикл дескрипторов, маркирующих перерыв, и контрольную сумму CRC.

Две команды, которые несут перерыв: splice_insert против time_signal

Более старая и простая команда – splice_insert. Она описывает рекламный перерыв своими собственными полями. Ключевое – единственный бит out_of_network_indicator: когда он 1, метка отмечает out point – момент выйти из программы в рекламу («cue-out»); когда 0, метка отмечает in point – момент вернуться в программу («cue-in») (ANSI/SCTE 35 2023r1, §9.7.3.1). splice_insert может нести и break_duration (длину avail), и unique_program_id, чтобы связать cue-out с парным cue-in. Для простого «уйти на 90 секунд рекламы и вернуться» splice_insert говорит всё, что нужно.

Более новая и богатая команда – time_signal. Сама по себе time_signal несёт только метку времени – точную точку на таймлайне и ничего больше. Её смысл задают целиком прикреплённые дескрипторы. Стандарт прямо говорит: когда time_signal используется для сигнализации событий склейки, она «должна нести один или более segmentation-дескрипторов» с дополнительной информацией о том, что делать (ANSI/SCTE 35 2023r1, §9.3). Звучит как слабость, но это наоборот сила – именно это позволяет time_signal выражать то, что splice_insert не может: «это начало provider placement opportunity для конкретной программы с таким-то ID» или «это граница главы, а не реклама».

Практический вывод, к которому пришла вся отрасль: splice_insert – legacy, но всё ещё широко используется для простых перерывов; time_signal плюс segmentation-дескриптор – современный выбор по умолчанию, потому что несёт идентичность и намерение, на которые опирается таргетированная реклама. Надёжная платформа читает обе, потому что реальные фиды сверху присылают обе.

Рисунок 3. Два способа отметить перерыв. `splice_insert` описывает перерыв своими полями; `time_signal` несёт лишь метку времени и опирается на segmentation-дескриптор ради идентичности и намерения.

Segmentation-дескрипторы: какой это перерыв

Segmentation-дескриптор – это надстройка, превращающая голую метку времени в осмысленное событие. Это часть SCTE-35, которая говорит что это за граница, а не только когда. Он несёт три важные вещи.

Во-первых, segmentation_type_id – число, называющее тип границы. Вот где «здесь реклама» становится конкретной. Рекламно значимые значения – те, с которыми живёт стриминг-команда; ниже самые важные, с колонкой, какая команда может нести каждое (матрица совпадает с тем, как трактуют их продакшн-энкодеры, например Bitmovin):

Type IDТип сегментацииНесёт splice_insert?Несёт time_signal?
0x10 / 0x11Program Start / EndДаНет
0x20 / 0x21Chapter Start / EndДаНет
0x22 / 0x23Break Start / EndДаДа
0x30 / 0x31Provider Advertisement Start / EndДаДа
0x32 / 0x33Distributor Advertisement Start / EndДаДа
0x34 / 0x35Provider Placement Opportunity Start / EndДаДа
0x36 / 0x37Distributor Placement Opportunity Start / EndДаДа
0x40 / 0x41Unscheduled Event Start / EndДаНет

Таблица 2. Рекламно значимые segmentation type ID (ANSI/SCTE 35 2023r1, Table 23). «Placement Opportunity» (0x34–0x37) – тип, который большинство ad-систем трактует как заменяемый рекламный avail; «Provider» против «Distributor» говорит, кому принадлежит инвентарь. Правые две колонки показывают, какой командой обычно несётся каждый тип, – placement-opportunity и advertisement спокойно едут на time_signal, поэтому таргетированная реклама использует именно её.

Самое важное различие в таблице – «placement opportunity» против «advertisement». Placement opportunity (0x34–0x37) – слот, который платформе предложено заполнить своим динамически выбранным роликом; именно на это нацелена динамическая вставка рекламы. Простой маркер advertisement (0x30–0x33) описывает ролик, уже находящийся в фиде. А «provider» против «distributor» отвечает, кому принадлежит инвентарь: контент-провайдеру (сети) или дистрибьютору (вам, платформе, которая её несёт).

Во-вторых, segmentation-дескриптор несёт UPIDunique program identifier (уникальный идентификатор программы), – который говорит, какой именно это кусок контента или какой это перерыв. У UPID есть тип, и тип говорит приёмнику, как читать байты. Распространённые типы UPID: Ad-ID (0x03, стандартный рекламный идентификатор отрасли), TMS/TID (0x08), EIDR (0x0A, реестровый ID для фильмов и сериалов), обобщённый URI (0x0F) и UUID (0x10). UPID – это то, как ad decision server сопоставляет перерыв с кампанией, правилом блэкаута или корзиной отчётности.

В-третьих, он несёт флаги ограничений – прежде всего web_delivery_allowed_flag и no_regional_blackout_flag, – которые кодируют, можно ли доставлять этот контент web/OTT-аудитории или его нужно блэкаутить в определённых регионах. Так ограничения прав на спорт и синдикацию едут вместе с меткой.

Часы и упреждение: показываем математику

Срабатывание перерыва там, где надо, определяют два числа, и оба стоит проговорить вслух, потому что они объясняют значительную долю реальных багов рекламного тайминга.

Первое – часы. Метки времени SCTE-35 выражены как pts_time, 33-битное значение, считающее тики часов на 90 000 тиков в секунду – тех же 90 kHz-часов представления, что MPEG использует для тайминга видео. Чтобы перевести момент по настенным часам в pts_time, умножьте секунды на 90 000:

точка склейки на 1 ч 23 мин 45,5 с от начала потока
секунды   = (1 × 3600) + (23 × 60) + 45,5 = 5025,5 с
pts_time  = 5025,5 × 90 000 = 452 295 000 тиков

Поскольку поле 33-битное, наибольшее значение, которое оно вмещает, – 2³³ − 1, так что часы обнуляются примерно каждые:

2^33 ÷ 90 000 ≈ 8 589 934 592 ÷ 90 000 ≈ 95 443 с ≈ 26,5 часа

Это переполнение каждые ~26,5 часа – причина, по которой канал 24/7 не может просто доверять «сырым» меткам времени, что они будут расти вечно, и почему существует поле pts_adjustment для коррекции тайминга при ре-стемпинге. Единицы важны: метка времени, сбитая на 90 000 тиков, – это ровно одна секунда рассинхрона, реклама, стартующая на секунду внутрь следующей фразы ведущего.

Второе число – упреждение. Метка бесполезна, если приходит к ститчеру слишком поздно, чтобы на неё среагировать. Руководство стандарта по pre-roll конкретно: метку «можно отправить за 8, 5, 4 и 2 секунды до» точки склейки, и предупреждает, что «любое сообщение, полученное менее чем за 4 секунды предупреждения, может не дать желаемого результата» (ANSI/SCTE 35 2023r1, §9.1). Рабочее правило из этого: сигнализируйте рекламные паузы минимум за 4 секунды и в идеале повторяйте метку несколько раз на подходе, чтобы приёмник, пропустивший одну копию, всё же поймал другую. Большинство инцидентов «пауза не сработала» уходят корнями в метку, пришедшую внутри этого 4-секундного окна.

Рисунок 4. Бюджет упреждения. Метку шлют несколько раз до точки склейки, чтобы приёмник, пропустивший одну копию, всё же сработал вовремя; метки, пришедшие позже чем за 4 секунды, могут не сработать.

Из транспортного потока в манифест: SCTE-35 в HLS и DASH

Пока метка живёт в транспортном потоке MPEG-2 – вещательном контейнере для контрибуции и live-фидов, – где едет на своём выделенном потоке, опознаваемом по PID (идентификатору пакетов), указанному в program map table. Но зритель на телефоне или Smart TV смотрит не транспортный поток; он смотрит сегменты, названные в манифесте HLS или MPEG-DASH – маленьком плейлисте, который говорит плееру, какие чанки качать. Значит, метку надо перевести из транспортного потока в манифест. Этот перевод – работа пакетайзера, и именно здесь стриминг-команды реально встречают SCTE-35.

В HLS (формат Apple, RFC 8216) метка всплывает несколькими способами, от простого к богатому:

#EXTINF:4.0,
segment_18188.ts
#EXT-X-CUE-OUT:90.000        ← выйти на 90-секундную рекламу (cue-out)
#EXTINF:4.0,
ad_segment_0001.ts
...
#EXT-X-CUE-IN                 ← вернуться в программу (cue-in)
#EXTINF:4.0,
segment_18221.ts

Пара #EXT-X-CUE-OUT / #EXT-X-CUE-IN выше – простейшая форма по длительности, которую принимают многие сервисы вставки рекламы. Для полной точности HLS использует тег #EXT-X-DATERANGE, способный нести «сырые» байты исходной метки. RFC 8216 указывает, что пара out/in, сигнализированная splice_insert, «ДОЛЖНА быть представлена одним или более тегами EXT-X-DATERANGE»: секция out-точки помещается в атрибут SCTE35-OUT, а in-точки – в SCTE35-IN (RFC 8216, §4.3.2.7.1):

#EXT-X-DATERANGE:ID="ad-break-42",START-DATE="2026-06-17T12:30:00Z",
  DURATION=90.000,SCTE35-OUT=0xFC30200000...

Некоторые энкодеры также выдают теги #EXT-OATCLS-SCTE35 или #EXT-X-SCTE35 с base64- или hex-кодированным «сырым» сообщением SCTE-35, чтобы система ниже могла перечитать исходную метку в точности. Какой тег выдавать, зависит от того, что документирует ваш сервис вставки рекламы.

В MPEG-DASH (ISO/IEC 23009-1) метка выражается как событие внутри манифеста (MPD). SCTE 214 – набор, профилирующий DASH под эти сервисы, – определяет два пути переноса: out-of-band события в MPD как EventStream и in-band события в сегментах как боксы emsg. Форма в MPD выглядит так:

<Period start="PT32S" id="2">
  <EventStream schemeIdUri="urn:scte:scte35:2014:xml+bin" timescale="90000">
    <Event duration="8100000" id="42">
      <Signal xmlns="urn:scte:scte35:2013:xml">
        <Binary>/DAvAAAAAAAAAP/wBQb+AAAAAAAZAhdDVUVJ...==</Binary>
      </Signal>
    </Event>
  </EventStream>
</Period>

Элемент Binary держит то же сообщение SCTE-35, кодированное в base64 по RFC 4648 (ANSI/SCTE 35 2023r1, §7.4) – доказательство, что HLS и DASH – два конверта, несущих одну и ту же исходную метку. Про механику самих форматов манифестов см. HLS и DASH в разделе Video Streaming; здесь нас интересует лишь то, как метка едет внутри них. То, что одна метка из транспортного потока чисто отображается в оба манифеста, и позволяет одним проходом сигнализации обслужить все устройства – тот же принцип, что и при упаковке CMAF, HLS и DASH из одного mezzanine.

Рисунок 5. Одна метка, два конверта. Пакетайзер рисует одно и то же сообщение SCTE-35 как теги HLS `EXT-X-DATERANGE` / `CUE-OUT` и как DASH MPD `EventStream`, чтобы перерыв увидело каждое устройство.

Рукопожатие: как метка становится рекламой

Метка – начало разговора, а не его конец. Как только маркер доходит до слоя вставки рекламы, четыре шага превращают его в рекламу на экране.

Ститчер (при серверной вставке) или рекламный компонент плеера (при клиентской) обнаруживает метку в манифесте и читает её тип и длительность. Затем он зовёт ad decision server – систему, которая выбирает, какой ролик показать, – используя рекламный запросный стандарт отрасли VAST (Video Ad Serving Template, от IAB Tech Lab), часто оркестрованный по всему перерыву через VMAP (описывает весь набор рекламных слотов в куске контента). Ad decision server возвращает ролик. Наконец, при серверной вставке ститчер подгоняет этот ролик под лестницу качества контента и переписывает манифест так, чтобы реклама играла как часть одного непрерывного потока.

Две границы держат статью в фокусе. Вся цепочка запрос-ответ VAST/VMAP – отдельная тема, раскрытая в ad serving, VAST/VMAP и рекламный стек; а архитектура ститчинга – почему серверная вставка обходит ad-блокеры и держит паузы плавными – раскрыта в SSAI против CSAI. Работа SCTE-35 заканчивается там, где те начинаются: она даёт где, как долго и какого типа, что нужно ad decision server, чтобы действовать. Без верной метки самому изощрённому рекламному стеку в мире не на что срабатывать.

Out-of-band расписание: SCTE 224 и ESNI

Внутрипотоковые метки – не единственный способ управлять рекламой и контентом. SCTE 224, Event Scheduling and Notification Interface (ESNI), – это out-of-band, API-стандарт, который несёт расписания и политику – какие программы где могут идти, когда применяется региональный блэкаут, какая аудитория видит какой контент – как структурированные данные рядом с потоком, а не внутри него. Если SCTE-35 – это кадр-в-кадр пометка мелом внутри потока, то SCTE 224 – отдельно доставленный свод правил, который говорит системам, как трактовать и применять эти пометки по регионам и аудиториям.

Эти двое дополняют друг друга, а не конкурируют. Live-спорт обычно использует SCTE-104/35 для точного внутрипотокового тайминга каждого перерыва и SCTE 224 для политики верхнего уровня – эта игра в блэкауте на этих рынках, этот перерыв доступен для местной продажи на тех. Платформа, обслуживающая несколько территорий или продающая локальный инвентарь, рано или поздно нуждается в обоих; единый региональный AVOD-каталог часто может начать с одного SCTE-35.

Частая ошибка: доверять метке, не подготовив поток

Повторяющийся провал в рекламной сигнализации – считать метку всей работой. Команда настраивает pass-through SCTE-35, видит маркеры в манифесте и полагает, что реклама встанет ровно, – а потом обнаруживает паузы, стартующие с запозданием, ролики, которые не срабатывают, или перерывы, обрывающие ведущего на полуслове. Корень почти всегда – одна из трёх специфичных для сигнализации ошибок, ни одну из которых рекламный стек сам не починит.

Первая – точка склейки не попадает на границу сегмента. Плеер может переключать поток только на краю сегмента, так что если pts_time метки падает в середину чанка, склейка округляется к ближайшей границе и уезжает. Лечение – свести кодирование так, чтобы граница сегмента (IDR-кадр, на который плеер может переключиться) стояла ровно на точке склейки; ради этого энкодер вставляет keyframe в метке. Вторая – поздняя метка: маркер, доставленный внутри 4-секундного окна упреждения, о котором предупреждает стандарт, и который ститчер может просто проигнорировать. Третья – потеря дескрипторов: тракт, сохраняющий голый time_signal, но срезающий его segmentation-дескриптор, доставляет метку времени без смысла, так что ad-сервер не отличит placement opportunity от границы главы. Верная рекламная сигнализация – это не «есть ли маркеры», а «точны ли они, достаточно ли ранние, на границе ли и полны ли». Это дисциплина контроля качества, а не галочка.

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

Рекламная сигнализация – там, где вещательная точность встречает стриминговый масштаб, и дорогие провалы тихие: перерыв, срабатывающий на секунду позже у каждого зрителя; блэкаут, протёкший потому, что срезали флаг ограничения; федеральный фид, чьи местные avail так и не открылись, потому что segmentation-дескриптор срезали в пакетировании. Фора Софт строит видеостриминговые и OTT/Internet-TV платформы с 2005 года, на 250+ выпущенных проектах для 400+ клиентов, – а значит, мы прокладывали тракты SCTE-104-в-SCTE-35 для live-каналов, готовили энкоды так, чтобы точки склейки падали на границы сегментов, верно несли метки в манифесты HLS и DASH и связывали их с ad decision server и серверными ститчерами, держащими live-нагрузку. Наша позиция – scalability-first и нейтральность к вендорам: мы стартуем от масштаба и точности, которых требуют ваши каналы – кадр-в-кадр паузы на любом устройстве, верные блэкауты на любой территории, – и строим тракт сигнализации и вставки рекламы, который реально нужен вашим live-, FAST- и AVOD-потокам.

Ключевые выводы

  • SCTE-35 – внутрипотоковая метка, отмечающая, где начинается перерыв и какой он длины.
  • Она лишь отмечает возможность; саму рекламу дают ad decision server и ститчер.
  • splice_insert – legacy cue-out/cue-in; time_signal плюс дескриптор – современный выбор.
  • Segmentation type ID и UPID говорят, какой это перерыв и какому контенту он принадлежит.
  • Метки должны приходить минимум за 4 секунды и падать на границу сегмента, чтобы сработать.
  • Пакетайзер переводит одну метку из транспортного потока в маркеры HLS и DASH.

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

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

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