GOP와 Segment 경계 — Media Push 송출 설정 검증
Encoder GOP와 streaming platform의 keyframe 요구사항, HLS segment 경계가 서로 영향을 주는 지점을 정리합니다. 플랫폼별 권장값을 보편 규칙으로 일반화하지 않고, frame rate와 keyframe interval 단위를 확인한 뒤 실제 manifest와 frame timestamp로 결과를 검증하는 방법을 다룹니다.
목차(40개 항목)
- 0. 핵심 명제 — 패키징 경계와 GOP를 함께 검증한다
1. GOP가 정확히 뭔가
2. 세그먼트 길이는 누가 정하나
3. GOP가 세그먼트와 안 맞으면 — 패키저가 무엇을 하나
4. 경계 정렬 규칙 — 세그먼트 시작점을 IDR에 둔다
5. Scene-Cut Detection — 경계 정책과 함께 설정한다
7. 클린 정렬 모델이 깨지는 지점들
- 8. SA 체크리스트 — Media Push 설정 검토
- 관련 글
- 참고 자료
"YouTube Studio가 자꾸 키프레임 간격 경고를 띄워요.", "Media Push의 gop을 얼마로 설정해야 하나요?" 둘 다 키프레임 간격과 패키저의 세그먼트 경계를 따로 확인해야 풀립니다.
이 글은 GOP의 정의부터, 세그먼트 길이를 누가 정하는지, GOP가 안 맞을 때 HLS 패키저가 무엇을 하는지, Agora Media Push의 gop 파라미터를 어떻게 설정해야 하는지까지 정리합니다.
0. 핵심 명제 — 패키징 경계와 GOP를 함께 검증한다
인코더는 키프레임 간격을 만들고, 패키저는 실제 키프레임을 기준으로 세그먼트 경계를 선택한다. 목표 세그먼트 길이와 경계 키프레임을 함께 설계해야 한다.
흔한 오해와 정정:
| 오해 | 정확한 이해 |
|---|---|
| 인코더 GOP와 패키징은 별개라 무관 | 세그먼트 시작점에 적절한 랜덤 액세스 프레임이 필요 |
| GOP가 작으면 무조건 좋음 | 너무 작으면 압축 효율 ↓ → bitrate 동일이면 화질 ↓ |
| Scene-cut detection은 항상 꺼야 함 | 고정 경계가 필요하면 주기 키프레임을 보장하고 결과를 검증 |
| GOP=90, Seg=2초면 반드시 재인코딩 | 패키저 설정에 따라 다음 키프레임까지 세그먼트가 길어질 수 있음 |
1. GOP가 정확히 뭔가
GOP = Group of Pictures = 하나의 I-frame부터 다음 I-frame 직전 프레임까지의 묶음.
GOP는 인코더가 만드는 프레임 묶음을 설명하는 용어입니다. 독립 디코딩 가능 여부는 단순한 I-frame 표기만이 아니라 IDR 등 랜덤 액세스 지점과 open/closed GOP 구조에 달려 있습니다.
Open GOP vs Closed GOP
| 구분 | 정의 | 라이브 송출 |
|---|---|---|
| Closed GOP | 경계 뒤 프레임이 이전 GOP의 프레임을 참조하지 않음 | 독립 세그먼트 구성에 유리 |
| Open GOP | 경계를 넘어 참조할 수 있음 | 압축 효율과 랜덤 액세스 요구를 함께 검토 |
HLS에서 각 비디오 세그먼트는 IDR로 시작해야 한다는 Apple authoring 요구가 있으므로, 이 글의 예시는 닫힌 GOP와 주기적 IDR을 전제로 합니다.
두 가지 의미로 쓰임 — 헷갈리는 포인트
| 용어 | 의미 | 예시 (30fps, 키프레임 매 2초) |
|---|---|---|
| GOP size (프레임 수) | I-frame 사이의 프레임 개수 | 60 |
| GOP length (시간) | I-frame 사이의 시간 | 2초 |
| GOP interval / 키프레임 인터벌 | 위 둘 중 하나 (보통 시간) | 2초 |
계산 공식:
인코더 설정에서는 보통 프레임 단위로 입력:
| 도구 | 옵션 |
|---|---|
| FFmpeg | -g 60 |
| x264 | keyint=60 |
| Agora Media Push | gop: 60 |
GOP 구조 시각화
GOP size가 크다 = 압축 효율 ↑ (P/B-frame 비율 ↑) but 시작점 드뭄 GOP size가 작다 = 시작점 자주 = 빠른 채널 전환 but 압축 효율 ↓
고정 경계가 필요한 파이프라인에서는 목표 세그먼트 경계에 랜덤 액세스 지점이 오도록 GOP를 설계할 수 있습니다. 다만 플랫폼의 ingest 요구사항, open/closed GOP, scene-cut 정책이 다르므로 실제 manifest와 keyframe timestamp로 결과를 확인해야 합니다.
더 깊게: #27 프레임의 모든 것, #30 x264 실전 옵션
2. 세그먼트 길이는 누가 정하나
자체 파이프라인에서는 패키저 운영자가 목표 길이를 정하고, 관리형 플랫폼에서는 플랫폼의 ingest 요구사항을 따릅니다. 인코더의 키프레임 위치 때문에 실제 세그먼트 길이가 달라질 수 있습니다.
결정 주체별 정리
| 주체 | 결정하는 것 | 예시 |
|---|---|---|
| 패키저/플랫폼 | 목표 세그먼트 길이와 경계 정책 | HLS target duration, segment template |
| 인코더 (Media Push) | GOP 길이, 비트레이트, 코덱 | gop=60, 2500kbps, H.264 |
| HLS 규격/authoring 지침 | 플레이리스트 제약과 권장값 | target duration, IDR·경계 정렬 |
플랫폼별 세그먼트 길이
| 기준 | 공개 요구사항 |
|---|---|
| YouTube Live encoder | 키프레임 간격 2초 권장, 4초를 넘기지 않음 |
| Apple HLS authoring | 비디오 세그먼트는 IDR로 시작, IDR 간격 2초 권장, target/segment duration 6초 권장 |
| RFC 8216 | EXT-X-TARGETDURATION은 반올림한 모든 Media Segment duration 이상이어야 함 |
| Agora Media Push | gop 기본값은 frameRate × 2; 대상 플랫폼 요구에 맞춰 설정 가능 |
YouTube의 2초 값은 공개 encoder의 키프레임 간격 지침이지 YouTube 내부 HLS 세그먼트 길이를 공개한 값이 아닙니다. 둘을 같은 숫자로 단정하지 않습니다.
라이브 지연 공식
아래 식은 지연 예산을 설명하는 단순 모델이지 표준의 보장값이 아닙니다.
실제 E2E 지연은 여기에 추가:
- 인코더 버퍼링 (첫 GOP 완성 대기)
- CDN edge 전파 시간
- 네트워크 RTT
따라서 세그먼트 길이만으로 실제 E2E 지연을 산출하지 않습니다.
워크플로우
자체 HLS라면 패키저의 실제 경계와 IDR 위치를 함께 확인합니다. 관리형 플랫폼이라면 공개된 키프레임·코덱·비트레이트 지침을 따르고 헬스 메시지로 결과를 확인합니다.
3. GOP가 세그먼트와 안 맞으면 — 패키저가 무엇을 하나
핵심: HLS 패키저는 영상을 자를 때 키프레임 위치에서만 자를 수 있습니다. 키프레임이 없는 위치에서 시작하는 세그먼트는 독립 디코딩 불가능 → 패키저가 그런 세그먼트를 emit하지 않음.
시나리오 A: GOP = 세그먼트 길이 (정렬됨)
시나리오 B: GOP = 90 (3초), 세그먼트 = 2초
패키저가 취할 수 있는 동작
Apple authoring 요구에 맞춘 파이프라인은 비디오 세그먼트를 IDR로 시작시킵니다. transmux만 하는 패키저는 보통 목표 시각 뒤의 적절한 키프레임까지 경계를 늦추며, 재인코더가 앞단에 있으면 경계 키프레임을 새로 만들 수 있습니다. 정확한 동작은 패키저 설정으로 확인합니다.
옵션 1: 키프레임에 맞춰 세그먼트 길이를 늘림
원래 2초 세그먼트 → 강제로 3초 세그먼트로 변경.
- FFmpeg HLS 세그먼터의 기본 동작:
segment_time을 초과한 직후 다음 키프레임이 나올 때 자름 - 결과: 실제 세그먼트 길이가 목표보다 길어지고 target duration이 커질 수 있음
- 클라이언트가 원한 동작이 아님
옵션 2: 강제 키프레임 삽입 + 재인코딩
들어온 영상 → 디코딩 → 2초마다 I-frame 강제 삽입 → 재인코딩.
- 결과: CPU 비용 ↑, 화질 손실 (재인코딩은 항상 손실), 지연 ↑
- 관리형 플랫폼의 내부 재인코딩·패키징 방식은 공개 문서가 없으면 추정하지 않음
YouTube Stream Health 경고 (공식 확인)
YouTube는 키프레임 간격 문제에 대해 4종의 공식 헬스 메시지를 정의합니다.
| 코드 | 의미 |
|---|---|
gopSizeLong / gopSizeOver | "4초 이하 키프레임 주기를 사용하세요. 키프레임이 충분히 자주 전송되지 않아 버퍼링 발생 가능" |
gopSizeShort | 키프레임 간격이 권장보다 짧음 |
gopMismatch | 키프레임 주기 불일치 |
출처: YouTube Health Status Messages
이 경고가 뜬다면 GOP 값을 다시 검토할 신호.
4. 경계 정렬 규칙 — 세그먼트 시작점을 IDR에 둔다
고정된 세그먼트 시각마다 경계를 만들려면 그 시각에 IDR이 있어야 합니다. 고정 GOP가 세그먼트 경계와 같은 원점에서 시작한다는 전제에서는 segment_length / GOP_length가 정수인 설정이 간단한 방법입니다. 하지만 규격이 정수 비율 자체를 요구하는 것은 아닙니다.
인코더 시작 시각, VFR, 강제 키프레임 표현식의 반올림, scene-cut, 패키저 경계 정책 때문에 산수만 맞아도 실제 경계가 어긋날 수 있습니다.
케이스 매트릭스
| 설정 | 비율 | 결과 |
|---|---|---|
| GOP=2s, Seg=2s | 2/2 = 1 ✓ | 1:1 정렬, 세그먼트당 I-frame 1개 |
| GOP=1s, Seg=2s | 2/1 = 2 ✓ | 1:2 정렬, 세그먼트당 I-frame 2개 |
| GOP=2s, Seg=6s | 6/2 = 3 ✓ | 1:3 정렬, 세그먼트당 I-frame 3개 |
| GOP=4s, Seg=2s | 2/4 = 0.5 | 2초마다 독립 경계를 만들 수 없음 |
| GOP=1.67s (50f@30fps), Seg=2s | 약 1.2 | 고정 2초 경계와 주기적으로 어긋남 |
시나리오 C: GOP = 50 (1.67초), 세그먼트 = 2초
세그먼트마다 키프레임과 어긋나는 위치가 다름 → 일부는 정렬, 일부는 어긋남 → 옵션 1/2 패키저 보정 발생.
고정 경계가 필요한 경우의 출발점
고정 경계가 필요한 자체 패키징에서는 목표 세그먼트 경계와 같은 시각에 IDR을 두는 설정이 단순합니다.
YouTube의 2초 키프레임 권장을 따르면 30fps CFR 입력에서 gop=60이 출발점입니다. 실제 IDR 간격은 출력으로 확인합니다.
Apple HLS Authoring Spec의 세그먼트 길이 지침
Apple은 세그먼트가 target duration을 0.5초보다 많이 초과하지 않도록 권고하고, 모든 비디오 세그먼트가 IDR로 시작하도록 요구합니다. 이는 ±0.5초 허용이라는 대칭 허용 범위가 아닙니다.
5. Scene-Cut Detection — 경계 정책과 함께 설정한다
Scene-Cut Detection이 뭔가
대부분의 비디오 인코더(x264, NVENC, VideoToolbox)는 화면이 갑자기 바뀌는 순간(컷 전환, 카메라 스위치)을 감지하면 자동으로 그 자리에 I-frame을 끼워 넣습니다.
왜 이게 좋은가 (압축 효율 관점):
화면이 완전히 바뀌면 이전 프레임을 참조해봤자 차이가 너무 커서 P-frame이 거의 I-frame만큼 커짐. 차라리 그냥 새 I-frame 박는 게 효율적.
고정 경계에서 확인할 점
가변 GOP가 됨.
비활성화 방법
| 도구 | 옵션 |
|---|---|
| FFmpeg | -sc_threshold 0 |
| x264 params | scenecut=0 또는 no-scenecut |
| AWS IVS 권장 FFmpeg | -x264opts "nal-hrd=cbr:no-scenecut" |
| NVENC | -no-scenecut (일부 버전에서 -sc_threshold 무시 이슈 보고) |
| VideoToolbox / MediaCodec | 직접 끄는 공개 옵션 명확 X — 고정 GOP(-g)와 -force_key_frames로 우회 |
실무 팁: 하드웨어 인코더는 소프트웨어(x264)보다 GOP 제어 옵션이 제한적입니다. NVENC는 일부 옵션이 무시되는 이슈가 있어 결과를 ffprobe로 확인 권장.
6. Agora Media Push — 구체 설정
gop 파라미터는 공식 노출됨
Agora Media Push REST API의 transcodeOptions.videoOptions 하위에 gop 파라미터가 있습니다.
| 항목 | 값 |
|---|---|
| 기본값 | frameRate × 2 (기본 frameRate가 15fps이므로 기본 GOP = 30프레임 = 2초) |
| 단위 | 프레임 수 |
| 명시적 설정 | 클라이언트가 송출 대상에 맞춰 직접 계산해 넣어야 함 |
설정 예 — YouTube Live (30fps, 2초 키프레임 간격)
Rate Control — 대상 플랫폼 요구에 맞춘다
GOP만큼 자주 묻는 질문: "비트레이트는 고정해야 하나, 가변으로 해야 하나?"
| 모드 | 동작 | 용도 |
|---|---|---|
| CBR (Constant Bitrate) | 버퍼 모델 안에서 목표 전송률 유지 | 일부 라이브 ingest 요구 |
| VBR (Variable Bitrate) | 복잡한 장면엔 더, 단순한 장면엔 덜 | VOD, 파일 저장 |
| CRF (Constant Rate Factor) | 화질 일정하게 유지, 비트레이트 가변 | 고품질 VOD |
| Capped VBR | VBR이지만 최대 비트레이트 제한 | 라이브 + 화질 우선 |
YouTube는 라이브 encoder 설정에서 CBR을 권장합니다. 다른 플랫폼이나 자체 파이프라인은 capped VBR을 허용할 수 있으므로 ingest 문서를 우선합니다.
- 네트워크 대역폭 예측 가능 → 시청자 디바이스의 ABR 알고리즘이 정확히 판단 가능
- 시청자 버퍼 관리 안정적 → 갑자기 비트레이트가 폭증하는 일 없음
- CDN 비용 예측 가능 → 정량적 청구
FFmpeg CBR 설정 예:
-x264-params nal-hrd=cbr이 핵심 — 이게 빠지면 x264는 평균 비트레이트만 맞추고 순간 비트레이트는 가변. AWS IVS 같은 엄격한 플랫폼에서는 이 옵션이 없으면 거부될 수 있음.
Agora REST 문서는 bitrate의 허용 범위를 공개하지만 rate-control 모드를 CBR로 보장한다고 명시하지 않습니다. 이 값만 보고 순간 비트레이트 동작을 단정하지 않습니다.
Scene-Cut Detection — 공개 계약과 출력 검증 범위
Agora 공개 REST 문서는 gop 값은 설명하지만 scene-cut 정책은 명시하지 않습니다. gop을 설정한 뒤 출력 스트림의 실제 keyframe timestamp를 측정해 고정 간격 여부를 확인합니다.
gop 설정값만으로 출력의 IDR과 패키저 경계를 증명할 수 없습니다. 다음 두 결과를 측정합니다.
- 필요한 최대 키프레임 간격을 충족
- 패키저가 선택한 세그먼트 경계에 IDR 존재
잘못된 케이스 예
클라이언트가 gop: 90 (30fps에서 3초)로 YouTube에 송출:
- 실제 키프레임 간격이 3초라면 YouTube의 2초 권장값보다 김
- YouTube 내부 세그먼트 길이나 재인코딩 방식을 추정하지 않고 Stream Health 경고로 확인
- Stream Health에
gopSizeLong경고 발생 가능
7. 클린 정렬 모델이 깨지는 지점들
이 글의 모든 산수는 표준 HLS 기준입니다. 다음 시나리오에서는 모델 자체가 바뀜.
LL-HLS — Part 단위로 쪼갬
LL-HLS는 EXT-X-PART 태그로 세그먼트 안의 sub-segment "part"를 표현합니다. part target은 패키저가 정하며 Apple 문서는 200ms 예시를 보여 줍니다.
Part는 세그먼트보다 먼저 전송할 수 있는 조각입니다. 모든 part가 독립 디코딩 가능한 것은 아니며 INDEPENDENT=YES인 part만 독립 시작점입니다. 따라서 GOP를 part duration과 같게 만들 필요는 없습니다. 세그먼트와 rendition 경계 정렬, 독립 part 정책을 패키저 문서에 맞춥니다.
CMAF Chunked Transfer
CMAF chunk는 세그먼트 내부 샘플을 일찍 전달할 수 있지만, 랜덤 액세스와 switching set 정렬 요구가 사라지는 것은 아닙니다.
LL-DASH는 0.5~2초 chunk가 일반적이며, GOP는 chunk 단위가 아닌 segment 단위에 맞춤.
HLS vs DASH 패키저 차이
| 항목 | HLS | DASH |
|---|---|---|
| 세그먼트 duration 표현 | EXT-X-TARGETDURATION (엄격) | SegmentTemplate + $Time$/$Number$ |
| 가변 GOP 톨러런스 | 낮음 | 비교적 높음 (실제 duration을 명시) |
| 라이브 모드 | 표준 + LL-HLS | 표준 + LL-DASH |
DASH는 각 세그먼트의 실제 duration을 명시할 수 있어 약간의 GOP drift에 더 관대합니다. 멀티 프로토콜 환경에서는 이 차이를 고려.
8. SA 체크리스트 — Media Push 설정 검토
9. 한 줄 결론 + 진단 흐름
플랫폼의 키프레임 요구를 먼저 따르고, 자체 패키징에서는 실제 세그먼트 경계가 IDR에 놓이는지 출력으로 검증한다. 정수 비율은 유용한 설계법이지 표준의 보편 규칙은 아니다.
트러블 진단 흐름
한 장 요약
관련 글
- 프레임의 모든 것 — I·P·B-frame / GOP / PLI·FIR
- B-frame 이해하기 — 라이브 전송에서 B-frame이 만드는 재정렬 지연
- x264 실전 옵션 — ref / tune / keyint — keyint 강제 설정 패턴
- M3U8과 TS 파일의 모든 것 — HLS 세그먼트 구조
- 라이브 스트림 점검 — ffprobe / gstreamer — GOP 검증 명령어
- RTMP B-frame PTS rollback 사례 — Agora Media Gateway 트러블
- ABR Ladder Layer B 정렬 — 키프레임 동기화 — 멀티 레이더에서 GOP 정렬이 ABR 전환에 미치는 영향
- 라이브 스트리밍 프로토콜 선택 — HLS / LL-HLS / WebRTC — 세그먼트 길이가 지연을 결정하는 큰 그림
참고 자료
- RFC 8216 — HTTP Live Streaming — EXT-X-TARGETDURATION, 세그먼트 duration 제약의 원전 (§4.3.3.1, §6.2.1)
- draft-pantos-hls-rfc8216bis — HTTP Live Streaming 2nd Edition — LL-HLS / EXT-X-PART / HOLD-BACK·PART-HOLD-BACK (3배 규칙) 정의
- Apple — HLS Authoring Specification for Apple Devices — 세그먼트 duration 톨러런스, 키프레임 정렬, IDR 권장사항
- YouTube Help — Live streaming error messages — gopSizeLong / gopSizeShort / gopMismatch 등 Stream Health 메시지 정의
- YouTube Help — Choose live encoder settings, bitrates, and resolutions — 2초 키프레임 간격 및 해상도별 비트레이트 권장값
- Agora — Media Push REST API — transcodeOptions.videoOptions.gop 등 송출 파라미터 명세
- FFmpeg — x264 / libx264 encoding options — keyint, sc_threshold, nal-hrd=cbr 등 GOP·Rate Control 옵션