블로그 목록
Media15분 읽기

x264 실전 옵션 — ref, tune, keyint 설정과 검증

x264의 reference frame 수, tune, keyint, scenecut 설정이 압축 효율·encoder latency·random access에 미치는 영향을 설명합니다. 실시간 통신과 HLS·VOD의 요구사항을 구분하고, 특정 값을 보편적인 정답으로 제시하지 않고 수신기 호환성과 실제 frame output으로 검증합니다.

x264H.264reftunezerolatencykeyintGOPOBSFFmpegWebRTC

28편에서는 Profile과 비트레이트, 29편에서는 B-frame 자체를 다뤘습니다. 이 글은 OBS/FFmpeg에서 만나는 x264의 ref, tune, profile, keyint를 다룹니다. 값은 표준 정답이 아니라 latency budget, 협상 capability와 ingest 규격에 맞춰 선택합니다.


1. ref — reference frames (참조 프레임 수)

개념

ref는 x264가 사용할 최대 reference picture 수를 제한합니다. ref=1도 항상 직전 picture만 고른다는 뜻은 아니며, 실제 reference와 DPB 요구량은 picture type·B-pyramid·level과 encoder 결정에 따라 달라집니다.

ref=1 (실시간용 권장) I P1 P2 P3 각 P는 직전 프레임 1개만 참조 (체인처럼) ref=4 (VOD용 고화질) I P1 P2 P3 P4 P4가 과거 4개(I, P1, P2, P3) 모두 참조 가능 — 압축률 ↑ (최적 참조 선택), 연산량 ↑, 메모리 ↑ 실시간 통신: ref=1 — 디코더 부담 최소, 손실 복구 단순 • 디코더 메모리 사용량 ↓ — 과거 프레임 1개만 보관 • reference graph 단순화 — refresh와 concealment 분석이 쉬워질 수 있음 • 인코더 연산 ↓ — 후보 프레임 하나만 비교 • 압축률은 약간 손해지만 실시간에서는 지연/안정성이 우선

왜 실시간에서 ref=1?

  • 디코더 메모리 사용량 ↓ — 과거 프레임 1개만 보관하면 되므로 저사양 기기에서도 안정적으로 동작합니다.
  • reference graph 단순화 — ref=1은 의존 구조를 단순화할 수 있지만 PLI는 손실 frame 자체를 재요청하지 않습니다. PLI는 picture loss를 알리고 sender가 decoder refresh picture를 만들 수 있게 합니다.
  • 인코더 연산 ↓ — 후보 참조 프레임이 하나이므로 탐색 연산이 최소입니다.
  • 압축률은 약간 손해지만 실시간에서는 지연/안정성이 우선입니다.

ref 값 선택 가이드

ref 값용도이유
1low-latency 시작점reference 탐색·DPB와 dependency 단순화
2~3live/VOD 후보target device level과 실측 quality 확인
4~6VOD 후보DPB·level 제약과 encoding time 확인

2. tune — 용도별 프리셋

튠(tune)은 특정 용도에 맞춰 x264 내부 파라미터 세트를 한 번에 조정하는 프리셋입니다. x264엔 수십 개의 세부 옵션이 있어 수동으로 모두 맞추기가 복잡합니다. tune 하나로 주요 파라미터 묶음을 한 번에 최적화합니다.

튠용도
film영화용, 고화질 VOD
animation애니메이션 (단색 영역 많음)
grain노이즈 보존 (필름 질감)
stillimage정지 이미지에 가까운 영상
fastdecode디코딩 부담 최소화 (저사양 기기)
zerolatency지연 최소화 (실시간 스트리밍/화상회의)

zerolatency가 내부적으로 하는 일

--bframes 0           (B-frame 비활성)
--force-cfr           (고정 프레임레이트)
--no-mbtree           (매크로블록 트리 비활성 — 미리보기 분석 끔)
--sync-lookahead 0    (look-ahead 비활성)
--sliced-threads      (슬라이스 병렬처리, 프레임 대기 없음)
--rc-lookahead 0      (레이트 컨트롤 look-ahead 제거)

핵심은 미래 프레임 미리 보지 말고 현재 프레임만 즉시 처리입니다. B-frame도 자동으로 꺼집니다. → 왜 B-frame이 지연의 원인인지는 B-frame 이해하기 참조.

-tune zerolatency는 x264 source에서 bframes=0을 포함해 적용합니다. 같은 값을 -x264-params에 반복한다고 더 강하게 적용되지는 않으므로, override 의도가 없다면 중복을 줄입니다.

tune 적용 FFmpeg 예시

