FFmpeg

FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created

FFmpeg는 인간과 기계가 만들어낸 거의 모든 것을 디코딩/인코딩, 트랜스코딩, 먹스/디먹스, 스트림, 필터링 및 재생할 수 있는 선도적인 멀티미디어 프레임워크입니다.

FFmpeg about

동영상 편집에서 FFmpeg는 오픈소스로 이루어진 표준 프로그램입니다. 동영상 관련 프로그램을 만들면 꼭 FFmpeg가 끼게 되더군요. 이번에 만드는 사이트 최적화를 위해 테스트와 벤치마크를 진행했으며, 그 과정을 정리합니다.

로컬 테스트

다음 흐름으로 벤치마크 코드를 작성해, CRF 1826·비트레이트 4M10M·프리셋 4종 조합(총 40케이스)으로 HLS 인코딩 옵션을 바꿔 가며 출력 용량과 VMAF 점수를 비교해 최적 값을 도출해 봤습니다. 최종 목적은 강좌 공유 사이트에서 PPT로 보여주는 글자가 뭉개지지 않으며 적당히 높은 화질로 HLS 영상을 뽑아내는 것입니다.

옵션

  • CRF(Constant Rate Factor): 화질 기준 인코딩 방식으로 압축 품질을 선택할 수 있습니다. 숫자가 낮을수록 화질이 좋고 용량이 커지며, 영상 내용에 따라 비트 수를 조절해 사용합니다. 비트 조절 기준은 픽셀 단위에서 이루어지는 색 변화량에 비례합니다.
    • CRF 18 → 고화질, 큰 용량
    • CRF 22 → 적당한 화질/용량 균형
    • CRF 26 → 낮은 용량, 품질 저하 가능
  • 비트레이트(bitrate): 초당 사용할 비트 양을 제한합니다.
  • 프리셋(preset): x264 인코더가 얼마나 오래 고민해서 압축할지를 정하는 옵션입니다.
    • veryfast → 빠르게 인코딩, 용량 효율 낮음
    • fast → 빠른 편, 품질/용량 조금 개선
    • medium → 기본값, 균형 좋음
    • slow → 느림, 용량 효율 좋음
    • ※ 같은 비트레이트 기준이면 느린 프리셋이 더 좋은 화질을 나타낼 수 있습니다.
  • VMAF: FFmpeg의 옵션이 아닙니다. VMAF는 Netflix가 만든 영상 품질 평가 지표로, 편의상 이를 토대로 점수를 측정했습니다.

이제 아래 흐름의 테스트 코드로 Jitsi로 녹화한 강의 영상을 기준으로 테스트를 돌려 봤습니다.

flowchart TD A["원본 영상"] --> B["5분 샘플 생성"] B --> C["고품질 기준 영상 생성"] C --> D["옵션 선택"] D --> D1["CRF 옵션<br/>18, 20, 22, 24, 26"] D --> D2["비트레이트 옵션<br/>4M, 5M, 6M, 8M, 10M"] D --> D3["인코딩 프리셋<br/>veryfast, fast, medium, slow"] D1 --> E["HLS 인코딩"] D2 --> E D3 --> E E --> F["인코딩 시간 측정"] E --> G["출력 용량 측정"] E --> H["세그먼트 개수 측정"] F --> I["VMAF 점수 측정"] G --> I H --> I I --> J["결과 CSV 저장"] J --> K["HTML 리포트 생성"] K --> L["옵션별 비교"] L --> L1["화질 점수 비교"] L --> L2["인코딩 시간 비교"] L --> L3["파일 용량 비교"] L --> M["추천 옵션 선정"] M --> M1["VMAF mean·p5 기준<br/>가장 작은 용량"] M --> M2["VMAF mean 95 이상<br/>용량 대비 효율"]

위 프로세스의 테스트 코드로 값을 도출하면 아래와 같습니다. 전체적으로 시간이 많이 소요된 원인은 VMAF 측정 때문입니다. 컬럼별 특징은 다음과 같습니다.

  • mode: 인코딩 방식
  • preset: 속도/압축 효율 옵션
  • crf_value: crf 인코딩의 화질 기준값
  • target_bitrate: bitrate 인코딩의 목표 비트레이트
  • encode_seconds: 인코딩 시간(참고 지표. 테스트 PC의 병렬 실행·시스템 부하에 따라 변동될 수 있음)
  • total_seconds: 전체 처리 시간(VMAF 측정 포함)
  • output_size: 결과 파일 크기
  • measured_bitrate: 실제 측정 비트레이트
  • vmaf_mean: 평균 품질
  • vmaf_p5: 하위 5% 품질
  • vmaf_min: 최저 품질

인코딩 시간은 병렬 실행 환경과 시스템 부하에 따라 변동될 수 있으므로, 이번 비교에서는 참고 지표로만 사용하는 것이 좋다고 판단했습니다. 로컬 PC다 보니 변수가 많다고 판단이 들더군요.

최종 판단은 VMAF 평균, VMAF p5, 출력 용량을 중심으로 했습니다.

데이터

