1편: https://yestomo.tistory.com/25
[O+T]: 영상 품질 측정하기 (1. 올바른 영상 변환과 품질 측정)
영상 트랜스코딩 - VMAF 품질 측정 과정을 거치며 마주한 문제를 해결하는 과정에 대해 적어놓은 글입니다. 문제 해결 중심으로 글이 전개되므로 영상에서 사용하는 개념에 대한 설명이 적게 들
yestomo.tistory.com
0. 개요
1편을 진행하기도 전.. 프로젝트를 막 시작했을 때, 팀원들과 영상에 대해 처음 공부하고 이것저것 알아보며 Per-Title-Encoding이라는 것을 알게 되었습니다. 프로젝트 기간에는 시간이 부족해서 완성하지 못했지만, 그때 논의했던 것들이 생각나 따로 공부해봤습니다.
영상 단위로 최적화하는 Per-Title-Encoding도 있고, 아예 장면 단위로 최적화를 진행하는 Per-Shot-Encoding도 있지만, 넷플릭스나 유튜브처럼 초대형 플랫폼이 아니라면 큰 의미가 있지는 않을 것이라고 생각했습니다.
1편에서는 트랜스코딩 결과물을 VMAF로 믿고 측정할 수 있게 만들고, 변환 시 기본적으로 갖춰야 할 요소들(정렬·CFR·GOP·매니페스트)을 보완했습니다. 그 과정에서 모든 영상의 VMAF 점수가 94~97점으로 높게 나타났습니다.
이번 2편에서는 그 기준선 위에서 '모든 영상에 같은 bitrate ladder를 쓰는 것이 정말 효율적인가?'를 따져보았습니다.
효과를 확실하게 살펴보고자 영상은 저/중/고 복잡도로 구분하여 3개 준비했고, 작업에 앞서 이번 작업의 최종 결과를 표로 먼저 정리해봤습니다.
| 영상 | 복잡도 | PTE 판단 | 결과 |
| Big Buck Bunny | 저복잡도 | 줄여도 됨 | 총 bitrate 36.1% 절감 |
| Meridian | 중복잡도 | 일부 절감 가능 | 총 bitrate 12.4% 절감 |
| Tears of Steel | 고복잡도 | 무리한 절감 부적합 | 총 bitrate 6.8% 증가, 품질 방어 |
PTE는 '압축률을 무조건 높이는 기술'이 아니라 영상별로 적절한 품질-용량 균형점을 찾는 과정이었음을 확인할 수 있었습니다.
1. Per-Title-Encoding 소개
영상 인코딩과 재생 시 사용되는 데이터의 양을 비트레이트라고 하며, 이에 따라 파일의 용량이 결정됩니다.
해당 프로젝트도 그렇고, 대부분의 영상 스트리밍 서비스에서는 영상을 S3같은 저장소에 저장하고, CDN을 사용하기도 합니다. 영상 자체가 대부분 크기가 매우 큰 파일이기 때문에 이 용량이 항상 비용과 직결됩니다. 따라서 품질에 이상이 없는 한 용량을 최대한 줄여 저장 공간을 효율적으로 사용할 필요가 있습니다.
전송 측면에서도 동일하게 적은 비트레이트로 충분한 영상에 많은 비트레이트를 할당하게 되면 전송량이 낭비될 수 있습니다.
이러한 문제를 해결하기 위해 영상별 최적화 방식인 Per-Title-Encoding을 도입해보기로 결정했습니다.
1-1. 기존 방식: 모든 영상에 같은 Ladder 사용

위 표는 넷플릭스에서 제시한 대부분의 영상에 적합한 해상도 x 비트레이트 조합입니다. 이를 바탕으로 기존 트랜스코딩 과정에서는 영상이 무엇이든 360p·720p·1080p에 고정 비트레이트(800·2400·4800k)를 주도록 구성했습니다. 어떤 영상이든 업로드되면 360p, 720p, 1080p를 만들고, 각 해상도에 고정된 bitrate를 적용합니다.
하지만, 영상마다 필요한 bitrate가 다르다는 점을 온전히 반영하지는 못합니다. 같은 1080p라도 영상이 단순하면 낮은 bitrate로도 충분하고, 영상이 복잡하면 더 많은 bitrate가 필요할 수 있습니다. 잔잔한 애니메이션과 장면 전환이 잦은 액션 영상에 같은 비트레이트를 주면 단순한 영상은 용량을 낭비하고 복잡한 영상은 품질이 떨어질 수 있습니다.
1-2. Per-Title-Encoding이란 무엇인가?
PTE(Per-Title Encoding)는 영상마다 최적의 비트레이트 ladder를 측정으로 결정하는 방법입니다. 한 영상을 여러 품질 후보로 인코딩해보고, 화질(VMAF)과 용량(비트레이트)을 함께 재서 가장 효율적인 지점을 고르는 것입니다.

