Упаковка just-in-time против pre-packaged origin

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

TL;DR

Стриминговый origin может хранить каталог в одной из двух форм. Форма pre-packaged один раз при ингесте записывает на диск каждый плейлист HLS, каждый MPD DASH и каждый короткий сегмент – и далее отдаёт их как статические HTTP-объекты навсегда. Форма упаковки just-in-time, сокращённо JIT или JITP, хранит на диске один fragmented-MP4 мастер на каждую ступень bitrate-лесенки и синтезирует плейлисты, MPD и сегменты, адаптированные под конкретный протокол, в момент запроса плеера. JIT заменяет хранилище на вычислительные ресурсы origin’а – типично экономия хранилища в 3–5 раз при росте вычислительной нагрузки на origin в 5–20 раз – и даёт стратегическое преимущество, недоступное при pre-packaging: новый протокол, нюанс упаковки или DRM-правило можно внедрить на каталог из тысячи тайтлов одним обновлением origin’а, а не перепаковкой всего каталога. Для стриминговой платформы 2026 года с сотнями тайтлов и более JIT – это стандарт, а архитектура, в которую он встроен – CMAF-совместимый fMP4 мастер на каждую ступень, JIT origin за origin shield, CDN с длинными TTL на сегменты и короткими – на манифесты – это форма, к которой приходит любая серьёзная OTT-, спортивная или e-learning-платформа.

Кому и зачем это нужно

Упаковка – это строка расходов на хранилище, которую большинство продакт-менеджеров игнорируют, пока счёт AWS не утроится. Готовые origin-пакеты могут незаметно увеличить объём хранилища в двенадцать раз – как только вы добавите HLS, DASH, несколько аудиодорожек и пару low-latency-вариантов. И каждый гигабайт будет списываться с счёта каждый месяц – смотрит на него кто-то или нет. JIT origin заменяет эту строку хранилища на строку CPU origin’а, а новая статья хуже прогнозируется: она зависит от того, насколько cache-friendly построен путь JIT, как настроен CDN, стоит ли перед ним origin shield и сколько трафика catch-up переживает cache miss. Выберите не ту форму – переплатите либо за хранилище, которое никто не смотрит, либо за вычислительные ресурсы, которые могли бы покрыть всего одно правило кэширования. Эта статья объясняет обе формы с нуля, даёт реальную арифметику, по которой между ними выбирают, и показывает архитектуру, необходимую для каждого JIT-деплоя, чтобы он был достаточно cache-friendly, чтобы выгода от обмена реально работала.

Что хранит стриминговый origin

Прежде чем говорить о том, как origin упаковывает контент, важно чётко понимать, что такое origin. Стриминговый origin – это HTTP-сервер, с которым CDN взаимодействует, когда edge-кеши ещё не имеют нужного файла, запрошенного зрителем. Origin – это источник истины: каждый байт, который зритель в итоге воспроизведёт, изначально поступает отсюда. CDN копирует байты с origin’а на edge-серверы и отдаёт их зрителям с ближайших edge-узлов, расположенных рядом с телефоном или телевизором зрителя. (Обзор окружающего пайплайна – в статье Конвейер стриминга от и до.)

Работа origin’а – отвечать на два вида HTTP-запросов. Первый – запрос манифеста, то есть небольшого текстового файла, в котором перечислены все уровни качества, между которыми может переключаться плеер, все короткие сегменты внутри каждого уровня, а также любые альтернативы аудио или субтитров. Манифесты HLS – текстовые .m3u8; манифесты DASH – XML-файлы .mpd. Второй вид – запрос сегмента, то есть бинарного фрагмента видео или аудио продолжительностью 2–6 секунд, упакованного в контейнер (почти всегда fragmented MP4, сокращённо fMP4), который плеер может декодировать независимо от других сегментов.

То, как origin обрабатывает эти два типа запросов, и определяет разделение мира на pre-packaged и JIT. Обе формы возвращают одни и те же байты для одного и того же URL. Разница заключается в том, когда эти байты были созданы.

Форма pre-packaged: всё – это файл