modepresetcrf_valuetarget_bitrateencode_secondstotal_secondsoutput_sizemeasured_bitratevmaf_meanvmaf_p5vmaf_min
crfveryfast18136.4973.141.97 MB1,173,066 bps95.91695.264687.1316
crfveryfast20137.0969.033.94 MB949,010 bps95.419294.477887.5633
crfveryfast22136.6977.927.55 MB770,355 bps94.80493.567187.8429
crfveryfast24137.2971.222.72 MB635,195 bps94.020292.468186.7679
crfveryfast26136.6969.118.89 MB528,247 bps93.071591.06385.4895
bitrateveryfast4M145.01,002.5120.30 MB3,363,767 bps97.106896.675887.4941
bitrateveryfast5M130.5950.8143.54 MB4,013,489 bps97.218296.878886.6481
bitrateveryfast6M129.8950.5161.76 MB4,522,577 bps97.27896.99386.8844
bitrateveryfast8M131.4948.9188.04 MB5,257,395 bps97.337697.136986.261
bitrateveryfast10M133.3956.3196.97 MB5,507,232 bps97.362697.219685.9719
crffast18139.4943.053.46 MB1,494,516 bps96.774196.505785.9342
crffast20123.7948.642.91 MB1,199,624 bps96.496196.067886.0927
crffast22146.5957.734.93 MB976,696 bps96.094395.481986.2577
crffast24144.2961.028.65 MB801,058 bps95.6694.747686.9226
crffast26143.9952.823.81 MB665,763 bps95.070993.719187.6512
bitratefast4M168.5990.2119.44 MB3,339,445 bps97.245396.926587.082
bitratefast5M166.3986.9134.95 MB3,772,725 bps97.304897.038186.2122
bitratefast6M153.8992.5145.98 MB4,081,517 bps97.34397.117885.7265
bitratefast8M159.61,004.6161.52 MB4,515,925 bps97.381797.227185.6859
bitratefast10M169.51,013.7170.84 MB4,776,514 bps97.400997.298585.6429
crfmedium18161.7988.856.88 MB1,590,215 bps96.849896.620585.8193
crfmedium20161.7971.445.58 MB1,274,350 bps96.587196.241985.9814
crfmedium22158.4975.536.85 MB1,030,287 bps96.26495.754686.143
crfmedium24140.9971.930.18 MB843,782 bps95.853695.098486.6804
crfmedium26138.1991.525.02 MB699,329 bps95.329194.286687.4335
bitratemedium4M205.31,031.3120.51 MB3,369,406 bps97.284297.015687.1076
bitratemedium5M214.11,033.8135.75 MB3,795,327 bps97.334597.119486.1957
bitratemedium6M219.61,043.1146.32 MB4,090,826 bps97.366997.200885.7986
bitratemedium8M217.81,043.4161.49 MB4,515,022 bps97.397897.296985.6782
bitratemedium10M204.51,031.7170.32 MB4,761,776 bps97.412897.356385.6202
crfslow18123.21,002.258.77 MB1,643,090 bps96.905296.669285.7663
crfslow20199.41,018.447.47 MB1,327,204 bps96.671996.33186.0551
crfslow22194.31,008.438.35 MB1,072,355 bps96.36395.904586.1877
crfslow24185.11,003.131.35 MB876,415 bps95.977995.238286.6933
crfslow26181.5991.225.91 MB724,473 bps95.479194.550387.7418
bitrateslow4M204.81,051.4119.93 MB3,353,010 bps97.291597.024787.1576
bitrateslow5M130.7902.4135.27 MB3,781,923 bps97.344997.138486.1405
bitrateslow6M177.5891.0145.62 MB4,071,401 bps97.376797.200785.7874
bitrateslow8M180.5892.9161.70 MB4,520,882 bps97.40697.311785.7257
bitrateslow10M181.3895.9170.99 MB4,780,564 bps97.419397.368485.6088

표는 5행마다 mode가 바뀌도록 묶었습니다. 파란 배경은 crf, 주황 배경은 bitrate이며, 각 묶음 시작 행에는 구분선을 넣었습니다.

VMAF 평균, VMAF p5, 출력 용량을 기준으로 보면 다음과 같습니다.

  • CRF가 bitrate보다 효율적으로 보입니다. bitrate에 용량을 더 줘도 점수가 크게 오르지 않는 모습이지만, 용량은 비례하여 올라가는 것을 확인할 수 있습니다.
  • CRF 영상의 용량이 품질 점수 대비 매우 효율적이고, mean·p5 차이도 크게 발생하지 않고 있습니다. Bitrate는 이번 비교 범위에서 배제해도 되겠습니다.
    설정파일 크기measured bitrateVMAF meanVMAF p5
    CRF fast 2234.93 MB976,696 bps (0.98 Mbps)96.094395.4819
    CRF medium 2236.85 MB1,030,287 bps (1.03 Mbps)96.264095.7546
    CRF slow 2238.35 MB1,072,355 bps (1.07 Mbps)96.363095.9045
    Bitrate fast 4M119.44 MB3,339,445 bps (3.34 Mbps)97.245396.9265
  • veryfast 프리셋은 CRF에서 품질 손실이 크게 발생하는 것을 볼 수 있습니다. (CRF 22 기준)
    preset파일 크기VMAF meanVMAF p5
    veryfast27.6 MB94.804093.5671
    fast34.9 MB96.094395.4819
    medium36.8 MB96.264095.7546
    slow38.4 MB96.363095.9045
  • fast → medium → slow로 갈수록 mean·p5는 소폭 상승하지만, 용량 증가 대비 이득이 크지 않아 보입니다. (CRF 22 기준)
    presetVMAF meanVMAF p5파일 크기
    fast96.094395.481934.9 MB
    medium96.264095.754636.8 MB
    slow96.363095.904538.4 MB