PTE의 핵심은 '영상별 품질-용량 곡선'을 찾는 것입니다.
| 구분 | 기존 고정 ladder | PTE |
| 기준 | 모든 영상 동일 | 영상별로 다름 |
| 판단 | 해상도별 고정 bitrate | 후보별 bitrate-quality 측정 |
| 장점 | 단순, 운영 쉬움 | 영상별 최적화 가능 |
| 단점 | 쉬운 영상은 용량 낭비, 어려운 영상은 품질 부족 가능 | 후보 인코딩/측정 비용 증가 |
| 결과 | 하나의 공통 ladder | 영상마다 다른 ladder |
주의할 점은 용량을 줄이는 것이 목적이긴 하지만, 무작정 줄이면 안 된다는 점입니다. 적절한 품질을 유지하는 선에서 용량을 절감하는 것이 핵심입니다.
품질 지표로 사용되는 VMAF 6점당 1JND(사람이 눈으로 인식 가능한 품질 차이라고 하네요..!)라고 합니다. 이를 활용해서 JND 하락을 신경 쓰며 작업을 수행해야 합니다. 어쨌든 영상 플랫폼의 주 목적은 좋은 품질의 영상을 제공하는 것도 있기 때문입니다!
PTE는 단순히 bitrate를 줄이는 기술이 아닙니다. 더 정확히는 아래 내용을 자동화하는 과정입니다.
| 영상 상태 | PTE 판단 |
| 기존 bitrate가 과한 영상 | bitrate를 줄인다 |
| 기존 bitrate가 적절한 영상 | 유지하거나 일부만 줄인다 |
| 기존 bitrate가 부족한 영상 | 줄이지 않거나 오히려 품질을 방어한다 |
PTE의 목적은 '적절한 비트레이트'를 설정하여 모든 영상을 작게 만드는 것이 아니라, 영상별로 적절한 품질-용량 균형점을 찾는 것입니다.

PTE 작업은 위 흐름으로 이어집니다.
1-3. 가설
복잡도가 낮은 영상은 Bitrate가 적게 필요하고, 복잡도가 높은 영상은 상대적으로 Bitrate가 많이 필요할 것이라고 생각했습니다. 따라서 영상의 복잡도에 따라 절감되는 Bitrate 비율이 달라질 것이라고 생각했습니다. 특히, 고복잡도 영상의 고화질에서는 Bitrate 절감보다 영상 품질 방어를 위해 오히려 Bitrate를 더 사용할 수도 있습니다.
복잡도가 낮은 영상은 적은 bitrate로도 충분한 품질을 유지할 수 있고, 복잡도가 높은 영상은 같은 품질을 유지하기 위해 상대적으로 더 많은 bitrate가 필요할 것이라고 생각했습니다.
따라서 PTE를 적용하면 영상 복잡도에 따라 결과가 다르게 나올 것이라고 가정했습니다.
고복잡도 영상에서는 '얼마나 줄였는가'보다 '무리하게 줄이지 않는가'가 더 중요하다고 보았습니다. PTE가 단순한 용량 절감 기술이라면 고복잡도 영상에서도 억지로 bitrate를 낮추겠지만, 실제로 필요한 것은 영상별 품질-용량 균형점을 찾는 것입니다.
그래서 이번 실험에서는 다음 두 가지를 함께 확인했습니다.
| 확인할 것 | 의미 |
| Bitrate 변화 | 기존 고정 ladder보다 얼마나 줄거나 늘었는가 |
| VMAF 변화 | bitrate 변화 후 품질이 유지되는가 |
2. 대표 구간 추출
PTE는 영상을 여러 후보로 인코딩해 비교하는데, 영상 인코딩과 VMAF 측정은 영상 길이에 비례해 시간이 늘어납니다. 특히, VMAF는 원본과 후보 영상을 프레임 단위로 비교하기 때문에 후보 수가 늘어날수록 비용이 급격히 커집니다. 실제로 1시간 짜리 영상을 인코딩하고 VMAF 측정하는 데 각각 50분 이상 걸렸던 것으로 확인한 적이 있습니다.
그런데 후보는 해상도 × CRF 조합이라 수가 많고, 이걸 전체 영상마다 돌리면 매우 오랜 시간과 자원이 필요합니다. 그래서 전체를 대신할 대표 구간을 뽑아 인코딩과 VMAF 측정 시간을 줄이고, 이들을 통해 Ladder를 결정하기로 했습니다.
2-1. 대표 구간 정의
대표 구간은 하나의 '평균 장면'만 의미하지 않습니다. PTE에서는 쉬운 구간과 어려운 구간을 모두 봐야 합니다. 쉬운 구간만 보면 bitrate를 너무 많이 줄여도 된다고 오판할 수 있고, 반대로 어려운 구간만 보면 모든 영상을 지나치게 보수적으로 인코딩하게 되기 때문입니다.
그래서 이번 실험에서는 영상마다 5개 구간을 사용했습니다.
| 구간 | 의미 | 목적 |
| LOW | 복잡도가 낮은 구간 | 절감 가능성 확인 |
| AVERAGE_1 | 평균적인 구간 1 | 일반 품질 확인 |
| AVERAGE_2 | 평균적인 구간 2 | 평균 구간 편향 완화 |
| SCENE_CHANGE | 장면 전환이 뚜렷한 구간 | 전환 구간 품질 확인 |
| HIGH | 복잡도가 높은 구간 | 품질 붕괴 방지 |
대표 구간을 영상의 난이도 분포를 나눠서 보는 샘플로 구성하고자 했습니다.