# 실시간 스트리밍 (OBS Custom FFmpeg 설정 참고)
ffmpeg -i input \
  -c:v libx264 \
  -preset veryfast \
  -tune zerolatency \
  -x264-params "ref=1:keyint=60" \
  -b:v 2500k \
  -f flv rtmp://live.example.com/stream

# VOD 고화질 인코딩
ffmpeg -i input \
  -c:v libx264 \
  -preset slow \
  -tune film \
  -x264-params "ref=4:bframes=3:keyint=240" \
  -crf 18 \
  output.mp4

3. profile — 호환성 vs 기능

이전 글에서 다뤘듯이 H.264 프로파일 선택입니다. 자세한 분석은 H.264 Profile·인코더 옵션 참조. 이 글에서는 x264 옵션 맥락에서의 실무 정리만 다룹니다.

프로파일특징Agora/WebRTC
baseline기능 제한downstream이 해당 profile을 협상한 경우 사용
mainB-slice, CABAC 허용Main 협상과 실제 bitstream 일치 필요
high8x8 transform 등 추가High 협상·level·decoder capability 확인

**profile=main + bframes=0**은 CABAC을 사용할 수 있으면서 B-picture reorder delay를 제거하는 조합입니다. 그러나 WebRTC endpoint가 Main을 협상하지 않았다면 호환 설정이 아닙니다.

profile 선택 매트릭스

환경별 권장:

브라우저 WebRTC (Chrome ↔ Safari ↔ Firefox):
  → Constrained Baseline 또는 Baseline
  → MTI 표준, 가장 안전

SDK 기반, 서버-클라이언트 양쪽 통제:
  → SDP/SDK capability가 Main을 합의한 경우 Main + bframes=0
  → High도 실제 협상·target device 검증 후 사용

VOD 녹화·배포:
  → High + bframes=2~3  (최대 압축 효율)

4. keyframe 간격 — 2초는 표준이 아니라 운영 설정

2초는 여러 live ingest 가이드에서 자주 보이는 값이지만 WebRTC나 H.264의 보편 표준값은 아닙니다. 서비스의 join/seek 방식, segment duration, feedback 복구와 bitrate budget으로 결정합니다.

개념

keyint는 x264의 최대 keyframe interval을 frame 수로 제한합니다. scene cut, open GOP, 외부 forced keyframe과 IDR 정책 때문에 모든 "I-picture 사이 시간"과 항상 같은 개념은 아닙니다.

x264 파라미터 이름: keyint (또는 --keyint). 단위는 프레임 수. 60fps에서 keyint=120이면 2초 간격.

1초 간격 (매우 짧음) I 0초 I 1초 I 2초 I 3초 I 4초 keyframe 기회 증가 → bitrate 비용과 refresh 속도 tradeoff 2초 간격 (live ingest 예시) I 0초 I 2초 I 4초 P P P ... P P P P ... P segment 경계와 맞출 수 있는 한 예; 실제 요구사항 확인 10초 간격 (VOD용) I 0초 P P P P P P P P P P P P P P P P P P ... I 10초 긴 interval → intra 비용 감소 가능, refresh 기회는 줄어듦 interval 선택 기준 — ingest 규격, segment alignment, join/refresh 정책, bitrate • independent segment가 필요하면 segment boundary와 random-access point 정렬 • WebRTC join은 PLI·cached keyframe 등 구현 경로도 함께 확인 • 다음 keyframe이 와도 packet loss가 있으면 복구가 보장되지 않음 • ingest provider별 현재 keyframe 요구사항을 공식 문서에서 확인 • bitrate 차이는 content·QP·scene cut 조건으로 실측

interval을 정할 때 확인할 5가지

1. HLS/DASH 세그먼트 단위와 일치

independent HLS segment를 만들려면 segment boundary를 random-access point에 맞춥니다. 2초 keyframe interval이 2/4/6초 segment와 정확히 정렬하려면 CFR, 시작 시각과 forced-keyframe policy까지 맞아야 합니다.

2. 채널 조인 대기 시간

새 decoder는 적절한 parameter set과 refresh picture가 필요합니다. WebRTC에서는 PLI 전달이나 SFU keyframe cache를 쓸 수 있으므로 대기 시간이 정기 interval과 항상 같지는 않습니다.

3. 패킷 손실 복구 최악 시나리오

feedback 없이 다음 decoder refresh point를 기다리는 시간은 interval의 영향을 받습니다. 다만 해당 packet도 손실될 수 있어 interval이 복구 시간의 보장 상한은 아닙니다.

4. 대역폭 오버헤드 적정