В pre-packaged origin каждый манифест и каждый сегмент – это реальный файл, хранящийся на физическом хранилище, записанный один раз при ингесте и больше никогда не пересчитываемый. Когда плеер запрашивает /movie-42/playlist_1080p.m3u8, origin считывает /movie-42/playlist_1080p.m3u8 с диска и передаёт. Когда плеер запрашивает /movie-42/segment_00042.m4s, origin считывает /movie-42/segment_00042.m4s с диска и передаёт. HTTP-слою безразлично, что представляет собой файл; для него это может быть даже JPEG.

Упаковка выполняется один раз – до того, как придёт первый зритель. Энкодер передаёт пакетайзеру (например, Shaka Packager, Bento4 или FFmpeg с нужными флагами – подробности см. в Упаковка видео: подробный разбор) готовую «лесенку» закодированных mezzanine-файлов – по одному файлу на каждую ступень. Пакетайзер разбивает каждый mezzanine на короткие сегменты, сохраняет каждый сегмент в отдельный файл, формирует HLS-плейлист со списком этих сегментов, создаёт DASH MPD с тем же списком, при необходимости генерирует версию в формате MPEG-TS рядом с fMP4 для поддержки устаревших плееров, при необходимости создаёт low-latency HLS-версию с partial-сегментами, при необходимости шифрует каждый сегмент по стандарту Common Encryption – и загружает всё это в хранилище origin-сервера. Любой зритель, который будет смотреть этот контент в течение следующих десяти лет, будет читать одни и те же файлы.

Pre-packaged – это исходная форма. Любой статический HTTP-сервер по сути является pre-packaged стриминговым origin’ом: вы кладёте .m3u8 и .m4s в дерево директорий, настраиваете на это CDN – и обслуживаете миллионы зрителей. NGINX – это pre-packaged origin. S3-бакет за CloudFront – тоже pre-packaged origin. Первое поколение HLS в 2009 году работало исключительно на pre-packaged origin’ах, потому что других вариантов просто не существовало.

Сильная сторона pre-обёртки очевидна. На запрос не тратится вычислительная мощность на упаковку; единственная задача origin-сервера – прочитать байты с диска и отправить их в сокет. Это самое дешёвое, самое кешируемое и самое рутинное, что может делать HTTP-сервер. CDN кэширует каждый URL при первом запросе любого зрителя – и любой следующий зритель в любой точке мира получает закэшированную копию. Сценарии сбоев просты: если сегмента нет, плеер получает 404 – и на этом всё.

Скрытая цена pre-упаковки

Скрытая цена pre-packaging – умножение storage. Современная стриминговая платформа не отдаёт одну версию тайтла. Она отдаёт много.

Возьмём один 90-минутный фильм. Этап энкодера выдаёт шесть разрешений: 240p, 360p, 480p, 720p, 1080p и 4K – это первый множитель, равный шести. Платформе нужны HLS для iOS, Safari и большинства смарт-ТВ, а также DASH для Android, Chrome и других смарт-ТВ – второй множитель, равный двум. Поддерживаются два языка аудио и один язык субтитров – третий множитель, небольшой, но не нулевой. Кроме того, платформа требует low-latency HLS-вариант для near-live-контента и MPEG-TS-формат для устаревших Apple TV из long tail. За это добавляется ещё ×1.4.

В худшем случае объём на диске для одного тайтла выглядит так:

6 ступеней × 2 формата упаковки × 2 аудио-дорожки × 1.4 legacy/LL-множитель
= ~33.6 копий одного и того же контента на диске на один тайтл.

90-минутный фильм в разрешении 1080p с битрейтом около 5 Мбит/с занимает примерно 3,4 ГБ при передаче по сети. Умножьте это на 33,6 – и один тайтл займёт около 114 ГБ на диске. Каталог из 1000 таких тайтлов потребует 114 ТБ хранилища. По цене AWS S3 Standard – около 0,023 доллара за гигабайт в месяц – это выйдет 2622 доллара в месяц, смотрит хоть кто-нибудь хоть один тайтл или нет. Добавьте второй регион для отказоустойчивости – и счёт удвоится.

Арифметика становится ещё хуже для long tail. Распределение Парето в видео-каталогах жёсткое: типично 80% просмотров приходится на 20% каталога, а у многих платформ половина каталога проигрывается меньше десяти раз в месяц. Вы платите полную стоимость хранения за ту половину каталога, которая не приносит заметной выручки. CDN не помогает, потому что данные хранятся на origin’е, и оплата за storage идёт независимо от того, кешируется ли контент на CDN.

