Содержание статьи +
- TL;DR
- Зачем это нужно
- Что такое GOP и зачем он существует
- Три типа кадров и как они складываются в GOP
- Порядок кадров: чем display order отличается от decode order
- Иерархические B-кадры: узор B-пирамиды
- IDR, CRA и разница между I-кадром и keyframe
- Open vs Closed GOP
- Длина GOP: самая тонко настраиваемая настройка стриминга
- Частая ошибка: невыровненные GOP по лестнице битрейтов
- Codec-специфические отличия, которые стоит знать
- Где здесь Фора Софт
- Ключевые выводы
- Что читать дальше
TL;DR
GOP (Group of Pictures, «группа изображений») – это отрезок видеопотока, который начинается с keyframe и заканчивается прямо перед следующим keyframe. Это наименьший кусок видео, который можно декодировать независимо. Внутри GOP кодер чередует три типа кадров: I-кадры (полные картинки), P-кадры (предсказанные из прошлых кадров) и B-кадры (предсказанные из прошлых и будущих), располагая их так, чтобы после небольшой перестановки декодер мог их воспроизвести. Две главные структурные настройки – длина GOP (расстояние между keyframe) и его «открытость» (могут ли B-кадры внутри GOP ссылаться за пределы), и любая ошибка в них ломает seek, переключение битрейтов в ABR или то и другое одновременно. Эта статья даёт рабочую ментальную модель, которую в 2026 году используют инженеры HLS, DASH, WebRTC и вещания, цифры за каждым решением и одностраничный чит-лист.
Зачем это нужно
Длина GOP – единственная настройка, которая одновременно определяет размер ваших видеофайлов, скорость перемотки у зрителя, чистоту переключения битрейтов в HLS-плеере и латентность лайв-стрима от камеры до экрана. Слишком длинный GOP – и seek-to-position тормозит; слишком короткий – и битрейт растёт на 20–40% при том же визуальном качестве. Open vs closed GOP – следующее решение, и оно проводит чёткую границу между архивными мастерами и стримингом для пользователя. Основатель, прочитавший эту статью, сможет на встрече по инфраструктуре спорить о правильных цифрах; операционный руководитель – за пять секунд найти расхождение в энкодерной лестнице вендора.
Что такое GOP и зачем он существует
Group of Pictures, почти всегда сокращаемое до GOP, – это последовательность кадров, начинающаяся с keyframe и заканчивающаяся прямо перед следующим keyframe. Keyframe – это точка входа: кадр, который декодер может восстановить, не видя ничего до него. Все остальные кадры GOP нуждаются в keyframe (или в цепочке кадров, ведущей обратно к нему).
Это похоже на главы в книге. Вы можете открыть книгу в начале любой главы и читать вперёд, не читая предыдущую, но не можете подобрать предложение из середины третьей главы и понять его без контекста. Keyframe – это первое предложение главы; следующие кадры – предложения, которые на нём строятся; следующий keyframe – первое предложение следующей главы.
Эта конструкция «глав и страниц» существует из-за математики сжатия, разобранной в предыдущих статьях о внутрикадровом кодировании и межкадровом кодировании. Inter-frame coding – описание кадра как небольшой коррекции более раннего кадра – примерно в 30 раз эффективнее, чем intra-кодирование того же содержимого. Но за эту эффективность приходится платить: P-кадр бесполезен сам по себе. Чтобы восстановить его, нужно проиграть все кадры от ближайшего keyframe.
GOP-структура – это компромисс между этими двумя фактами. Длинные GOP дают кодеру много inter-кадров и уменьшают битрейт. Короткие GOP дают декодеру много точек входа и делают seek, переключение каналов и адаптивный стриминг быстрым. Любой поток, который вы когда-либо смотрели, выбрал точку на этой шкале.
Три типа кадров и как они складываются в GOP
Полные названия – Intra-coded, Predicted, Bi-predictive – были закреплены в MPEG-1 в 1993 году и с тех пор не менялись. Компрессионное поведение тоже почти не сдвинулось: современные кодеки добавили новые приёмы к каждому типу, но буквы остались те же.
I-кадр – это полная картинка. Он сжимается только информацией, содержащейся в нём самом, – той же логикой, что и JPEG. I-кадр можно декодировать сам по себе. Каждый GOP начинается с него. Типичный I-кадр 1080p в H.264 стоит 80–250 килобит.
P-кадр – это кадр, который копирует большую часть содержимого из кадра, идущего раньше в порядке отображения, а затем правит отличия. Буква P означает Predicted. Кодер описывает каждый блок motion vector – указателем на похожий участок в прошлом кадре – плюс маленьким residual. P-кадр в том же контенте обычно стоит 30–60% от I-кадра.
B-кадр – это кадр, который может копировать содержимое и из прошлого, и из будущего кадра и усреднять их. Буква B означает Bi-predictive. B-кадры самые сжимаемые из трёх: обычно 15–30% от I-кадра. Они же самые дорогие по латентности: кодер не может создать B-кадр, пока не увидит будущий референс, а декодер не может его отрендерить, пока не декодирует этот будущий кадр.
Рабочий GOP сплетает три типа в повторяющийся узор. Классический узор – IBBPBBPBBPBB…: один keyframe, потом P-кадр каждые три позиции с двумя B-кадрами между каждым P. Иерархические B-pyramid-структуры, разобранные ниже, заменяют этот простой шаблон чем-то более умным, но принцип тот же: I-кадр стартует GOP, P-кадры скачут вперёд, B-кадры заполняют промежутки.
Конкретный пример закрепляет цифры. Возьмём 2-секундный сегмент 1080p24 – 48 кадров на 24 fps – закодированный современным пресетом x265 с closed GOP длиной 48 и узором IBBPBBPBBPBB…. В этом сегменте 1 I-кадр, 15 P-кадров и 32 B-кадра.
I-кадр: 1 × 200 кбит = 200 кбит
P-кадры: 15 × 100 кбит = 1500 кбит
B-кадры: 32 × 50 кбит = 1600 кбит
итого за 2-секундный сегмент: 3300 кбит
средний битрейт: 1650 кбит/с ≈ 1.65 Мбит/сА теперь проиграйте тот же сегмент с выключёнными B-кадрами – так работает лайв-кодер с низкой латентностью. Каждая позиция B становится P-кадром.
I-кадр: 1 × 200 кбит = 200 кбит
P-кадры: 47 × 100 кбит = 4700 кбит
итого за 2-секундный сегмент: 4900 кбит
средний битрейт: 2450 кбит/с ≈ 2.45 Мбит/сОтключение B-кадров стоит +48% битрейта при том же визуальном качестве. Это постоянная цена low-latency лайв-стриминга и главная причина, по которой WebRTC-пайплайну нужно больше бит, чем HLS при том же разрешении.
Порядок кадров: чем display order отличается от decode order
Кадры B-узорного GOP не лежат на диске в том порядке, в котором вы их смотрите. Они лежат в порядке, нужном декодеру для обработки, а это не одно и то же. Это разделение – display order (порядок отображения) vs decode order (порядок декодирования) – источник почти всех начальных недоразумений вокруг B-кадров.
Возьмём GOP, начинающийся I B B P …. В display order – порядке, в котором кадры идут на экран, – последовательность I(0) B(1) B(2) P(3). Но второй B-кадр на позиции 2 нуждается в P-кадре на позиции 3 как в одном из референсов. Декодер не может декодировать B(2) раньше P(3), поэтому кодер переставляет. В decode order те же четыре кадра хранятся как I(0) P(3) B(1) B(2).
Декодер читает кадры в decode order, складывает их в небольшой reorder-буфер и выпускает в display order в нужный момент. Reorder-буфер добавляет один кадр латентности на каждый уровень переупорядочивания – поэтому поток с N B-кадрами между P-кадрами добавляет до N кадров буферизации в декодере.
Эта перестановка не опциональна для B-кадров – она структурна. Два практических следствия для продуктовых команд: во-первых, каждый B-кадр добавляет один кадр сквозной латентности – это около 42 мс на 24 fps и 17 мс на 60 fps; во-вторых, плееры, transmuxer-ы и packager-ы обязаны уважать picture-timing-метаданные в битстриме, чтобы показывать кадры в правильное wall-clock-время. Частый баг: быстрый FFmpeg-пайплайн теряет picture-order-данные, плеер рисует B-кадры в момент decode, и получается видимый jitter.
Иерархические B-кадры: узор B-пирамиды
GOP с одним B-кадром между каждой парой P-кадров – это пол всего design space. Современные кодеки идут на несколько уровней глубже. Иерархическая B-структура, часто называемая B-pyramid, позволяет B-кадрам ссылаться на другие B-кадры, строя несколько временных слоёв внутри одного GOP.
Представьте 16-кадровый GOP. Плоская структура втыкает B-кадры между P-кадрами одним уровнем: I B B B B B B B B B B B B B B P. Pyramid-структура организует те же 16 кадров в дерево. Кадр 8 – это B-кадр на вершине пирамиды, ссылающийся на I-кадр и следующий P-кадр. Кадры 4 и 12 – B-кадры среднего уровня, ссылающиеся на кадр 0, кадр 8 и кадр 16. Кадры 2, 6, 10, 14 – B-кадры нижнего уровня, и так далее. Каждый уровень использует референсы уровнем выше, поэтому глубина зависимостей логарифмическая, а не линейная.
Выигрыш по сжатию заметный: иерархическое B-pyramid-кодирование даёт HEVC и AV1 примерно на 10–15% лучше сжатие на типовом контенте, чем плоская B-структура той же длины. Цена – декодерная буферизация: самый глубокий B-кадр зависит от референсов, отстоящих на GOP_length/2 кадров. Для VOD это не проблема; для лайв-стриминга – стоп-сигнал, поэтому LL-HLS-потоки держат пирамиду неглубокой или отключают её полностью.
Чтобы полноценно использовать B-pyramid, длину GOP задают степенью двойки: 16, 32 или 64 кадра. И HEVC, и AV1 настроены под это. AV1 по умолчанию использует 4-кадровый mini-GOP с тремя временными слоями; его система референсов ALTREF и GOLDEN – это, по сути, пирамида, построенная из неотображаемых отфильтрованных кадров, что мы затронем в секции про AV1 ниже.
IDR, CRA и разница между I-кадром и keyframe
Частый источник багов – предположение, что «I-кадр» и «keyframe» – одно и то же. Это не так. Каждый keyframe – это I-кадр, но не каждый I-кадр – keyframe.
IDR-кадр – Instantaneous Decoder Refresh – это I-кадр, который одновременно чистит reference buffer декодера. После IDR ни один последующий кадр не может ссылаться на что-либо до него. IDR – настоящие точки случайного доступа: плеер может вклиниться в поток на любом IDR и декодировать вперёд корректно. В HLS, DASH и CMAF каждый видеосегмент начинается с IDR – это требование спецификации.
Не-IDR I-кадр – это полностью intra-coded картинка, но последующие кадры всё ещё могут ссылаться на кадры до него. Scene-cut детектор, вставляющий I-кадр для сжатия в начале нового кадра, не вставляет автоматически IDR – это зависит от настроек кодера.
HEVC добавляет третью категорию: Clean Random Access (CRA). CRA выглядит как IDR – leading-кадры можно декодировать, если стартовать с него, – но его trailing leading pictures могут ссылаться на кадры до CRA, что делает границу чище для stream-splicing. AV1 идёт другим путём: его display order равен coding order, поэтому концепция GOP ближе к VP9-овской «golden frame group», а различие keyframe vs I-frame заменено на битстрим-сигналы KEY_FRAME и INTRA_ONLY_FRAME.
Практические следствия для HLS- и DASH-пайплайнов: во-первых, каждая граница сегмента должна быть IDR, а не обычным I-кадром, иначе плеер не сможет в этот сегмент seek-нуть; во-вторых, форсируйте фиксированную длину GOP, чтобы кодер не вставлял scene-cut keyframe в произвольных местах разных рендишенов вашей лестницы; в-третьих, никогда не путайте счётчик keyframe плеера (считает IDR) со счётчиком I-кадров кодера (считает оба типа).
Open vs Closed GOP
GOP закрыт, если ни один кадр внутри него не ссылается на кадры вне его. Граница между двумя closed GOP – это жёсткий разрез: можно остановить декодирование в конце одного GOP, выбросить все референсы и стартовать с нуля на следующем IDR без потерь.
GOP открыт, если B-кадру в начале GOP разрешено ссылаться на последний P-кадр предыдущего GOP. Логика чисто компрессионная: тот P-кадр часто намного лучший референс для первых одного-двух B-кадров нового GOP, чем собственный I-кадр нового GOP. Разрешение кросс-границной ссылки экономит биты.
Open GOP обычно экономит 1–3% битрейта при том же VMAF. Это правильный default для архивных мастеров и единичных VOD-файлов, в середину которых вы никогда не seek-аете.
Closed GOP обязателен для любого современного adaptive-bitrate workflow. И HLS authoring spec от Apple, и DASH-IF interoperability guidelines требуют closed GOP, выровненных по всем рендишенам лестницы. Причина структурная: когда плеер переключается с 720p на 1080p, он делает это на границе сегмента. Если 1080p-сегмент начинается с open GOP, чьи первые B-кадры хотят ссылаться на P-кадр, которого плеер не видел, плеер на пару кадров декодирует мусор и показывает видимый артефакт.
Правило для продакшена однозначное: closed GOP, фиксированная длина, выравнивание по всем рендишенам. Экономия 1–3% от open GOP – для mezzanine и архива, не для доставки.
Длина GOP: самая тонко настраиваемая настройка стриминга
Длина GOP – расстояние от одного keyframe до следующего, измеряемое в кадрах или секундах, – настройка, которую operations-инженер трогает чаще всего. Правильное значение зависит от того, что вы оптимизируете.
В VOD-стриминге выигрывает длинный GOP. Каждый I-кадр дорогой; чем шире вы разносите их, тем ниже средний бит-на-пиксель. Потолок задают ограничения seek, переключения и выравнивания сегментов. Типичный мастер YouTube или Netflix использует GOP в 2 секунды; 24 fps × 2 с = 48 кадров.
В лайв-стриминге длина GOP – нижняя граница латентности. Плеер не может начать воспроизведение, пока не получил полный сегмент, а сегмент не может закончиться раньше следующего keyframe. GOP 2 с означает минимум 2 с сегментной латентности поверх сети и буфера. LL-HLS-потоки с GOP 1 с и CMAF-парт 200–400 мс достигают 3 с glass-to-glass; full-segment HLS с GOP 6 с в проде живёт на 15–25 с.
В WebRTC длина GOP определяется устойчивостью сети, а не seek-ом. WebRTC использует RTP-feedback (PLI, FIR, NACK), чтобы запрашивать keyframe по требованию, когда пир теряет синхронизацию, поэтому кодер обычно крутится на очень длинном GOP – иногда один keyframe в минуту – и вставляет keyframe только по запросу. Результат – экономия бит ценой нулевого random-access, что нормально, потому что WebRTC-потоки не сегментируются для adaptive-доставки.
В вещании длина GOP задаётся стандартом: ATSC требует IDR каждые 0.5–1 с; DVB целится в 0.5–2 с; SCTE-35 маркеры должны попадать на границы IDR для вставки рекламы.
Эмпирически частые настройки в продакшене на 2026 год:
| Workflow | Длина GOP | Заметки |
|---|---|---|
| HLS / DASH VOD, 24 fps | 48 кадров (2 с) | Closed, B-pyramid включён |
| HLS / DASH VOD, 30 fps | 60 кадров (2 с) | Closed, B-pyramid включён |
| HLS / DASH VOD, 60 fps | 120 кадров (2 с) | Closed, B-pyramid включён |
| LL-HLS / LL-DASH live | 24–60 кадров (1 с) | Closed, B-pyramid выключен или 2 слоя |
| WebRTC-конференция | 30–1800 кадров (1–60 с) | По feedback, B-кадры off |
| Видеонаблюдение / NVR | 60–600 кадров (2–20 с) | Часто open, B-кадры off, очень длинный при статичной сцене |
| Broadcast-ингест | 12–30 кадров | Короткий для splicing; B-кадры опционально |
| Архивный мастер (ProRes / DNxHR) | 1 кадр (all-intra) | Нет GOP – каждый кадр keyframe |
Практическое правило для стриминга: выбирайте длину GOP так, чтобы она ровно делилась на длину сегмента, число audio sample-ов на сегмент и frame rate. Несовпадение заставляет кодер вставлять лишние IDR на границах сегментов и тихо повышает битрейт.
Частая ошибка: невыровненные GOP по лестнице битрейтов
Самая дорогая ошибка в HLS и DASH – невыровненные GOP по рендишенам. Если 720p-стрим и 1080p-стрим вставляют keyframe в чуть разное время – например потому, что у каждого свой scene-cut детектор, – сегменты не совпадают. Плеер всё ещё может играть любой из стримов отдельно, но в момент переключения между ними на границе сегмента он перепрыгивает или повторяет кадр, и ABR-switching становится заметно дёрганым.
Лечение – форсировать фиксированный одинаковый GOP по всем рендишенам. В x264 это --keyint 48 --min-keyint 48 --no-scenecut. В x265 – --keyint 48 --min-keyint 48 --no-scenecut --no-open-gop. В FFmpeg с libx264 эквивалент – -g 48 -keyint_min 48 -sc_threshold 0. Те же числа на каждом рендишене.
Вторая, родственная ошибка – смешение open и closed GOP по рендишенам, обычно потому что один рендишен пересжали с дефолтами, пока остальные использовали явные ABR-параметры. Аудитируйте лестницу периодически: HLS-чит-лист в PDF ниже содержит точные FFmpeg-флаги для самых частых workflow.
Третья ошибка, которую стоит назвать: задание длины GOP в секундах без проверки, что frame rate постоянный. VFR-источники могут давать GOP сильно разного байтового веса, даже если time-domain-расстояние «постоянное». Сначала CFR-нуть исходник, потом задавать GOP.
Codec-специфические отличия, которые стоит знать
Концептуальный GOP одинаков во всех современных кодеках, но детали реализации различаются.
H.264 / AVC. До 16 reference-кадров. B-pyramid по умолчанию через b-pyramid normal в x264. IDR и не-IDR I-кадры чётко разделены. SPS/PPS NAL-юниты в начале каждого IDR позволяют декодерам стартовать mid-stream.
H.265 / HEVC. Та же модель, что и H.264, плюс CRA-кадры, разрешающие leading-кадры, декодируемые независимо, и trailing leading pictures, ссылающиеся через CRA. GOP-структуры HEVC обычно имеют 4 или 8 уровней иерархических B; low-delay-режим SVT-HEVC по умолчанию использует 4-кадровый mini-GOP.
VP9. Концепция «golden frame group» – долгопериодический референс, отличный от непосредственного предыдущего кадра, – ведёт себя как мягкий GOP без строгой random-access-семантики.
AV1. Display order равен coding order; GOP в AV1 формируется управлением reference-кадрами, а не reorder-буфером. Два типа неотображаемых референсов – ALTREF (вперёд, temporally filtered) и ALTREF2 (вперёд, более короткий горизонт) – вместе с GOLDEN, LAST, LAST2, LAST3 и BWDREF дают кодеру набор из семи референсов. High-delay-режим libaom-av1 крутит golden-frame group из 16 кадров со встроенной трёхслойной пирамидой.
H.266 / VVC. Наследует семейство IDR/CRA/BLA из HEVC плюс новый тип – Gradual Decoding Refresh (GDR), – позволяющий декодеру восстанавливаться постепенно после ошибки или входа в поток за заданное число кадров, не дожидаясь следующего IDR. GDR важен для low-latency спутника и contribution-линков.
Где здесь Фора Софт
Настройка GOP – одна из тех вещей, которые трогаются на каждом нашем проекте. В наших WebRTC- и видеоконференцпроектах мы крутим feedback-driven keyframe и очень длинные GOP, чтобы минимизировать bandwidth на unicast peer-соединениях. В лестницах OTT и интернет-ТВ мы форсируем closed-фиксированный GOP, выровненный по всем разрешениям, потому что misalignment – тихий убийца качества ABR. В проектах видеонаблюдения мы эксплуатируем длинные статичные участки, поднимая GOP до 20 с и больше, и вставляем event-driven IDR из metadata детектора движения. Наши e-learning и telemedicine-проекты живут посередине: достаточно random-access-точек для мгновенной перемотки, достаточная длина GOP для экономного CDN. Чит-лист ниже суммирует производственные пресеты, которые мы поставляем чаще всего.
Ключевые выводы
- GOP – это последовательность кадров между двумя keyframe; наименьший независимо декодируемый кусок видео.
- I-кадры – полные картинки; P-кадры предсказывают из прошлого; B-кадры – из прошлого и будущего и сжимаются лучше всего.
- Display order и decode order различаются; B-кадры заставляют кодер переставлять и добавляют латентность.
- Иерархическое B-pyramid-кодирование даёт +10–15% сжатия на длинных GOP, позволяя B-кадрам ссылаться на другие B-кадры.
- Только IDR-кадры – настоящие точки random-access; обычного I-кадра недостаточно для границы HLS-сегмента.
- Closed GOP обязателен для ABR-стриминга; open GOP экономит 1–3% битрейта только для архивных мастеров.
- Правило продакшена: фиксированный closed GOP, длина выровнена по сегменту и frame rate, одинаковая на всех рендишенах.