Skip to content

libx264와 libx265 파라미터 비교: CRF, VBV, 스레딩 실측 데이터 ​

CRF 26과 CRF 30이 같은 화질이라면 처음 들었을 때는 앞뒤가 맞지 않는 이야기로 들립니다. 숫자를 먼저 보고 거꾸로 파라미터를 뜯어보겠습니다.

먼저 숫자부터: 같은 원본, 세 가지 설정의 실측 결과 ​

같은 1080p 원본을 세 가지 설정으로 인코딩했습니다. 목표는 하나였습니다. libx264 기본 설정 대비 비트레이트를 얼마나 줄이면서 화질을 지킬 수 있는가였습니다.

인코더출력 비트레이트VMAFvs 기준 절감
libx264 (기준값)1,478 kbps97.858(기준)
libx264 (템플릿)909 kbps98.207-38.5%
libx265 (템플릿)678 kbps98.629-54.1%

여기서 기준값은 튜닝 없이 인코딩한 libx264 결과이고, 템플릿은 이 글에서 다룰 CRF와 VBV, preset 등을 조정한 설정입니다.

눈여겨볼 지점은 비트레이트가 아니라 VMAF가 함께 올랐다는 사실입니다. 보통 절감율을 높이면 화질은 내려갑니다. 그런데 678 kbps 설정이 1,478 kbps 기준값보다 높은 점수를 받았습니다. 절반 이하의 비트로 더 높은 점수를 낸 셈입니다.

참고: VMAF는 업계에서 널리 쓰이는 객관적 화질 평가 지표입니다. 0에서 100 스케일이고 통상 93점 이상부터 일반 시청자가 원본과 구분하지 못하므로, 98.6점은 프로덕션 마스터 급입니다.

두 줄의 명령어가 먼저 보여주는 것 ​

같은 파이프라인, 같은 오디오 설정인데 비디오 파라미터는 이렇게 달랐습니다.

bash
# libx264 템플릿 (H.264)
./bin/ffmpeg -i input.mp4 \
  -c:v libx264 \
  -x264-params preset=slow:tune=vod:crf=26:vbv-maxrate=3000:vbv-bufsize=6000 \
  -c:a libfdk_aac -ab 64k -ac 2 -ar 48000 \
  -y output.mp4
bash
# libx265 템플릿 (H.265/HEVC), 오디오 설정은 위와 동일
./bin/ffmpeg -i input.mp4 -c:v libx265 \
  -x265-params preset=3:tune=vod:crf=30:vbv-maxrate=2000:vbv-bufsize=4000 \
  -c:a libfdk_aac -ab 64k -ac 2 -ar 48000 -y output_hevc.mp4

차이는 세 가지입니다. CRF는 4가 높아졌고(화질 목표를 낮췄다는 뜻입니다), VBV는 모두 3분의 2로 줄었습니다. 그런데 결과물의 화질은 더 좋았습니다. 이게 HEVC의 압축 효율입니다. 아래에서 하나씩 뜯어보겠습니다.

CRF 26과 CRF 30이 같은 화질인 이유 ​

CRF는 비트레이트가 아니라 화질을 목표값으로 잡는 레이트 컨트롤입니다. 인코더가 프레임마다 QP를 자동 조절해서 영상 전체의 인지 품질을 일정하게 유지합니다. 복잡한 장면은 QP를 낮춰 비트를 더 쓰고, 단순한 장면은 QP를 올려 비트를 아낍니다. 경험칙이 하나 있습니다. CRF가 6 올라갈 때마다 비트레이트는 대략 절반이 됩니다.

CRF 스케일 0에서 51까지, 18 전후부터 시각적 무손실 구간이 시작됨을 보여주는 다이어그램

그럼 왜 264는 26, 265는 30일까요. 두 사실을 겹치면 답이 나옵니다.

  1. CRF +6은 비트레이트 절반과 같습니다
  2. HEVC는 H.264 대비 동일 화질에서 40~50% 낮은 비트레이트를 냅니다

즉 HEVC 쪽에서 CRF를 4~6 올려도 눈에 보이는 화질은 유지되고, 대신 비트레이트가 확 줄어듭니다.

설정비트레이트VMAF
libx264 CRF 26909 kbps98.207
libx265 CRF 30678 kbps98.629

CRF가 4나 높음에도 VMAF가 오히려 올랐습니다. 이게 HEVC 효율의 실측 증거입니다.

264 쪽에서 26을 쓰는 이유는 CRF 스펙트럼에서 26의 위치를 보면 이해됩니다. 18은 시각적 무손실, 23은 방송급 OTT 1080p, 28은 모바일 절약용입니다. 23은 VOD 용도로 과잉 품질이고, 28은 야간이나 폭포 같은 고복잡도 장면에서 열화가 눈에 띌 수 있습니다. 26이 일반적인 VOD의 최적 지점입니다.