Это как раз ту боль, которую и придумали лечить JIT.

Форма JIT: один мастер, много видов

Origin с упаковкой just-in-time хранит каталог на диске в канонической форме – обычно один fragmented-MP4 файл на каждую ступень – и синтезирует каждый протокол-специфичный вид по запросу. Объём mezzanine-раскладки на диске невелик: шесть fMP4-файлов на тайтл (по одному на ступень), по одному инициализационному сегменту на язык аудио, опциональные sidecar-файлы для субтитров и небольшие метаданные.

Когда плеер запрашивает /movie-42/index.m3u8, JIT origin читает sidx-боксы fMP4-файлов с диска, формирует актуальный HLS multi-variant playlist со списком доступных ступеней и отправляет его. При запросе variant-плейлиста /movie-42/playlist_1080p.m3u8 JIT origin анализирует sidx-индекс fMP4, создаёт свежий HLS media playlist со списком URL сегментов и отдаёт его. Когда плеер запрашивает /movie-42/seg_00042.m4s, JIT origin открывает fMP4-файл 1080p, находит байтовый диапазон, соответствующий 42-му сегменту, упаковывает эти данные в новый .m4s с корректными боксами styp и moof, соответствующими протоколу, указанному в URL, – и отправляет.

Ключевой момент: на диск ничего не было записано в ответ ни на один из этих запросов. Каталог на диске остался таким же маленьким, каким был до прихода первого зрителя. Если миллион зрителей посмотрят фильм 42, JIT origin обработает один и тот же сегмент миллион раз – если только его не закеширует CDN, и именно в этом «если» заключается суть того, как JIT делает доставку экономичной (см. «Почему нужен shield» ниже).

Рис. 1. Pre-packaged origin умножает объём хранилища на количество протоколов, аудиодорожек и legacy-вариантов. JIT origin хранит один канонический мастер на ступень и генерирует каждый пер-протокольный вариант по запросу.

Та же арифметика из предыдущего раздела, пересчитанная для JIT:

6 ступеней × 1 формат упаковки (fMP4 мастер) × ~1.1 audio-накладной расход
= ~6.6 копий одного и того же контента на диске на тайтл.

90-минутный 1080p-фильм ≈ 3.4 GB «по проводу».
Storage на тайтл ≈ 22.4 GB.
1 000 тайтлов ≈ 22.4 TB ≈ $515 в месяц (S3 Standard).

5-кратная экономия по строке storage. Для каталога из 10 000 тайтлов это более 20 000 долларов в месяц. Для каталога из 100 000 тайтлов (крупная стриминговая платформа) – несколько годовых зарплат инженеров.

Размен не бесплатен. CPU, который раньше выполнялся один раз при ингесте, теперь работает при каждом запросе – или, в идеале, при каждом промахе кэша. Следующие разделы показывают, как на практике настраивается этот компромисс.

Что реально работает при обращении

Чтобы понять стоимость CPU JIT origin’а, нужно знать, что он делает при каждом запросе. Его задача – упаковка, а не энкодинг, и это принципиальное различие. JIT origin не перекодирует видео: не пережимает, не меняет кодек, не запускает x264. Кадры на диске – те же самые, что передаются по сети. То, что делает origin, – это репакетирование: он читает закодированные сэмплы из мастер-файла fMP4 и переписывает контейнерные боксы, адаптируя их под протокол, запрошенный плеером.

Конкретно, при одном запросе HLS-сегмента JIT origin выполняет следующие действия:

  1. Парсит URL, чтобы определить, какой тайтл, ступень и номер сегмента запрашиваются.
  2. Открывает мастер-файл fMP4 для указанной ступени.
  3. Читает бокс sidx (индекс сегментов), чтобы найти байтовый диапазон, в котором расположен сегмент 42.
  4. Считывает эти байты с диска (или из кеша в оперативной памяти, если тайтл «горячий»).
  5. Формирует новую структуру: styp (тип сегмента), sidx, moof (заголовок фрагмента фильма) и mdat (медиаданные), соответствующую формату fMP4, ожидаемому плеером в рамках HLS.
  6. Если сегмент зашифрован – применяет схему CENC cbcs AES-CBC pattern к содержимому mdat с использованием правильного content key из системы управления ключами.
  7. Записывает собранные байты сегмента в тело HTTP-ответа.