2-2. 구간 분석 방식
해당 구간의 복잡도가 얼마나 되는지, 장면 전환은 어떻게 되는지 등을 사람이 확인할 수는 없었습니다. 많은 영상을 모두 할 수 없을 뿐더러 직접 고르면 기준이 흔들리고, 나중에 자동화하기 어렵기 때문입니다.
영상 분석 지표를 기준으로 구간을 분석했습니다.
| 지표 | 역할 | 사용 방식 |
| SI | 공간 복잡도, 디테일/질감 | FFmpeg로 영상을 디코딩하면서 프레임별 공간/시간 복잡도 계산 |
| TI | 시간 복잡도, 움직임 | |
| Scene Change Density | 장면 전환 구간 선택 | FFmpeg scene change 계열 필터로 컷 변화 감지 |
| Black Frame Ratio | 검은 화면/무의미 구간 제외 | FFmpeg blackdetect 계열로 검은 구간 감지 |
| Luma Mean | 극단적으로 어둡거나 밝은 무정보 구간 보조 판단 | FFmpeg signalstats 계열로 밝기 평균 확인 |
이 지표들을 이용해 각 구간의 복잡도를 계산했습니다.
대표 구간 추출 흐름

5단계를 거쳤으며, 각 단계에서 이상치를 줄이려고 노력했습니다. 구간들이 너무 붙어있거나 크레딧이나 의미 없는 장면이 대표 구간으로 선택될 수 있었고, 이들은 압축 난이도를 대표하기 어렵기 때문입니다.
2-3. 한계
대표 구간 방식은 전체 영상을 완전히 대체하지 않기 때문에 대표 구간 밖에서 품질이 무너질 가능성은 항상 남아 있습니다. 그래서 대표 구간은 후보 탐색에만 사용했고, 최종 선택된 ladder는 반드시 전체 영상으로 다시 검증했습니다.
대표 구간의 역할은 최종 판단이 아니라 탐색 비용 절감으로 후보 Ladder를 빠르게 찾는 것입니다.
3. 인코딩 조합 후보 생성 및 인코딩
영상마다 대표 구간 5개를 뽑은 후 이제 이 구간들을 실제 인코딩 후보로 펼쳐야 합니다. PTE에서 필요한 것은 '이 영상은 복잡하다/단순하다'는 판단이 아닌 실제로 여러 설정으로 인코딩했을 때, 각 설정이 어느 정도 bitrate와 품질을 만드는지입니다.
그래서 이 단계에서는 대표 구간을 해상도와 CRF 조합으로 인코딩해 후보군을 만들었습니다.
3-1. 후보 축 결정: 해상도 × CRF
후보는 해상도와 CRF 두 축으로 만들었습니다.
해상도는 360p/720p/1080p 3개로, CRF는 18/21/24/27/30 5개로 정했습니다. CRF 값이 낮을수록 화질이 좋고 bitrate가 커집니다. 해상도는 업스케일하지 않아 원본이 720p이라면 최대 제공 해상도는 720p로 설정됩니다.
CRF란?
CRF(Constant Rate Factor)는 목표 비트레이트가 아니라 목표 화질 수준을 정해 인코딩하는 방식입니다.
PTE에서 CRF를 쓴 이유는 영상마다 복잡도가 다르기 때문에 같은 bitrate로 후보를 찍는 것보다 CRF로 여러 화질 단계를 만들면 영상별 bitrate–quality 관계를 더 자연스럽게 관찰할 수 있기 때문입니다.
후보 생성 방식으로 고정 bitrate, 2-pass ABR, CRF, VMAF Target 방식을 검토했습니다. 고정 bitrate 방식은 ladder 제어가 쉽지만 영상별 복잡도를 반영하기 어렵고, 2-pass 방식은 목표 bitrate 정확도는 높지만 후보 수가 많은 PTE 실험에서는 인코딩 비용이 커집니다. VMAF Target 방식은 품질 기준이 명확하지만 반복 인코딩과 측정 비용이 큽니다.
따라서 초기 후보 생성 단계에서는 CRF를 사용해 동일한 화질 수준에서 영상 복잡도에 따라 자연스럽게 bitrate가 달라지도록 했고, 이후 각 후보의 실제 bitrate와 VMAF를 측정해 Convex Hull 기반으로 비효율 후보를 제거했습니다.
3-2. 후보 수
2장에서 선택한 대표구간은 영상마다 5개입니다.
각 구간마다 3개 해상도와 5개 CRF를 조합했습니다.
세 영상을 모두 실험했기 때문에 총 후보 수는 75 x 3 == 225개가 됩니다.