keyframe과 inter picture의 크기 차이는 content·QP·rate control에 따라 다릅니다. 후보 interval별 bitrate와 quality를 같은 clip으로 측정합니다.

5. 업계 관행

live ingest provider는 각자 keyframe interval 요구사항을 둘 수 있습니다. WebRTC 구현체의 공통 표준 기본값으로 일반화하지 말고 현재 공식 ingest 문서와 SDK encoder 설정을 확인합니다.

프레임 수로 환산

fpskeyint (2초 기준)
3060
60120

OBS에서 "키프레임 간격 2"라고 입력하면 OBS가 현재 fps를 보고 자동 계산합니다. FFmpeg 직접 설정 시엔 -x264-params keyint=60 식으로 프레임 수를 씁니다.

keyint vs min-keyint

x264엔 두 가지 keyint 옵션이 있습니다.

keyint     (또는 --keyint):     최대 키프레임 간격
min-keyint (또는 --min-keyint): 최소 키프레임 간격

기본값:
  keyint=250     (약 8초 @ 30fps)
  min-keyint     (x264 source 기본 계산: min(keyint/10, fps), 이후 1..keyint/2+1로 clip)
                 keyint=250, 30fps이면 25

실시간 스트리밍 권장:
  keyint=60      (2초 @ 30fps)
  scenecut=0     (scene-cut keyframe 억제)

사용자가 지정한 min-keyint도 x264 validation에서 최대 keyint/2+1로 clip됩니다. 따라서 keyint=60:min-keyint=60을 "정확히 60 frame"의 근거로 쓰면 안 됩니다. closed, fixed GOP가 필요하면 CFR 입력에서 keyint=60:scenecut=0:open-gop=0을 사용하고 실제 output의 IDR/PTS를 ffprobe로 검증합니다.


5. 한 줄 정리

옵션실시간 값VOD 값이유
reflow-latency 시작점 1content·level에 따라 평가DPB, 탐색 비용, reference graph
tunezerolatencyfilm미래 프레임 look-ahead 제거 vs 최대 압축
profileSDP/SDK에서 협상된 profiletarget decoder가 지원하는 profilecompatibility와 coding tool
keyintingest/refresh 정책에 맞춤seek·segment 정책에 맞춤random access, bitrate, segment alignment

조합 예시 — 실전 설정

# OBS x264 option 예시. Tune은 OBS의 별도 Tune 항목에서 zerolatency 선택
x264opts=ref=1:keyint=60:scenecut=0:open-gop=0

# FFmpeg CLI (실시간 스트리밍)
ffmpeg -i input \
  -c:v libx264 \
  -profile:v main \
  -preset veryfast \
  -tune zerolatency \
  -x264-params "ref=1:keyint=60:scenecut=0:open-gop=0" \
  -b:v 2500k \
  -maxrate 2500k \
  -bufsize 5000k \
  -f flv rtmp://live.example.com/stream

# FFmpeg CLI (VOD 고화질)
ffmpeg -i input \
  -c:v libx264 \
  -profile:v high \
  -preset slow \
  -tune film \
  -x264-params "ref=4:bframes=3:keyint=240:b-pyramid=normal" \
  -crf 18 \
  output.mp4

위 live 명령의 -b:v/-maxrate/-bufsize는 VBV 제약 예시이지 모든 순간의 strict CBR을 보장하는 설정은 아닙니다. ingest provider가 HRD/filler를 요구하면 해당 규격을 별도로 확인합니다. 또한 tune은 FFmpeg의 -tune zerolatency로 전달해야 하며 -x264-params "tune=zerolatency"는 유효한 x264 parameter가 아닙니다.


6. 트레이드오프 시각화 — 실시간 vs VOD

실시간과 VOD 설정의 차이를 한 번에 보면 이렇습니다.

실시간 스트리밍 / WebRTC VOD 인코딩 / 녹화 배포 ref ref=1 디코더 메모리 ↓, 복구 단순 ref ref=3~4 압축률 최대화 tune zerolatency look-ahead 제거, bframes=0 tune film / animation 콘텐츠 특성 최적화 profile main + bframes=0 협상된 경우 CABAC 사용, B-picture 제거 profile high + bframes=2~3 8x8 변환, B-frame 압축 keyint 60 @ 30fps / 120 @ 60fps 2초는 ingest 설정 예시 keyint 240 ~ 300+ I-frame 최소화, 파일 크기 ↓ 우선순위 ① 지연 최소화 ② 패킷 손실 복구 안정성 우선순위 ① 압축률 최대화 ② 같은 화질에 파일/대역폭 최소

관련 글

참고 자료

© 2026 Frank Kim. All rights reserved.