На запрос манифеста JIT origin считывает из индекса sidx, из бокса moov – кодек-конфигурацию и длительность каждого фрагмента, а затем формирует новый плейлист или MPD. Также он применяет все манифест-фильтры, переданные в URL (min_video_bitrate, белый список языков аудио, белый список DRM-систем для устройства), и включает в результат только те ступени и дорожки, которые проходят фильтрацию.

Работа по упаковке значительно меньше, чем энкодинг – она обходится примерно в 20–200 раз дешевле в секунду на единицу медиа, – но всё же не бесплатна. Pre-packaged сегмент требует от origin'а одного read() и одного sendfile(). JIT-сегмент требует нескольких read(), парсинга бинарных боксов, выделения нового буфера для сегмента, опционального шифрования AES-CBC каждого макроблока и HTTP-обрамления ответа. На современном железе один инстанс Unified Origin обрабатывает приблизительно 500–2 000 запросов на JIT-сегменты в секунду на ядро – в зависимости от длины сегмента и наличия DRM в цепочке. Pre-packaged статический файловый сервер справляется с десятками тысяч запросов на ядро. Множитель настолько велик, что JIT-origin'ы проектируются в первую очередь как cache-friendly – каждый JIT-запрос, который вы отдаёте, это промах кэша, который вы не смогли предотвратить.

Зачем нужен shield

Самое важное архитектурное правило для JIT origin’а: поставьте перед ним origin shield. Без него JIT не будет работать экономически эффективно на больших масштабах. Origin shield – это выделенный одноуровневый кеш CDN, расположенный между остальными edge-узлами CDN и JIT origin’ом. Любой cache miss на любом edge-узле в мире сначала направляется в shield; только cache miss на shield доходит до origin’а. CloudFront, Akamai, Fastly и CloudFlare предлагают origin shield в своих решениях. (Подробнее – Origin shielding и многоуровневое кеширование.)

Почему shield критичен именно для JIT: типичный глобальный CDN имеет десятки–сотни edge-узлов, у каждого – свой кеш. Без shield первый зритель в Токио, первый в Франкфурте, первый в Сан-Паулу и первый в Мумбае независимо вызывают cache miss и обращаются к JIT origin’у – за одним и тем же сегментом. Origin упакует одни и те же байты четыре раза. С shield только первый cache miss в мире доходит до origin’а; все региональные edge-узлы наполняются из shield, а не из origin’а.

Опубликованные цифры впечатляют. AWS в докладах re:Invent по MediaPackage указывает на сокращение egress-трафика origin’а примерно на 95% при типичных OTT-нагрузках. Cloudflare и Akamai приводят схожие значения. Что это значит для JIT: с использованием shield’а нагрузка на origin снижается примерно в 20 раз по сравнению с прямым трафиком edge → origin. Без shield JIT обходится в 20 раз дороже с точки зрения вычислительных ресурсов, чем должен быть.

Shield’у нужно ещё несколько вещей, чтобы он корректно работал с JIT.

  • Ключ кэша должен включать query-параметры фильтра манифеста. Семейство aws.manifestfilter от AWS MediaPackage и параметр ?filter= у Unified Origin изменяют содержимое манифеста, который отдаёт origin, поэтому они должны входить в ключ кэша. В противном случае фильтрованный манифест зрителя A может попасть зрителю B, и в плеере окажутся неправильные ступени. Документация MediaPackage и Unified Origin содержит точный список параметров, обязательных для включения в ключ.
  • TTL кэша для сегментов и манифестов различаются. Сегменты после публикации не меняются – например, сегмент 5.8 тайтла VOD остаётся неизменным, – поэтому TTL в 24 часа и более на shield вполне обоснованы. Манифесты, особенно live-манифесты, обновляются каждые 2–6 секунд (в зависимости от длительности сегмента), поэтому TTL на манифесты на shield должен быть коротким: обычно 1–2 секунды для live и 60+ секунд для VOD.
  • Shield – это часть архитектуры, а не настройка. Команда, которая включает JIT без origin shield, видит рост затрат и отключает его, делает неверный вывод. JIT без shield – это ошибка. JIT с shield – один из самых экономичных способов доставки большого каталога контента.