하지만, 그림처럼 이 75개가 그대로 최종 R-D Curve의 점이 되는 것은 아닙니다. 각 구간은 같은 해상도와 같은 CRF끼리 나중에 합산됩니다.
구간 인코딩 방식
처음에는 빠르게 진행하기 위해 5개 대표구간을 하나의 클립으로 이어붙인 뒤, 15개 후보만 인코딩하는 방식을 생각했습니다. 하지만, 구간을 이어붙이면 새로운 문제가 생길 수 있습니다.
| 문제 | 설명 |
| PTS 정렬 위험 | 구간마다 시간축이 끊기고 다시 붙으면서 PTS reset/offset 문제가 생길 수 있음 |
| 가짜 장면 전환 | 원래 이어지지 않는 장면을 붙이면서 인위적인 컷이 생김 |
| 원인 추적 어려움 | 특정 후보가 나쁠 때 어느 구간 때문인지 분리하기 어려움 |
이미 PTS 정렬 문제로 VMAF가 크게 흔들리는 것을 겪었습니다..ㅜㅜ...
따라서 PTE 후보 실험에서 다시 시간축 리스크를 만들 이유가 없었기에 구간을 이어붙이지 않고, 각 구간을 독립적으로 인코딩했습니다.
가장 큰 문제는 대표 구간에서 다른 대표 구간으로 이어지는 부분에 어색한 장면 전환이 발생할 것이라 생각했고, 이것이 점수에 영향을 줄 것이라고 판단했습니다.
3-3. 원본과 결과물 클립
VMAF 측정을 하려면 원본 역할을 하는 reference와, 인코딩 결과물인 distorted가 필요합니다.
이 단계에서는 먼저 대표구간마다 reference clip을 뽑아낸 후 reference clip을 해상도와 CRF 조합으로 인코딩해 distorted clip을 만들었습니다.
이렇게 한 이유는 정렬 안정성 때문입니다.
| 방식 | 문제 |
| 후보마다 원본에서 직접 seek | 매번 잘리는 위치가 미세하게 달라질 수 있음 |
| reference clip을 한 번 만들고 재사용 | 모든 후보가 같은 입력에서 파생되어 프레임 대응이 안정적 |

이 구조 덕분에 이후 VMAF 측정에서 '서로 다른 구간을 비교하는 문제'를 줄일 수 있었습니다!!
4. VMAF 기반 R-D Curve 그리기
이제 후보들의 VMAF 점수를 측정해서 R-D Curve의 점을 만들어야 합니다. 각 후보가 실제로 어느 정도 bitrate를 만들고, 어느 정도 품질을 내는지 파악하기 위함입니다.
'이 후보가 실제로 얼마나 많은 용량을 쓰는가'를 나타내는 bitrate와 '이 후보가 원본 대비 어느 정도 품질을 유지하는가'를 나타내는 VMAF 점수를 축으로 그래프 위에 점을 찍어 bitrate-quality 관계를 보고자 했습니다. 이 곡선은 bitrate가 증가할 때 품질이 어떻게 좋아지는지 나타내며, R-D Curve(Rate-Distortion Curve)라고 부른다고 합니다!!
원본에 맞춰 VMAF 측정
1편에서는 HLS 결과물이 원본 대비 얼마나 잘 유지됐는지 보기 위해, 원본을 HLS 해상도로 낮춰 비교하는 Downscale VMAF를 사용했습니다.
하지만 PTE에서는 서로 다른 해상도인 360p, 720p, 1080p 후보끼리 비교해야 합니다. 이때, 각 후보를 자기 해상도에서만 비교하면 해상도 간 비교가 불가능해집니다.
예를 들어 360p 후보는 원본을 360p로 낮춰 비교하고, 1080p 후보는 원본을 1080p로 낮춰 비교한다고 하면 신뢰할 수 없는 결과가 나타날 수 있습니다.
PTE에서는 실제 사용자가 보는 화면 기준에서 후보들을 비교해야 합니다. 그래서 후보들을 공통 기준 해상도로 올려 비교했습니다. 해당 프로젝트의 정책으로 설정한 최대 품질인 1080p을 상한선으로 두고 후보들을 1080p 기준으로 비교했습니다. 물론 업스케일을 진행하지 않기 때문에 정확히는 1080p을 넘지 않는 한에서 원본과 1080p 중 더 낮은 것을 원본 기준으로 삼았습니다.
4-1. 왜 R-D Curve가 필요한가?
PTE는 여러 후보 중 VMAF가 가장 높은 것을 고르는 작업이 아닙니다. VMAF가 가장 높은 후보는 보통 bitrate도 가장 큽니다. 예를 들어 CRF 18은 품질은 좋지만 용량이 커질 가능성이 높습니다. 반대로 CRF 30은 용량은 작지만 품질이 떨어질 수 있습니다.
그래서 '어느 지점부터 bitrate를 더 써도 품질 개선이 크지 않은가?'에 대한 판단이 필요합니다.
예를 들어 아래와 같은 후보가 있다고 가정할 수 있습니다.
| 후보 | bitrate | VMAF |
| A | 1000k | 88 |
| B | 2000k | 94 |
| C | 4000k | 95 |
A에서 B로 가면 bitrate는 1000k 늘고 VMAF는 6점 오릅니다. 하지만, B에서 C로 가면 bitrate는 2000k나 늘었는데 VMAF는 1점만 오릅니다. 이 경우 C는 품질은 조금 더 좋지만, 효율은 낮을 수 있습니다.
R-D Curve는 그래프를 통해 이러한 판단이 가능하도록 도와줍니다.

4-2. 후보 75개를 R-D 점 15개로 바꾸기
영상마다 75개의 해상도-비트레이트 조합 후보가 존재합니다. 하지만, R-D Curve에서 보고 싶은 것은 '각 구간의 점'보다 '이 영상에서 720p CRF24는 어느 정도 효율인가?'입니다.
그래서 같은 해상도와 같은 CRF끼리 5개 구간을 합쳤습니다.
합산 방식
R-D Curve의 각 점은 bitrate와 VMAF를 가져야 합니다.
bitrate는 CRF 값으로 추정하기보다 5개 구간의 실제 인코딩 결과를 합쳤고, VMAF은 5개 구간의 평균 품질로 계산했습니다.