참고: 실무에서 자주 하는 실수는 H.264에서 쓰던 CRF를 H.265에 그대로 가져가는 것입니다. 그러면 비트레이트가 과하게 나와서 HEVC를 쓰는 이유가 사라집니다. 반대로 너무 올리면 효율을 화질 손해로 바꾸는 셈입니다.

VBV: 3000/6000과 2000/4000은 사실 같은 설정이다 ​

항목libx264libx265
vbv-maxrate30002000
vbv-bufsize60004000
bufsize / maxrate2.0초2.0초

절대값은 다른데 비율이 똑같습니다. 이게 핵심입니다.

VBV는 표준에 정의된 가상의 디코더 버퍼 모델입니다. 실존하지 않는 가상 디코더가 정해진 버퍼 크기 안에서 정해진 속도로 데이터를 꺼내간다고 가정하고, 인코더가 이 가상 디코더를 언더플로(버퍼가 빔)나 오버플로(버퍼가 넘침)시키지 않도록 비트 할당을 제한합니다.

vbv-maxrate는 수도관의 굵기(초당 들어오는 데이터량)이고, vbv-bufsize는 물탱크의 크기(미리 담아둘 수 있는 최대 데이터량)입니다. bufsize를 maxrate로 나눈 값은 몇 초 분량의 버스트를 허용할 것인가를 뜻합니다. 두 템플릿 모두 2.0초입니다. libx265의 절대값이 작은 건 출력 비트레이트 자체가 낮기 때문이지, 버스트 허용 전략이 다른 게 아닙니다.

주의: 비율을 깨뜨리면 양쪽 다 문제가 생깁니다. 너무 빡빡하게 잡으면(maxrate=1000, bufsize=1000, 비율 1.0초) 인코더가 비트 변동을 거의 못 줘서 장면 전환에서 화질이 급락합니다. 너무 헐겁게 잡으면(maxrate=10000, bufsize=80000, 비율 8.0초) 인코더가 큰 폭으로 비트를 뿜어서 실제 플레이어 버퍼가 감당하지 못합니다. 버퍼링이 발생합니다.

bufsize : maxrate = 2 : 1은 VOD 스트리밍의 경험적 최적비입니다. 네트워크 변동을 흡수하면서도 과도한 버스트를 막습니다. 2.0초로 잡은 이유는 Roku, Apple TV, 스마트 TV 계열 플레이어 SDK가 일반적으로 유지하는 재생 버퍼 크기와 맞닿아 있습니다. 인코더가 실제 플레이어가 감당할 수 있는 한도 내에서 최대한 코딩 효율을 끌어내겠다는 설계입니다.

preset 범위가 0~9와 -1~10으로 다른 이유 ​

인코더preset 범위템플릿 값
libx2640(ultrafast) ~ 9(placebo)slow (=5)
libx265-1(ripping) ~ 10(ultrafast)3

H.265의 연산 비용이 H.264의 5~10배이기 때문입니다. CTU 가변 블록 분할, 35개 인트라 예측 방향, 더 정교한 움직임 보상, SAO 필터가 추가되면서 연산 스펙트럼 자체가 넓어졌습니다. 그만큼 다이얼도 넓어야 합니다.

libx265 preset 스펙트럼, -1 ripping부터 10 ultrafast까지 표시되고 템플릿 값 3이 강조된 다이어그램

ripping(-1)은 placebo에서 한 단계 더 나아가 모든 B-frame을 양방향 참조(B-pyramid)로 구성하고 움직임 예측을 full search로 도는 모드입니다. slow 대비 10배 이상 걸리지만, 한 번 인코딩해서 오래 쓰는 아카이브 마스터 용도에는 맞습니다. 템플릿 값 3은 고화질 VOD와 합리적 인코딩 시간 사이의 실용적 지점으로, H.264의 slow와 체감 인코딩 시간이 비슷합니다. 264에서 slow를 쓰는 것도 같은 이유입니다. VOD는 실시간성이 필요 없으니 무거운 preset으로 화질 이득을 보면 됩니다. 다만 placebo는 slow 대비 화질 향상이 통상 0.5% 미만인데 인코딩 시간은 2~3배라 비용 대비 효과가 없습니다.

keyint에 "8의 배수" 제약이 붙는 이유 ​

libx265의 keyint에는 libx264에 없는 제약이 있습니다. 50보다 크면서 8의 배수여야 합니다. 이유는 H.265의 블록 단위인 CTU에 있습니다. H.264가 고정 16x16 Macroblock을 쓰는 것과 달리, HEVC는 최대 64x64까지 지원하는 CTU를 쿼드트리로 재귀 분할합니다.