Эталонные JIT-источники 2026 года

Три программных продукта занимают почти все продакшен-деплои JIT-оригинов в 2026 году.

Unified Origin от CodeShop (нидерландская Unified Streaming). Первый коммерческий JIT-origin, поставляется с 2010 года. Работает как модуль Apache (mod_smooth_streaming и расширения) внутри контейнера Apache HTTP Server. Принимает один ISMV / fMP4 / MP4 источник на каждую ступень, а также небольшой XML-дескриптор (.ism), в котором указано, какие аудио- и видеодорожки связаны между собой, – и упаковывает поток на лету в HLS (TS и fMP4), MPEG-DASH (включая профили DVB-DASH и HbbTV), Smooth Streaming и HDS. Поддерживает CMAF-выход со всеми тремя крупными DRM-системами (Widevine, PlayReady, FairPlay) в рамках схемы Common Encryption cbcs. Используется BBC Video Factory для каталога iPlayer, Sky и десятками европейских вещателей. Модель лицензирования – по ядру CPU, что делает её дорогой при сверхбольших нагрузках, но очень предсказуемой для платформ среднего масштаба.

AWS Elemental MediaPackage, особенно поколение v2 API. Полностью управляемый JIT-оригин внутри AWS. Принимает CMAF-совместимые потоки HLS или DASH от энкодера (обычно AWS Elemental MediaLive), хранит одну каноническую копию в S3 и упаковывает по запросу в HLS, LL-HLS, DASH и Microsoft Smooth Streaming с поддержкой DRM: FairPlay, Widevine и PlayReady. Поколение v2, представленное в 2023 году и ставшее стандартом для продакшена к 2026 году, добавляет origin endpoints с возможностью прикрепления до 25 манифестов на каждый, встроенный origin shield, фильтрацию манифестов через query-параметры aws.manifestfilter и тесную интеграцию с CloudFront. Ценообразование – по объёму ингестированных и упакованных данных (egress), отдельно от лицензии per-core у Unified. «v2»-ребрендинг в консоли AWS – причина, по которой в документации 2026 года вы увидите и MediaPackage, и MediaPackage v2; новые проекты используют v2 по умолчанию, если нет веских причин выбрать иначе.

Eyevinn Open Source Cloud Smoothly Origin и нижележащий Eyevinn Channel Engine, а также меньший open-source проект Norsk (id3as) и длинный хвост собственных in-house origin’ов на базе Shaka Packager в library-режиме с собственной HTTP-обёрткой. Это решение подходит для платформ, которым требуется полный контроль над логикой упаковки – обычно из-за нестандартных требований к DRM, использования экзотических кодеков (AV1, VVC) или стремления избежать как лицензии Unified по ядрам, так и привязки к AWS. Бессерверный подход Eyevinn, описанный в их постах об AWS Fargate с 2022 года, – это каноничная архитектура «JIT origin на скромном бюджете» для средних платформ.

Краткое сравнение.

OriginТипМодель лицензииManifest filteringНужен shieldТипичная нагрузка
Unified OriginКоммерческийPer-CPU-coreДа (?filter=)Да (внешний)Вещатели, крупные OTT
AWS MediaPackage v2ManagedIngested + egress GBДа (aws.manifestfilter)ВстроенныйOTT в AWS-стеке, live-спорт
Eyevinn Smoothly + Shaka libOSSНет (self-host)КастомныйДа (внешний)Средние OTT, dev-команды
NorskКоммерческий / OSS-гибридPer-channelДаДа (внешний)Live-вещатели, e-learning

Введение в инструменты упаковки, используемые для любого из этих источников, – в статье Упаковка видео: подробный разбор. Форматы манифестов, которые они генерируют, – в HLS: подробный разбор и MPEG-DASH: подробный разбор. Схема шифрования, применяемая ими, – в Common Encryption (CENC).

Размен storage против compute, в цифрах

Выбор между pre-packaged и JIT сводится к одному вопросу: останется ли сэкономленный на хранилище доллар у вас в кармане или окажется в счёте за вычисления на origin? Приведённая ниже арифметика основана на среднем каталоге и прайс-листе AWS 2026 года без учёта скидок за объёмные закупки.