평균 VMAF가 높아도 특정 구간 하나가 크게 무너지면 실제 시청 품질은 나쁠 수 있습니다.
그래서 이후 후보 선택 단계에서 worst segment와 P5 같은 하위 지표도 함께 확인할 수 있도록 기록했습니다.
4-3. 측정 결과
R-D Curve를 그려보니, 처음 예상처럼 단순히 저복잡도 영상은 항상 효율이 좋고, 고복잡도 영상은 항상 효율이 나쁘다로 정리되지는 않았습니다. 사용자 체감을 나타내는 VMAF를 사용하는 만큼 영상의 특성이 반영되었습니다.
BBB
저복잡도 영상에서는 낮은 bitrate에서도 품질이 잘 유지될 것이라고 예상했고, 실제로 1080p에서는 그 경향이 뚜렷했습니다. 실제로 CRF30에서 CRF24까지는 bitrate를 늘릴수록 VMAF가 의미 있게 상승했지만, CRF24 이후부터는 증가폭이 줄어듭니다.

BBB는 일정 수준 이후부터 bitrate를 더 써도 VMAF가 크게 오르지 않았습니다. 이 곡선은 기존 고정 ladder가 다소 보수적이었고, bitrate를 줄일 여지가 있다는 신호로 볼 수 있습니다. 전반적으로 비트레이트 효율이 꽤 높게 나타나는 것으로 분석할 수 있습니다.
다만, 360p에서는 VMAF가 낮게 나왔습니다. 이는 저복잡도 영상이라도 4K 애니메이션의 선명한 경계와 디테일이 360p로 줄어든 뒤 1080p 기준으로 비교되면 손실이 크게 반영되기 때문입니다.
Meridian
중간 복잡도 영상에서는 저복잡도 영상보다 더 많은 bitrate가 필요할 것이라고 예상했습니다. 하지만 R-D Curve에서 예상과 다른 부분이 있었습니다. 오히려 BBB보다 낮은 bitrate로 비슷한 VMAF에 도달했습니다.

Meridian이 BBB보다 더 효율적이지만, Meridian이 전체적으로 더 쉬운 영상이라는 뜻은 아닙니다.
Meridian은 어두운 SF로, 화면에 검은 영역이 많은 영상입니다. 검은 부분은 압축 비용이 저렴해서 적은 비트레이트로도 인코딩이 가능했기 때문에 예상했던 BBB와 Tears 사이로 나타나지 않은 것입니다.
Meridian은 낮은 구간에서 비트레이트 효율이 매우 높게 나타난 대신, 천장이 좀 낮고 높은 해상도 구간에서의 효율은 조금 낮다고 분석할 수 있습니다.
이는 복잡도 라벨과 VMAF 효율이 완전히 같은 개념이 아니기 때문입니다. Meridian은 실사 영상이지만 중간 품질대에서는 압축 손실이 VMAF에 덜 불리하게 나타났고, BBB는 애니메이션 특유의 선명한 경계와 디테일 손실이 VMAF에 더 민감하게 반영되었습니다.
또한, BBB는 약 3.6Mbps에서 VMAF 95.76까지 올라갔지만, Meridian은 약 4.3Mbps를 사용해도 VMAF 94.17에 머물렀습니다. Meridian의 곡선은 중간 품질대까지는 빠르게 올라가지만, 고품질 구간에서는 빨리 둔화되는 모습을 보입니다.
Tears
고복잡도 영상에서는 VFX, 장면 변화, 디테일이 많기 때문에 같은 품질을 유지하려면 더 많은 bitrate가 필요할 것이라고 예상했고, R-D Curve도 이 방향을 보여줬습니다. 같은 CRF24 기준으로 BBB 1080p는 약 3.6Mbps에서 VMAF 95.76이었지만, Tears는 약 4.8Mbps를 사용해도 VMAF 95.56으로 비슷한 품질에 머물렀습니다.

Tears는 같은 품질을 얻기 위해 BBB보다 더 많은 bitrate가 필요했습니다. 특히 360p와 720p에서는 낮은 bitrate로 줄이면 품질 하락이 커져, 단순 절감보다 품질 방어가 더 중요한 영상으로 볼 수 있습니다.
다만, 1080p에서는 CRF24 근처에서 VMAF 95점대를 확보했기 때문에, 고화질 구간은 무조건 bitrate를 늘리는 것이 아니라 품질을 유지하는 선에서 일부 절감 여지도 있었습니다.
한 번에 보기

