libx264와 libx265 파라미터 비교: CRF, VBV, 스레딩 실측 데이터
CRF 26과 CRF 30이 같은 화질이라면 처음 들었을 때는 앞뒤가 맞지 않는 이야기로 들립니다. 숫자를 먼저 보고 거꾸로 파라미터를 뜯어보겠습니다.
먼저 숫자부터: 같은 원본, 세 가지 설정의 실측 결과
같은 1080p 원본을 세 가지 설정으로 인코딩했습니다. 목표는 하나였습니다. libx264 기본 설정 대비 비트레이트를 얼마나 줄이면서 화질을 지킬 수 있는가였습니다.
| 인코더 | 출력 비트레이트 | VMAF | vs 기준 절감 |
|---|---|---|---|
| libx264 (기준값) | 1,478 kbps | 97.858 | (기준) |
| libx264 (템플릿) | 909 kbps | 98.207 | -38.5% |
| libx265 (템플릿) | 678 kbps | 98.629 | -54.1% |
여기서 기준값은 튜닝 없이 인코딩한 libx264 결과이고, 템플릿은 이 글에서 다룰 CRF와 VBV, preset 등을 조정한 설정입니다.
눈여겨볼 지점은 비트레이트가 아니라 VMAF가 함께 올랐다는 사실입니다. 보통 절감율을 높이면 화질은 내려갑니다. 그런데 678 kbps 설정이 1,478 kbps 기준값보다 높은 점수를 받았습니다. 절반 이하의 비트로 더 높은 점수를 낸 셈입니다.
참고: VMAF는 업계에서 널리 쓰이는 객관적 화질 평가 지표입니다. 0에서 100 스케일이고 통상 93점 이상부터 일반 시청자가 원본과 구분하지 못하므로, 98.6점은 프로덕션 마스터 급입니다.
두 줄의 명령어가 먼저 보여주는 것
같은 파이프라인, 같은 오디오 설정인데 비디오 파라미터는 이렇게 달랐습니다.
# 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# 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 올라갈 때마다 비트레이트는 대략 절반이 됩니다.
그럼 왜 264는 26, 265는 30일까요. 두 사실을 겹치면 답이 나옵니다.
- CRF +6은 비트레이트 절반과 같습니다
- HEVC는 H.264 대비 동일 화질에서 40~50% 낮은 비트레이트를 냅니다
즉 HEVC 쪽에서 CRF를 4~6 올려도 눈에 보이는 화질은 유지되고, 대신 비트레이트가 확 줄어듭니다.
| 설정 | 비트레이트 | VMAF |
|---|---|---|
| libx264 CRF 26 | 909 kbps | 98.207 |
| libx265 CRF 30 | 678 kbps | 98.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은 사실 같은 설정이다
| 항목 | libx264 | libx265 |
|---|---|---|
| vbv-maxrate | 3000 | 2000 |
| vbv-bufsize | 6000 | 4000 |
| bufsize / maxrate | 2.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 범위 | 템플릿 값 |
|---|---|---|
| libx264 | 0(ultrafast) ~ 9(placebo) | slow (=5) |
| libx265 | -1(ripping) ~ 10(ultrafast) | 3 |
H.265의 연산 비용이 H.264의 5~10배이기 때문입니다. CTU 가변 블록 분할, 35개 인트라 예측 방향, 더 정교한 움직임 보상, SAO 필터가 추가되면서 연산 스펙트럼 자체가 넓어졌습니다. 그만큼 다이얼도 넓어야 합니다.
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를 쿼드트리로 재귀 분할합니다.
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)
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 threads | H.265 pool-threads |
|---|---|---|
| 범위 / 기본값 | 0~128, 자동(코어 수) | 0~256, 자동(코어 수) |
| 병렬화 단위 | 프레임 | CTU 행(row) |
| 스레드 간 의존성 | 앞 프레임 완료를 기다림 | 윗 행이 2 CTU 앞서면 바로 시작 |
| 확장성 | 스레드 수만큼 지연, 화질 저하 가능 | 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)로, 완전히 다른 병렬화 아키텍처입니다.
종합 비교표
| 파라미터 | libx264 | libx265 | 차이의 근본 원인 |
|---|---|---|---|
| preset | 0~9 (slow=5) | -1~10 (3) | HEVC 연산량이 5~10배라 더 넓은 스펙트럼이 필요, ripping(-1)은 극한 압축 모드 |
| crf | 0~51, 템플릿 26 | 1~51, 템플릿 30 | CRF +6 = 비트레이트 절반, HEVC의 40~50% 효율 우위로 CRF를 4~6 올려도 동일 화질. 265는 무손실이 별개 파라미터(lossless)라 시작값이 1 |
| vbv-maxrate / vbv-bufsize | 3000 / 6000 | 2000 / 4000 | 출력 비트레이트가 낮으니 VBV도 비례 축소, 비율(2:1 = 2.0초 버스트)은 동일 유지 |
| rc-lookahead | 1~250 | 0~250 | HEVC의 계층적 B-frame이 lookahead 없이도 비트 분배를 어느 정도 최적화 |
| open-gop | 없음 | 있음 (기본 On) | HEVC 표준에 정식 포함, GOP 경계 예측으로 압축 효율 향상 |
| keyint | 0~100,000, 기본 256 | 0~100,000, 기본 256, 제약 50 초과 및 8의 배수 | CTU(64x64) 구조가 GOP 경계의 8프레임 정렬을 요구, WPP 스케줄링과 연관 |
| bitrate 상한 | 고정 2,000,000 kbps | yuv_size x fps 이하 | HEVC는 물리적으로 raw 데이터레이트를 초과할 수 없어 동적 상한을 둠 |
| threads / pool-threads | 0~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 지원 가능, 절감이 최우선 | libx265 | 54.1% 절감, 동일 대역폭에서 더 많은 동시 시청자 수용 |
| 실시간 라이브 트랜스코딩 | libx264 | H.264 인코딩이 훨씬 가볍다, HEVC 실시간은 고사양 머신 필요 |
| 4K, 8K 아카이브 | libx265 | WPP 확장성과 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으로 더 넓습니다.