Каталог из 1000 тайтлов, средняя продолжительность – 90 минут, 6 ступеней в иерархии, две аудиодорожки, поддержка HLS и DASH.

Pre-packaged storage = ~33.6 копий × 3.4 GB ≈ 114 GB на тайтл × 1 000 = 114 TB.
Storage в месяц (S3 Standard $0.023/GB-месяц) = $2 622.

JIT storage = ~6.6 копий × 3.4 GB ≈ 22.4 GB на тайтл × 1 000 = 22.4 TB.
Storage в месяц (S3 Standard $0.023/GB-месяц) = $515.

Экономия storage = $2 107 в месяц, или ~$25 000 в год.

Сторона CPU origin’а зависит от того, сколько viewer-часов в месяц доходит до origin’а. Возьмём скромный масштаб: 1 000 000 viewer-часов в месяц, средний битрейт 4 Mbps, средняя длина сегмента – 4 секунды. Это примерно 900 сегментных запросов на viewer-час, то есть 900 миллионов сегментных запросов в месяц – но почти ни один из них не доходит до JIT origin’а, если архитектура правильная.

Всего сегментных запросов в месяц       = 900 000 000
Cache hit rate на edge'ах CDN           = ~97% (типичный OTT-микс)
Miss'ов до origin shield                = ~27 000 000
Shield hit rate                         = ~95%
Miss'ов до JIT origin'а                 = ~1 350 000 в месяц

Запросов в секунду к JIT origin'у       ≈ 0.5 в среднем, 5–10 в пик
Нужно ядер JIT (1k req/s/core)          = 1 в среднем, 2 в пике

Compute origin'а (1 c6i.large EC2, $0.085/час)
                                        = $62 в месяц

Цифры иллюстративные – фактический cache hit rate, фактическое покрытие shield и профиль трафика сдвинуты на ±2× по каждой строке, но важна форма. Сэкономлено на хранилище: $2 107. Добавлено вычислительных ресурсов: $62. JIT выигрывает примерно в 30 раз на среднем каталоге с типичным OTT-кеш-профилем.

Точка безубыточности смещается по двум параметрам. Первый – размер каталога: каталог из 100 тайтлов экономит $200 в месяц на хранении – недостаточно, чтобы оправдать операционную сложность, поэтому небольшие каталоги остаются pre-packaged. Второй – cache hit rate: каталог с тяжёлым long tail и плохой локальностью кэша (каждый тайтл смотрят раз-два в месяц) снижает shield hit rate до 60–70%, увеличивая нагрузку на compute origin в 5–10 раз. JIT всё равно остаётся выгодным, но запас эффективности сокращается. Чистый long-tail архив – миллионы тайтлов, десятки часов просмотра на тайтл в месяц, мало хитов – это единственная нагрузка, где JIT окупается исключительно за счёт экономии на хранении, а экономика кэша остаётся более-менее нейтральной.

Подробная модель по пер-стеку – в кросс-калькуляторе CDN cost economics: 95-й перцентиль, commit, overage; полная unit-экономика стриминга – в Экономика стриминга: рабочая модель.

Cache-friendliness – не опция

Репутация JIT origin’а растёт или падает по одной ключевой метрике: какую долю сегментных запросов обслуживает CDN-кеш. Всё остальное – экономия на хранилище, операционная гибкость, возможность внедрить новый протокол в следующем квартале – строится на допущении, что кеш-слой обрабатывает 95% и более трафика. Когда кеш-слой не достигает этой планки, JIT кажется дорогим, команда винит origin – и хорошая архитектура списывается со счетов.

Три вещи снижают cache-friendly у JIT-оригинов, и все они встречаются довольно часто.

Шум в query string. Если два плеера запрашивают один и тот же URL сегмента с разными ?session_id=, а CDN включает query string в ключ кэша, один и тот же контент будет дважды запрошен с origin’а, хотя он уже лежит на диске. Решение: на edge-уровне удалять query string из URL сегментов или разрешить только те параметры, которые действительно меняют ответ (например, версия DRM-ключа, фильтр манифеста), а session- и аналитические токены – явно исключать. Функция Cache Policy в AWS CloudFront создана именно для этого; аналогичные правила Cache Key в Akamai решают ту же задачу.