세 영상의 그래프를 한 번에 보고 주요 포인트를 뽑아봤습니다.
- VMAF 95 라인 교차:
- BBB ≈ 3,600k / Tears ≈ 4,800k / Meridian 도달 불가.
- → 같은 95점을 만드는 비용이 영상마다 다름.
- 곡선 교차(~2,500k 부근): 저비트레이트에선 Meridian이 위(효율적)지만, 그 지점을 지나면 천장에 막혀 BBB·Tears가 추월. '저비트레이트 효율 ≠ 고품질 가능'을 한 그림이 보여줌.
- 수확 체감(무릎): 세 곡선 다 초반 급상승 → 90 부근부터 완만. 특히 95 위로는 비트레이트를 크게 써도 거의 안 오름.
PTE와의 연결
- BBB: 95를 baseline(5,069k)보다 싸게(3,638k) 달성 → 절감
- Tears: 95에 4,800k 필요 ≈ baseline(5,157k) → 더 못 깎음 → 방어
- Meridian: 1080p 천장 94 ≈ baseline(4,165k, 94.46) → 1080 유지, 곡선이 낮은 360/720만 절감
5. 후보 추리고 해상도별 Ladder 선택하기
이제 필요한 것은 위에서 그린 점들 중에서 실제 ladder 후보로 볼 만한 점만 남기는 것입니다.
후보는 많지만, 모든 후보가 의미 있는 것은 아닙니다. 어떤 후보는 더 많은 bitrate를 쓰면서도 VMAF가 낮기도 한데, 이런 후보는 실제 서비스 ladder에 들어갈 이유가 없습니다.
저는 Pareto 지배 제거와 Convex Hull이라는 두 단계를 거쳐 후보를 줄였습니다.
5-1. Pareto 지배 제거
먼저 Pareto 기준으로 명백히 비효율적인 후보를 제거했습니다.

A 후보가 B 후보보다 bitrate는 낮거나 같고,VMAF는 높거나 같다면 B 후보는 선택할 이유가 없습니다. 같은 품질이면 더 작은 파일이 좋고, 같은 bitrate면 더 높은 품질이 좋습니다.
예를 들어 아래와 같은 후보가 있다고 하면
| 후보 | Bitrate | VMAF |
| A | 2,000kbps | 92 |
| B | 2,400kbps | 91 |
B는 A보다 bitrate를 더 쓰면서 VMAF는 낮습니다. 따라서 B는 제거할 수 있습니다.
Pareto 제거 후 남은 후보 수는 다음과 같습니다.
| 영상 | 전체 R-D 점 | Pareto 통과 |
| BBB | 15 | 11 |
| Meridian | 15 | 12 |
| Tears | 15 | 12 |
업스케일해서 비교했고, 이 단계의 목적은 최종 후보를 고르는 것이 아니라 명백히 손해인 후보를 먼저 제거하는 것이기 때문에 해상도 간 교차 비교가 가능했습니다.
5-2. Convex Hull
Pareto 제거 후에도 후보가 여전히 많이 남았습니다. Pareto 후보는 '명백히 나쁘지는 않은 점'일 뿐 모두 효율적인 점은 아니므로 다음 단계로 Convex Hull을 사용했습니다.
Convex Hull은 R-D Curve에서 품질 대비 bitrate 효율이 좋은 바깥 경계선을 찾는 과정입니다. 쉽게 말하면, 여러 점 중에서 실제 효율 곡선을 만드는 점만 남기는 것입니다.

세 점을 연결시켜 기울기를 비교합니다. 왼쪽 점부터 시작해서 점1-점3의 기울기보다 점1-점2의 기울기가 작다면(완만함) 효율이 낮다는 뜻이고, 기울기가 크다면(가파름) 효율이 좋다는 뜻입니다.
점 세 개를 이었을 때 기울기가 '가파름-완만함'이면 가운데 점의 효율이 좋고, '완만함-가파름'이면 가운데 점의 효율이 좋지 않다고 정리할 수 있습니다.
여러 점을 이어보면 아래처럼 Pareto, Convex Hull을 그래프로 확인할 수 있습니다.