H.264의 고정 16x16 Macroblock과 H.265의 64x64 CTU가 32x32, 16x16, 8x8로 쿼드트리 분할되는 과정을 비교하는 다이어그램

HEVC에서 하나의 CTU 행은 8프레임에 걸쳐 완전히 순환하도록 설계되어 있습니다. keyint를 8의 배수로 맞추지 않으면 GOP 끝에서 CTU 행이 불완전하게 잘리고, WPP 스케줄링이 꼬여서 디코딩 효율이 떨어집니다.

keyint 자체의 트레이드오프도 짚어 두겠습니다. 30fps에서 256이면 GOP 하나가 약 8.5초입니다. 30(1초)은 압축률이 낮지만 seek가 매우 빠르고, 150(5초)은 스포츠 VOD에, 256(8.5초)은 일반 VOD에, 500 이상(16초 이상)은 압축률이 매우 높지만 seek가 느려 아카이브나 다운로드 전용에 어울립니다.

참고: keyint=0은 자동 모드입니다. 씬 전환을 감지해서만 IDR을 넣는데, 콘텐츠에 따라 간격이 크게 달라집니다. seek 성능이 중요한 OTT에서는 보통 명시적 값을 선호합니다.

open-gop, rc-lookahead와 두 개의 스레드 파라미터 ​

open-gop (265 전용, 기본 On)

Closed-GOP는 경계에서 참조가 끊어지고 Open-GOP는 경계 앞 B 프레임이 이전 GOP의 P 프레임을 참조하는 구조를 비교하는 다이어그램

Open-GOP는 GOP 경계에서도 예측을 유지할 수 있어 압축 효율이 높습니다. HEVC 표준에 정식으로 포함되어 있고 VOD에서는 기본 On이 일반적입니다. 대신 GOP 경계가 모호해져서, GOP 단위 컷 편집 시 참조가 깨질 수 있습니다.

rc-lookahead (264는 1~250, 265는 0~250)

인코더가 현재 프레임 이후 최대 N프레임을 미리 분석해서 비트 할당을 최적화하는 기능입니다. 씬 전환을 감지하면 새 장면 시작에 비트를 몰아주고, 움직임이 급해지면 선제적으로 QP를 낮춰 블러를 막습니다. 250이면 선견지명이 가장 길지만 30fps 기준 8.3초의 지연이 붙습니다. 40~60이 VOD 권장값으로 지연 1.3~2.0초에 대부분의 씬 전환을 커버합니다. 1이면 효과가 거의 없어 급변 장면에서 화질이 일시적으로 떨어집니다.

265가 0부터 시작하는 이유는 계층적 B-frame(Hierarchical B) 구조 덕분입니다. HEVC는 GOP 내 프레임을 시간적 계층으로 나눠 피라미드 구조를 만드는데, 이 구조 자체가 lookahead 없이도 비트 분배를 꽤 잘합니다. 그래서 rc-lookahead=0으로 꺼도 어느 정도 품질이 유지됩니다. 그래도 VOD 최적 화질을 원하면 40~60이 권장입니다.

threads(264) vs pool-threads(265)

항목H.264 threadsH.265 pool-threads
범위 / 기본값0~128, 자동(코어 수)0~256, 자동(코어 수)
병렬화 단위프레임CTU 행(row)
스레드 간 의존성앞 프레임 완료를 기다림윗 행이 2 CTU 앞서면 바로 시작
확장성스레드 수만큼 지연, 화질 저하 가능CTU 행 수만큼 거의 선형 확장
화질 영향있음없음

WPP는 CTU 행 단위로 병렬화를 겁니다. 윗 행이 2개 CTU 앞서 나가면 아랫 행이 시작하는 식입니다.

WPP가 CTU 행 단위로 2 CTU 지연을 두고 파도처럼 순차적으로 병렬 처리되는 구조를 보여주는 다이어그램

이 지연된 시작 패턴이 파도(wave)처럼 보인다고 해서 Wavefront입니다. 1080p 기준 CTU 행은 34개(1080/64, 올림), 4K면 68개, 8K면 136개입니다. 상한 256은 8K에서도 모든 CTU 행을 개별 스레드에 물릴 수 있게 둔 여유입니다. 반면 H.264의 프레임 기반 threading은 동시에 돌릴 수 있는 프레임이 수 프레임뿐이라 128이면 이미 충분합니다. 경험적으로 8~16 스레드가 H.264의 효율 상한이고, 그 이상은 화질 이득 없이 전력만 먹습니다.