Фрагментация манифеста. Если JIT-источник выдаёт слегка различающиеся манифесты для каждого user-agent – например, отдельный для Safari, отдельный для Chrome и отдельный для Android TV – то кеширование манифестов фрагментируется по user-agent, и каждый манифест, привязанный к конкретному UA, требует своих собственных сегментов. Решение: сделать манифест независимым от user-agent, вынести device-специфичную логику в плеер (он сам знает, что может декодировать), и пусть источник выдаёт один и тот же манифест на весь контент.

Микроскопические TTL. Команда, которая «на всякий случай» устанавливает TTL манифеста VOD в одну секунду, теряет 99% попаданий на уровне манифеста. VOD-манифесты не меняются – их нужно кешировать столько, сколько каталог хранит контент, то есть часы или дни. Короткий TTL нужен только для live-манифестов, и он должен соответствовать длине сегмента, а не быть произвольно установленным в одну секунду.

Кэш-дружественность аудита для JIT-деплоя короткая. (1) На репрезентативном URL-сегменте – даёт ли CDN кэш HIT при втором запросе из другого региона? (2) Достигает ли hit rate origin shield в steady-state значения выше 95%? (3) Не происходит ли повторная обработка одних и тех же URL-сегментов из-за фрагментации query string? Три проверки. Они отличают JIT origin, который окупается, от того, который нет.

Типичная ошибка: воспринимать JIT как готовую замену

Самый дорогой сценарий сбоя у команды, переходящей на JIT, – воспринимать его как простую замену статического origin’а, заменить NGINX на Unified Origin через тот же CDN и ожидать, что расходы снизятся.

Не упадёт. Без origin shield, без настроенного cache key и без UA-agnostic манифестов JIT приведёт к сопоставимым или даже большим ежемесячным расходам, чем заменённый им pre-packaged origin, поскольку каждый cache miss теперь нагружает CPU origin’а, а не просто потребляет трафик. Команда делает вывод: «JIT нам не подходит», откатывается – и упускает возможность построить правильную архитектуру.

JIT – это не один продукт. Это форма: JIT origin за настроенным shield, за настроенным CDN, за UA-agnostic манифестами – и именно эта форма экономит деньги. Принять origin без принятия формы – ошибка.

Лечится чек-листом, который нужно пройти до выкатывания миграции в продакшен. Origin shield включён? Cache key исключает session-токены? Сегменты кешируются на edge как минимум 24 часа? Манифесты кешируются на edge на duration (live) или на часы (VOD)? Параметры manifest filter включены в cache key? Каждая строка в чек-листе важна: пропуск любой из них – это и есть анекдот «JIT дороже».

Когда pre-packaged всё ещё выигрывает

Есть нагрузки, для которых pre-packaging – правильный выбор в 2026 году.

Маленький статический каталог – корпоративная обучающая библиотека из 50 тайтлов, документальная коллекция, фиксированный набор записанных событий. Экономия на хранилище при использовании JIT минимальна – не более $100 в месяц, операционная простота файлового origin’а высока, а инженерные затраты на настройку и запуск JIT-оригина превышают эту экономию.

Pass-through low-latency live – это один live-канал, где энкодер напрямую записывает HLS и DASH в S3-бакет, который выступает в роли origin’а, а время жизни сегмента на edge измеряется в секундах. JIT добавляет буферизующий слой, увеличивая end-to-end-латентность; для спортивных трансляций с задержкой менее 2 секунд этот запас латентности становится критичным. (Арифметика латентности – в LL-HLS: подробный разбор.)

Экстремально cache-горячий каталог – вирусный одиночный ассет, масштабное событие запуска, – где 99,99% трафика приходится на небольшое количество закешированных объектов. Упаковка заранее проще, а стоимость хранения пренебрежимо мала, поскольку каталог занимает мало места.

Паттерн: pre-packaging выигрывает, когда каталог мал, когда важна латентность или когда коэффициент попаданий в кэш настолько высок, что архитектура почти не играет роли. JIT выигрывает во всех остальных случаях.

Дерево решений: какая форма origin для какой нагрузки

Практический поток.

Рис. 2. Выбирайте pre-packaged, если каталог небольшой, бюджет латентности жёсткий или набор протоколов фиксирован. Выбирайте JIT – всегда за origin shield – если каталог превышает пару сотен тайтлов или ожидается рост разнообразия протоколов.