로컬 테스트 결론

VMAF mean, VMAF p5, 출력 용량을 중심으로 정리하면 아래 옵션이 타당해 보입니다.
30분, 1시간 예상 용량은 5분 샘플 결과를 선형 확대한 값입니다.

목적추천 설정30분 예상 용량1시간 예상 용량VMAF meanVMAF p5
균형 추천crf medium 22약 221 MB약 442 MB96.264095.7546
fast 프리셋 대안crf fast 22약 210 MB약 419 MB96.094395.4819
용량 우선crf medium 26약 150 MB약 300 MB95.329194.2866
고품질crf medium 20약 273 MB약 547 MB96.587196.2419

집중 테스트

위 테스트에서 CRF와 고정 비트레이트를 비교했고, 그 결과 비트레이트의 효율이 낮다고 정의를 내렸습니다. 이제 덜어낼 건 덜어내고 아래 옵션들을 적용해 봅시다.

아래 옵션을 실사용 후보군으로 보고 집중 테스트해 봅시다.

  • preset = fast, medium
  • crf = 20, 22, 24, 26

이들에 대해 벤치마크를 세 번 더 돌려 평균 값을 도출하면 다음과 같습니다.

presetcrfavg_output_mibavg_measured_mbpsavg_vmaf_meanavg_vmaf_p5
fast2042.911.296.496196.0678
fast2234.930.97796.094395.4819
fast2428.650.80195.6694.7476
fast2623.810.66695.070993.7191
medium2045.581.27496.587196.2419
medium2236.851.0396.26495.7546
medium2430.180.84495.853695.0984
medium2625.010.69995.329194.2866

crf 값에 따라 vmaf 점수도 마찬가지로 내려갔지만, 평균값이 전부 93점 이상을 기록하는 것을 보면 품질이 괜찮게 나오는 것을 알 수 있습니다. 수치만 보면 fast보다 미세하게 medium이 나은 점도 확인할 수 있습니다. 용량을 아끼기 위해 crf는 22~26으로 가정하고, 품질 안정성도 고려해 medium이 좋을 것 같습니다.

실제 영상의 캡처본을 보면 품질이 가장 안 좋은 fast crf 20이 아래 사진입니다.
이를 보아도 글자가 제대로 표시되죠. sample

다른 영상들도 눈으로는 차이를 체감하기 어려웠습니다. vmaf 1~2점 차이는 눈에 띄는 화질 차이로 이어지지 않는 것으로 느껴졌습니다.

EC2 테스트

최종적으로는 medium 24로 택하였고, 배포 환경에서 옵션을 다음과 같이 바꿨습니다.

항목수정 전수정 후변경 이유
비디오 코덱libx264libx264H.264 기반 HLS 호환성을 유지
해상도 제한scale='min(1920,iw)':-2scale='min(1920,iw)':-2원본이 1920보다 크면 1080p급 너비로 제한하고, 비율 유지
프리셋mediummedium벤치마크에서 품질 안정성과 압축 효율의 균형이 좋았음
CRF2224VMAF 평균 95 이상을 유지하면서 용량을 줄이기 위해 조정
Maxrate5M3MCRF 24 구간 실측 비트레이트에 맞춰 비트레이트 상한을 조정
Bufsize10M6Mmaxrate의 2배 버퍼를 유지해 순간 비트레이트 변동을 완충
오디오 코덱aacaacHLS 호환성을 위해 유지
오디오 비트레이트128k128k일반적인 스트리밍 음질 기준 유지
세그먼트 길이10초10초기존 서비스 재생 구조와 캐싱 정책 유지
HLS 타입vodvodVOD용 정적 플레이리스트 생성

이를 토대로 같은 영상을 배포 환경에서 S3를 이용해 배포해 보니,
기존 세팅은 636s가 소요되었고 새로 바뀐 세팅은 622s로 미세하게 줄었습니다.
이는 CPU 상황에 따라 달라질 수 있는 수준이라, 사실상 큰 의미는 없었습니다.

저장 공간도 74.8MB에서 73.8MB로 미세하게 줄었습니다.
아마 기존 세팅과 거의 유사했기에 이런 결과가 나왔습니다. 다만 리소스로 사용된 영상의 길이가 20분이어서 차이가 작게 보였을 뿐이며 분명한 개선이 발생했다는 점이 중요하죠.