판단 순서를 아래 5단계로 정리해보았습니다.
1. Pareto 통과 점들을 bitrate 낮은 순서로 정렬한다.
2. 왼쪽부터 점을 하나씩 이어 선을 만든다.
- 이웃한 점 사이의 기울기로, 비트레이트를 더 쓸 때 VMAF가 얼마나 오르는 지 확인하기 위함이다.
3. 새 점을 이었을 때, 가운데 점이 그 선보다 아래에 있으면 제거한다.
4. 이걸 끝까지 반복한다.
5. 남은 점들이 bitrate를 더 쓸 가치가 있는 효율 경계선이다.
위 순서로 Convex Hull까지 적용한 결과는 다음과 같습니다.
| 영상 | 전체 R-D 점 | Pareto 통과 | Convex Hull |
| BBB | 15 | 11 | 8 |
| Meridian | 15 | 12 | 10 |
| Tears | 15 | 12 | 10 |
15개의 후보 점 중에서 실제 ladder 선택에 참고할 효율 후보는 영상별로 8~10개 정도로 줄었습니다.
5-3. 왜 Pareto만으로는 부족한가?
Pareto만 적용하면 “명백히 손해인 후보”는 제거할 수 있습니다. 하지만 효율이 애매한 후보는 남습니다.
예를 들어 어떤 후보가 아래처럼 있을 때,
| 후보 | Bitrate | VMAF |
| A | 1,000kbps | 88 |
| B | 1,500kbps | 90 |
| C | 2,000kbps | 91 |
C는 B보다 bitrate도 높고 VMAF도 높기 때문에 Pareto 기준으로는 제거되지 않습니다. 하지만 B에서 C로 갈 때 bitrate는 500kbps 늘었는데 VMAF는 1점만 올랐습니다. 이 경우 C가 무조건 나쁘다고 할 수는 없지만, 효율이 좋은 지점인지는 따져봐야 합니다. Convex Hull은 이런 후보를 효율선 기준으로 다시 걸러줍니다.
정리하면 Pareto는 더 많이 쓰고도 더 나쁜 후보를 제거하는 것이고, Convex Hull은 남은 후보 중 효율선 안쪽에 있는 후보를 제거하는 것입니다.
5-4. 해상도별 ladder 선택
Pareto와 Convex Hull로 후보를 줄인 뒤에도 바로 최종 ladder가 정해지지는 않습니다.
실제 스트리밍 ladder는 360p, 720p, 1080p처럼 해상도별 rung이 필요합니다. 따라서 최종 선택은 전체 R-D Curve에서 효율적인 후보를 보되, 각 해상도별로 하나씩 선택해야 합니다.
저는 아래와 같은 기준으로 선택했습니다.
1. baseline(PTE 적용 x) 품질을 크게 해치지 않을 것
2. 가능하면 더 낮은 bitrate를 선택할 것
3. 품질이 부족한 영상은 bitrate를 줄이지 말고 방어할 것
4. 각 해상도별 ladder를 유지할 것
무조건 bitrate를 줄이는 것이 아니라, 영상별로 판단했으며, 아래와 같이 정리했습니다.
| 상황 | 선택 방향 |
| 기존 bitrate가 과한 경우 | 더 낮은 bitrate 후보 선택 |
| 기존 bitrate가 적절한 경우 | 비슷한 품질의 최소 bitrate 선택 |
| 기존 bitrate가 부족한 경우 | bitrate를 늘려 품질 방어 |
결정된 영상 & 해상도 Ladder
| 영상 | 360p | 720p | 1080p | 선택 결과 |
| BBB | CRF24 | CRF24 | CRF24 | 세 해상도 모두 bitrate 절감 |
| Meridian | CRF18 | CRF18 | CRF18 | 360p/720p 절감, 1080p 유지 |
| Tears | CRF21 | CRF21 | CRF24 | 360p/720p 품질 방어, 1080p 소폭 절감 |
BBB는 CRF24에서도 baseline 대비 품질 하락이 JND 미만으로 유지되어, 세 해상도 모두 절감 후보로 선택되었습니다.
Meridian은 360p/720p는 절감 가능했지만, baseline 품질과의 차이를 줄이기 위해 후보 중 가장 높은 품질인 CRF18을 선택했고 1080p는 거의 유지에 가까웠습니다.
Tears는 360p/720p는 기존 bitrate가 부족해 CRF21로 품질을 방어했고, 1080p만 CRF24에서 품질 유지와 소폭 절감 가능합니다.
6. Per-Title-Encoding 적용 전/후 비교
최종으로 선택한 ladder를 실제 전체 영상에 적용해 검증했습니다.
앞 단계까지는 대표 구간 5개를 기반으로 후보를 비교했지만, 대표 구간에서 좋아 보인 선택이 전체 영상에서도 유지되는지는 별도로 확인해야 합니다. 그래서 최종 ladder만 전체 영상으로 인코딩한 뒤, baseline과 같은 조건으로 VMAF를 다시 측정했습니다.
고정 Ladder로 인코딩한 결과와 PTE를 적용한 선택 Ladder 결과의 전체 영상을 1080p로 업스케일하여 VMAF 측정했습니다. 품질에 대한 판단은 Baseline 대비 VMAF 변화량이고, 용량에 대한 판단은 Bitrate 변화량으로 진행했습니다.
6-1. 전체 결과
결과는 영상별로 명확하게 나타났습니다.
비트레이트 비교

모든 영상에서 bitrate가 줄어든 것은 아니고, 영상의 성격에 따라 결과가 달라졌습니다.
BBB → 기존 ladder가 과해서 크게 줄일 수 있음
Meridian → 일부 줄일 수 있지만 고화질 구간은 유지에 가까움
Tears → 기존 ladder가 부족해 일부 해상도는 오히려 늘려야 함
이 결과가 무조건 bitrate를 줄이는 작업이 아니라, 영상마다 적절한 품질-용량 균형점을 찾는 작업인 PTE의 핵심을 잘 보여줍니다.
VMAF 비교