참고: 이름이 threads와 pool-threads로 다른 건 명명 취향이 아닙니다. 후자는 WPP 전용 스레드 풀(Wavefront pool)로, 완전히 다른 병렬화 아키텍처입니다.

종합 비교표 ​

파라미터libx264libx265차이의 근본 원인
preset0~9 (slow=5)-1~10 (3)HEVC 연산량이 5~10배라 더 넓은 스펙트럼이 필요, ripping(-1)은 극한 압축 모드
crf0~51, 템플릿 261~51, 템플릿 30CRF +6 = 비트레이트 절반, HEVC의 40~50% 효율 우위로 CRF를 4~6 올려도 동일 화질. 265는 무손실이 별개 파라미터(lossless)라 시작값이 1
vbv-maxrate / vbv-bufsize3000 / 60002000 / 4000출력 비트레이트가 낮으니 VBV도 비례 축소, 비율(2:1 = 2.0초 버스트)은 동일 유지
rc-lookahead1~2500~250HEVC의 계층적 B-frame이 lookahead 없이도 비트 분배를 어느 정도 최적화
open-gop없음있음 (기본 On)HEVC 표준에 정식 포함, GOP 경계 예측으로 압축 효율 향상
keyint0~100,000, 기본 2560~100,000, 기본 256, 제약 50 초과 및 8의 배수CTU(64x64) 구조가 GOP 경계의 8프레임 정렬을 요구, WPP 스케줄링과 연관
bitrate 상한고정 2,000,000 kbpsyuv_size x fps 이하HEVC는 물리적으로 raw 데이터레이트를 초과할 수 없어 동적 상한을 둠
threads / pool-threads0~128 (Frame Threading)0~256 (WPP)HEVC는 CTU 행 단위로 병렬화해 프레임 기반보다 확장성이 높음

bitrate 상한이 동적인 이유도 간단합니다. 1080p YUV420은 프레임당 1920 x 1080 x 1.5 bytes로 약 3.1 MB이고, 30fps면 raw 데이터레이트가 약 746 Mbps입니다. 압축기가 이보다 많은 비트를 출력할 수는 없습니다.

실무 적용 가이드 ​

인코더 선택

상황선택이유
기존 인프라가 H.264만 지원libx264호환성, 튜닝 전 기준 대비 38.5% 절감으로도 충분한 이득
HEVC 지원 가능, 절감이 최우선libx26554.1% 절감, 동일 대역폭에서 더 많은 동시 시청자 수용
실시간 라이브 트랜스코딩libx264H.264 인코딩이 훨씬 가볍다, HEVC 실시간은 고사양 머신 필요
4K, 8K 아카이브libx265WPP 확장성과 HEVC 효율이 대용량에서 진가를 발휘

파라미터 튜닝

목표조정
더 높은 화질CRF 2~4 낮춤, preset +2 (더 무겁게)
더 낮은 비트레이트CRF 2~4 높임 (부작용: 화질 저하)
모바일 데이터 절약vbv-maxrate를 목표 네트워크 속도의 60~70%로, bufsize:maxrate 비율은 유지
seek 성능 향상keyint 축소(150 이하), 부작용으로 I-frame 증가
인코딩 속도 향상preset 낮춤(fast, veryfast), rc-lookahead 축소, threads/pool-threads 증설
라이브 지연 최소화rc-lookahead=0, keyint=fps x 2, open-gop=0, preset=fast 이하

정리 ​

  • libx264 템플릿은 909 kbps / VMAF 98.207, libx265 템플릿은 678 kbps / VMAF 98.629로, 튜닝 전 libx264 기준값(1,478 kbps / 97.858) 대비 각각 38.5%, 54.1% 비트레이트를 절감하면서도 화질은 더 높았습니다.
  • CRF 26(264)과 CRF 30(265)이 같은 화질인 건 CRF +6 = 비트레이트 절반이라는 경험칙과 HEVC의 40~50% 효율 우위가 겹친 결과입니다.
  • vbv-bufsize / vbv-maxrate 비율이 허용 버스트 시간입니다. 두 코덱 모두 2.0초로 동일하고, 절대값만 비트레이트에 맞춰 줄어듭니다.
  • 265의 keyint에 8의 배수 제약이 붙는 건 CTU(64x64) 구조와 WPP 스케줄링 때문입니다. threads와 pool-threads가 이름부터 다른 것도 병렬화 단위가 프레임과 CTU 행으로 다르기 때문입니다.
  • HEVC는 open-gop 기본 On, 계층적 B-frame 덕분에 rc-lookahead=0도 가능합니다. 대신 연산량이 5~10배라 preset 스펙트럼이 -1~10으로 더 넓습니다.

基于 VitePress 构建 · 部署于腾讯云 EdgeOne Pages