Пороги в дереве – приблизительные: 500 тайтлов на разделение по размеру каталога, 1 секунда glass-to-glass на разделение по латентности, три протокола на разделение по разнообразию. Это не чёткие границы – а диапазоны. Каталог из 400 тайтлов с высоким разнообразием протоколов – это кейс для JIT. Каталог из 600 тайтлов, который отгружает только HLS в iOS-приложение, – всё ещё кейс для pre-packaged. Используйте дерево как отправную точку и проводите стресс-тестирование на основе реальной модели стоимости.

Стратегическая ценность: новый протокол во вторник

Финансовый аргумент за JIT – арифметика storage против CPU выше – это тот аргумент, который продакт-менеджеры понимают в первую очередь, и его одного достаточно. Есть второй, плохо укладывающийся в Excel, аргумент, который инженеры ценят не меньше: JIT позволяет внедрить новый протокол без перепаковки каталога.

Подумайте, что происходит, когда Apple выпускает новый вариант HLS, когда у CMAF появляется новая разновидность, когда регулятор требует ротации DRM на тысячу тайтлов, когда новое семейство устройств требует подкрутки манифеста. В мире pre-packaged каждое из этих событий – это работа по перепаковке: прочитать каждый mezzanine с хранилища, прогнать новые настройки упаковки, записать каждый сегмент обратно, инвалидировать CDN. Для 10 000 тайтлов это дни вычислительных ресурсов и логистический клубок.

В мире JIT то же самое изменение – это и есть деплой. Обновили логику упаковки в origin’е – следующий запрос манифеста возвращает новую форму. Файлы Mezzanine на диске не трогались. CDN наполняется по мере прихода зрителей. Полный простой длится столько, сколько займёт раскатка фронта origin’ов: минуты, а не дни.

Причина, по которой каждая крупная OTT-платформа перешла на JIT между 2018 и 2024 годами, – отчасти экономия на хранилище, отчасти вот что: в мире, где ландшафт стриминговых протоколов меняется быстрее, чем каталоги, сам каталог должен храниться в формате, способном пережить смену протоколов. JIT обеспечивает именно такой формат.

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

Фора Софт строит видео-байплайны с 2005 года – включая OTT- и Internet TV-платформы, e-learning-каталоги, архивы видеонаблюдения и записи телемедицины. В этих проектах используются одни и те же архитектурные решения: насколько велик каталог, сколько протоколов и DRM-систем он должен поддерживать, какой бюджет задержки можно выделить на edge-уровне и где экономия на хранении перевешивает затраты на вычисления на origin-сервере.

С точки зрения OTT мы разрабатывали как pre-packaged origin’ы для чётко очерченных архивов событий, так и JIT-origin’ы (с origin shield, ключами кэширования, учитывающими фильтры манифестов, и настроенными CDN-политиками) для каталогов, растущих до тысяч записей. В e-learning JIT-архитектура окупается, когда библиотека курсов превышает пару сотен уроков.

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

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

  • Pre-packaging записывает на диск каждый вариант под протокол один раз; JIT хранит один мастер-файл и генерирует нужные версии по запросу.
  • Экономия места при использовании JIT обычно составляет 3–5×, в то время как нагрузка на вычисления на origin растёт в 5–20 раз.
  • Для JIT обязательно нужен origin shield – без него вычислительная нагрузка выглядит значительно хуже, чем должна.
  • Параметры фильтра манифеста должны входить в ключ кэширования; токены сессии – нет.
  • Pre-packaging всё ещё выигрывает на небольших каталогах, при задержке live-трансляции менее 2 секунд и при экстремально высокой популярности отдельных ассетов.
  • Стратегическая ценность JIT – не только в экономии: внедрение нового протокола или ротация DRM требует лишь деплоя, а не перепаковки.

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

CTA

  • Поговорить со стриминговым инженером – забронируйте 30-минутную встречу для архитектурного ревью текущего стека упаковки.
  • Посмотреть наши кейсы – OTT, e-learning и broadcast-деплои, где JIT origin или статический origin оказались правильным решением.
  • Скачать decision sheet «JIT против pre-packaged» – одностраничный справочник: пороги каталога, арифметика хранения, чек-лист cache-friendliness и вендоры origin’ов 2026 года. Скачать PDF

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

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