품질 변화가 전부 JND(±6) 이내로 나타났습니다. 고정 래더에서 목표 품질 달성에 부족했던 건 품질을 높였고, 품질에 여유가 있었던 건 품질을 낮추어 용량을 줄이는 방안으로 진행되었습니다.
6-2. BBB 결과
BBB는 저복잡도 영상으로, 가장 큰 절감 효과가 나왔습니다.
| 해상도 | Baseline bitrate | PTE bitrate | 변화율 | Baseline VMAF | PTE VMAF | VMAF 변화 |
| 360p | 959k | 602.5k | -37.2% | 65.76 | 62.09 | -3.67 |
| 720p | 2641k | 1747.6k | -33.8% | 90.95 | 88.68 | -2.27 |
| 1080p | 5069k | 3185.9k | -37.2% | 96.72 | 95.17 | -1.55 |
BBB는 세 해상도 모두 CRF24가 선택되었습니다. 전체 bitrate는 약 36.1% 줄었고, VMAF 하락은 모두 JND 기준인 6점 이내였습니다.
특히, 1080p는 bitrate를 약 37% 줄였지만 VMAF는 1.55점만 낮아졌습니다. 기존 고정 ladder가 BBB에는 다소 과하게 잡혀 있었던 것이고, 품질을 크게 해치지 않으면서 bitrate를 줄일 수 있었습니다.
6-3. Meridian 결과
Meridian은 중간 복잡도 영상으로, 일부 절감 효과가 나왔습니다.
| 해상도 | Baseline bitrate | PTE bitrate | 변화율 | Baseline VMAF | PTE VMAF | VMAF 변화 |
| 360p | 862k | 490.1k | -43.1% | 75.55 | 73.88 | -1.67 |
| 720p | 2215k | 1682.5k | -24.0% | 90.59 | 90.13 | -0.46 |
| 1080p | 4165k | 4171.3k | +0.15% | 94.46 | 94.65 | +0.19 |
Meridian은 세 해상도 모두 CRF18이 선택되었습니다. 360p와 720p에서는 bitrate가 줄었지만, 1080p는 baseline과 거의 같은 수준으로 유지되었습니다.
즉 Meridian은 “무조건 크게 줄일 수 있는 영상”은 아니었습니다. 낮은 해상도에서는 절감 여지가 있었지만, 고화질 구간에서는 기존 ladder가 이미 적정에 가까웠습니다.
6-4. Tears 결과
Tears는 고복잡도 영상으로, 전체 bitrate가 오히려 증가했습니다.
| 해상도 | Baseline bitrate | PTE bitrate | 변화율 | Baseline VMAF | PTE VMAF | VMAF 변화 |
| 360p | 960k | 1182k | +23.1% | 67.71 | 73.33 | +5.62 |
| 720p | 2645k | 3467k | +31.1% | 90.69 | 93.31 | +2.62 |
| 1080p | 5157k | 4704k | -8.8% | 95.52 | 95.40 | -0.12 |
ears는 360p와 720p에서 bitrate가 증가했습니다. 이는 실패라기보다, 기존 고정 ladder가 이 영상의 낮은 해상도 품질을 충분히 방어하지 못했다는 의미입니다.
반면 1080p에서는 bitrate를 약 8.8% 줄이면서도 VMAF는 거의 유지되며, 해상도별로 판단이 달랐습니다.
6-5. 대표 구간은 신뢰성이 있었는가?
앞선 단계에서 전체 영상을 전부 후보 탐색하지 않고, 대표 구간 5개로 후보를 고른 뒤 최종 ladder만 전체 영상으로 검증했습니다. 이에 따라 대표 구간의 신뢰성도 검증할 필요가 있었습니다.
| 영상 | 해상도 | 대표 구간 예측 VMAF | 전체 영상 VMAF | 차이 |
| BBB | 360p | 60.59 | 62.09 | +1.50 |
| 720p | 90.38 | 88.68 | -1.70 | |
| 1080p | 95.76 | 95.17 | -0.59 | |
| Meridian | 360p | 74.40 | 73.88 | -0.52 |
| 720p | 89.93 | 90.13 | +0.20 | |
| 1080p | 94.17 | 94.65 | +0.48 | |
| Tears | 360p | 72.36 | 73.33 | +0.97 |
| 720p | 93.72 | 93.31 | -0.41 | |
| 1080p | 95.56 | 95.40 | -0.16 |
결과는 대체로 신뢰성 있는 대표 구간임이 나타났습니다. 모든 차이가 대략 ±1.7점 안에 들어왔고, 대표 구간 기반의 판단이 전체 영상에서도 크게 벗어나지 않았습니다.

y=x 그래프를 예측 = 실측으로 두고 점을 찍어 확인해보면 크게 벗어나지 않는 것을 확인할 수 있습니다.
7. 마무리
영상 처리를 접해본 적이 없어서 팀 프로젝트 기간 동안 회의를 정말 많이 했었는데, 기획을 좀 줄이고 아예 이러한 부분을 팀원들과 함께 더 깊게 공부해봤으면 좋았겠다는 아쉬움이 있습니다.
영상하면 역시 넷플릭스가 떠올라서 기술 블로그도 종종 봤었는데, 하나같이 다 거대하고 어려워서 프로젝트에 적용하기엔 어려웠습니다. 참고한 글도 처음엔 난해하고 어려웠는데, 지하철 오가며 여러 번 반복해서 보니까 좀 익숙해지는 것 같았습니다.
테스트를 정말 많이 했습니다. 부하 테스트나 쿼리 돌려보는 건 많이 해보기도 했고 익숙했는데, 이렇게 직접 가설을 세우고 뽑아낼 수치를 정하고, 비교군을 설정하여 계속해서 숫자를 만들어가는 건 조금 낯설었습니다. 하지만, 이 과정에서 작업의 목적과 제가 확인하고 싶은 게 무엇인지 여러 번 생각해 볼 수 있어 방향을 잃지 않았던 것 같습니다.
역시나 실제 결과로 확인하는 게 정말정말 중요한 것을 느꼈습니다!
참고 자료: https://netflixtechblog.com/per-title-encode-optimization-7e99442b62a2
Per-Title Encode Optimization
delivering the same or better experience while using less bandwidth
netflixtechblog.com
'Project' 카테고리의 다른 글
| [O+T] 영상 이어보기 처리량 개선하기 (0) | 2026.05.13 |
|---|---|
| [O+T] 홈 화면 인기 플레이리스트 API 개선하기 (0) | 2026.05.09 |
| [O+T] 테스트 준비하기 (2) | 2026.04.28 |
| 다중 기기 환경에서의 푸시 알림 (0) | 2025.04.03 |
| 상황별 조회수 성능을 위해 고려할 수 있는 것 (0) | 2025.04.01 |