📁 File3. 비디오12 · 인코딩 파이프라인 (ffmpeg · MediaConvert · CRF/CBR/VBR)

12 · 인코딩 파이프라인 (ffmpeg · MediaConvert · CRF/CBR/VBR)

이 문서가 답하는 질문: 비디오 인코딩 파이프라인은 어떻게 짜고, CRF·CBR·VBR은 언제 무엇을 쓰는가? 선행: 06-containers.md, 08-codec-h264.md


한 줄 답

**인코딩 파이프라인은 “원본 → 분석 → 정규화 → 인코딩 → 패키징 → 배포” 6단계로 구성되며, 각 단계의 결정은 최종 소비자(브라우저/디바이스/네트워크)에서 거꾸로 추론된다. Rate control(CRF·CBR·VBR·CapVBR)은 비트 예산을 어떻게 분배할지 의 정책이다.


Why — 왜 파이프라인이 필요한가

비디오 한 편을 그냥 ffmpeg 한 줄로 인코딩해도 동작은 한다. 하지만 수백만 시간의 콘텐츠를 자동으로 처리하려면:

  • 다양한 원본 (mp4·mov·mkv·VFR·anamorphic·interlaced…) 을 통일해야 함
  • 여러 클라이언트 (iOS·Android·Smart TV·Web·구형) 에 모두 송출
  • 품질 일관성: 어두운 장면에서 비트가 부족하면 안 됨
  • 비용 통제: 인코딩·CDN·스토리지 비용이 균형
  • 장애 처리: 한 영상이 깨지면 전체 파이프라인이 멈추면 안 됨

→ 단일 명령어가 아니라 단계별 결정의 트리가 필요.


How — 6단계 파이프라인

표준 인코딩 파이프라인

1) 원본 수신

  • 사용자 업로드 (multipart/tus → S3)
  • 또는 외부 ingest (RTMP·SRT 라이브)
  • 무결성 검증: 파일 크기·MD5·magic byte (00-foundations)

2) 분석 (ffprobe)

ffprobe -v error -print_format json \
  -show_format -show_streams in.mp4 > metadata.json

추출 정보:

  • 컨테이너 (format_name)
  • 비디오 코덱·해상도·fps·color matrix·field order·pix_fmt
  • 오디오 코덱·sample rate·channels·LUFS
  • duration·bit_rate·tags(rotation·creation_time…)
  • VFR vs CFR (avg_frame_rate vs r_frame_rate 비교)

→ 다음 단계의 결정 입력. 자동화 파이프라인에서는 분석 결과로 ladder를 가변 결정.

3) 정규화

입력 상태변환
Interlaced (1080i59.94)bwdif/yadif → 1080p
Telecine (3:2 pulldown)fieldmatch + decimate → 24p
VFR-vsync cfr → CFR
회전 메타만 있음transpose 필터로 픽셀 회전
BT.601 SD → BT.709 HD upscalecolormatrix 변환 + scale
Anamorphic 720×480scale=854:480, setsar=1:1
4:4:4 마스터yuv420p 변환
10bit HDR → SDRzscale + tonemap

이 단계가 빠지면 클라이언트마다 깨짐. 자동화에서 가장 깐깐한 단계.

4) 인코딩 (ABR ladder)

Ladder 설계

콘텐츠 특성과 타겟 디바이스 별로 ladder가 다름:

콘텐츠권장 ladder
단편/SNS360p · 540p · 720p · 1080p (4-step)
일반 OTT240·360·480·720·720p60·1080·1080p60 (7-step)
4K HDR+ 1440p · 4K · 4K HDR (10-step)
라이브 게임720p60·1080p60 단순 (latency 우선)

Per-Title encoding (Netflix 발명): 모든 타이틀에 같은 ladder 강제 X. 콘텐츠 복잡도에 따라 동적 ladder.

Rate Control 정책

모드풀이사용처
CBR (Constant Bit Rate)비트레이트 고정라이브·방송·CDN 대역폭 예측
VBR (Variable Bit Rate)비트레이트 가변, 평균 목표일반 OTT
CapVBRVBR + 최대 cap안전한 라이브·CMAF
CRF (Constant Rate Factor)시각 품질 고정, 비트레이트 가변마스터링·아카이브
2-pass VBR1-pass 분석 + 2-pass 인코딩정확한 사이즈 목표
# CRF (가장 흔함)
-c:v libx264 -crf 22
 
# 2-pass VBR (정확한 비트레이트)
ffmpeg -y -i in.mov -c:v libx264 -b:v 4M -pass 1 -an -f null /dev/null
ffmpeg -i in.mov -c:v libx264 -b:v 4M -pass 2 out.mp4
 
# CBR (라이브)
-c:v libx264 -b:v 4M -minrate 4M -maxrate 4M -bufsize 8M
 
# CapVBR (라이브 안전)
-c:v libx264 -b:v 4M -maxrate 6M -bufsize 12M

코덱별 ladder 비교

같은 1080p 품질 기준:

코덱권장 비트레이트
H.2645 Mbps
HEVC3 Mbps
VP93 Mbps
AV12.5 Mbps

5) 패키징

HLS

ffmpeg -i normalized.mp4 \
  -c:v libx264 -c:a aac \
  -hls_time 6 -hls_list_size 0 \
  -hls_segment_type fmp4 \
  -hls_segment_filename "v_%v_%03d.m4s" \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0,name:1080p v:1,a:1,name:720p v:2,a:2,name:480p" \
  -hls_playlist_type vod \
  out_%v.m3u8

→ master.m3u8 + 각 variant playlist + 세그먼트(fMP4 또는 ts).

DASH

ffmpeg -i in.mp4 \
  -map 0:v -map 0:a \
  -c:v libx264 -c:a aac \
  -seg_duration 6 \
  -use_template 1 -use_timeline 1 \
  -f dash out.mpd

CMAF (HLS+DASH 공통)

CMAF fMP4 fragment를 만들어 HLS와 DASH manifest 두 개를 동시에.

6) 배포

  • Origin S3 + CloudFront/Cloudflare CDN
  • 필요시 서명 URL (private 콘텐츠)
  • DRM packaging (Widevine·FairPlay·PlayReady) — 06-streaming 챕터 참조

What — 실용적 명령어 모음

풀 ABR ladder (H.264, single-shot)

ffmpeg -i in.mov \
  -filter_complex "\
    [0:v]split=4[v1][v2][v3][v4]; \
    [v1]scale=w=1920:h=1080[v1080]; \
    [v2]scale=w=1280:h=720[v720]; \
    [v3]scale=w=854:h=480[v480]; \
    [v4]scale=w=640:h=360[v360]" \
  -map "[v1080]" -c:v:0 libx264 -b:v:0 5M -profile:v:0 high -level 4.0 \
  -map "[v720]"  -c:v:1 libx264 -b:v:1 2.5M -profile:v:1 high -level 3.1 \
  -map "[v480]"  -c:v:2 libx264 -b:v:2 1.2M -profile:v:2 main -level 3.0 \
  -map "[v360]"  -c:v:3 libx264 -b:v:3 600k -profile:v:3 baseline -level 3.0 \
  -map a:0 -c:a aac -b:a 128k -ac 2 \
  -g 60 -keyint_min 60 -sc_threshold 0 \
  -hls_time 6 -hls_playlist_type vod \
  -hls_segment_type fmp4 \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0,name:1080p v:1,a:0,name:720p v:2,a:0,name:480p v:3,a:0,name:360p" \
  out_%v.m3u8

2-pass with target file size

# 100 MB로 1시간 영상 맞추기
TARGET_SIZE_MB=100
DURATION=$(ffprobe -v error -show_entries format=duration -of csv=p=0 in.mov)
BITRATE=$(echo "($TARGET_SIZE_MB * 8 * 1024) / $DURATION - 128" | bc)k
 
ffmpeg -y -i in.mov -c:v libx264 -b:v $BITRATE -pass 1 -an -f null /dev/null
ffmpeg -i in.mov -c:v libx264 -b:v $BITRATE -pass 2 -c:a aac -b:a 128k out.mp4

AWS Elemental MediaConvert 패턴

MediaConvert는 ffmpeg를 완전 매니지드 + ABR job 자동화 한 서비스.

Job 구조 (간략):

{
  "Settings": {
    "Inputs": [{
      "FileInput": "s3://bucket/in.mp4",
      "DeblockFilter": "DISABLED",
      "DenoiseFilter": "DISABLED"
    }],
    "OutputGroups": [{
      "Name": "Apple HLS",
      "OutputGroupSettings": {
        "Type": "HLS_GROUP_SETTINGS",
        "HlsGroupSettings": {
          "SegmentLength": 6,
          "MinSegmentLength": 0,
          "Destination": "s3://bucket/hls/"
        }
      },
      "Outputs": [
        {"NameModifier": "_1080", "VideoDescription": {"Width": 1920, "Height": 1080, "CodecSettings": {"Codec": "H_264", "H264Settings": {"Bitrate": 5000000}}}},
        {"NameModifier": "_720",  "VideoDescription": {"Width": 1280, "Height": 720,  "CodecSettings": {"Codec": "H_264", "H264Settings": {"Bitrate": 2500000}}}}
      ]
    }]
  }
}

→ MediaConvert는 ABR auto-ladder (AutomatedEncodingSettings)도 지원: 비트레이트 cap만 주면 콘텐츠 복잡도 분석해 자동 ladder 생성.

화질 검증 — VMAF

Netflix가 만든 perceptual quality metric. PSNR/SSIM보다 사람 인지에 가까움.

# 원본 vs 인코딩본 VMAF 점수
ffmpeg -i original.mp4 -i encoded.mp4 \
  -lavfi "[0:v][1:v]libvmaf=log_path=vmaf.json" -f null -

VMAF 점수 가이드:

  • 95+: 시각적으로 손실 거의 없음
  • 90~95: 일반 OTT 품질
  • 80~90: 모바일 데이터 절감 모드
  • < 70: 품질 저하 인지 가능

흔한 정규화 명령어

# 회전 메타 → 픽셀 회전
ffmpeg -i in.mp4 -vf "transpose=1" -metadata:s:v rotate=0 out.mp4
 
# 자동 디인터레이스 (input field order 자동 감지)
ffmpeg -i in.mov -vf "bwdif=mode=1:parity=auto:deint=1" out.mp4
 
# VFR → CFR
ffmpeg -i screen.mp4 -vsync cfr -r 60 -c:v libx264 cfr.mp4
 
# Anamorphic 정규화
ffmpeg -i ana.mov -vf "scale=854:480,setsar=1:1" out.mp4
 
# Color matrix 명시
-color_primaries bt709 -color_trc bt709 -colorspace bt709

What-if — 잘못 다루면 어떻게 깨지는가

❌ 함정 1 — 정규화 단계 생략

원본을 그대로 인코딩 → 어떤 클라이언트에서는 깨진 영상. 정규화는 비싸지만 반드시 통과해야 하는 게이트. 자동 파이프라인의 90% 버그가 여기서 나옴.

❌ 함정 2 — Key frame 위치가 ladder마다 다름

ABR 전환 시 반드시 모든 ladder에서 같은 시각에 key frame이 있어야 함.

# 모든 ladder에 동일 GOP 강제
-g 60 -keyint_min 60 -sc_threshold 0 \
-force_key_frames "expr:gte(t,n_forced*2)"

❌ 함정 3 — CBR을 VOD에 사용

CBR은 모든 장면에 같은 비트 — 정적 장면에서 비트 낭비, 격렬한 장면에서 비트 부족. VOD는 VBR 또는 CRF가 정석. CBR은 라이브의 대역폭 예측 용도.

❌ 함정 4 — CRF 값을 ladder마다 똑같이

CRF는 해상도 비-aware. 1080p CRF 22와 360p CRF 22는 다른 비트레이트. 해상도가 낮을수록 CRF를 낮춰야 (더 좋은 화질) — 작은 해상도에서 비트가 적게 쓰이는 걸 보정.

1080p: CRF 22
720p:  CRF 21
480p:  CRF 20
360p:  CRF 19

❌ 함정 5 — 인코딩 후 검증 안 함

인코딩이 silently fail (예: 일부 NAL 손상) 해도 재생 시 깨질 때까지 모름. ffprobe로 패킷 무결성 + VMAF 샘플 점수로 검증 단계 추가.

❌ 함정 6 — 모든 코덱·모든 해상도 ladder 풀 인코딩

H.264 7-step + HEVC 5-step + AV1 4-step + VP9 3-step = 19 인코딩. 콘텐츠 시청 분포에 비해 비싸짐. 상위 70% 시청 디바이스 커버하는 ladder만 선택.

❌ 함정 7 — 마스터 원본 폐기

ABR ladder만 남기고 원본 폐기하면 미래 코덱(VVC·AV2)으로 재인코딩 불가. 마스터(고품질)는 cold storage에 영구 보관, ABR은 재생성 가능한 derivative.


Insight — 흥미로운 이야기

“Netflix Per-Title Encoding”

2015년 Netflix가 발표 — 모든 타이틀에 같은 ladder를 쓰지 말자. 애니메이션은 평면 영역 많아 1080p에 1.5 Mbps로 충분, 액션 영화는 4 Mbps 필요. 콘텐츠 분석 후 맞춤 ladder 생성 → 평균 20% 대역폭 절감 + 같은 품질. 이후 Per-Shot Encoding, Dynamic Optimizer로 진화 — 한 영상 안에서도 장면별 다른 비트.

“VMAF가 VAS-MAF가 된 사연”

Netflix가 PSNR/SSIM이 사람 인지와 안 맞는다는 걸 깨닫고 만든 metric. 여러 quality metric (VIF·DLM·motion)을 머신러닝으로 융합 — 이름의 ‘M’은 Machine learning. 2016년 오픈소스화. AV1·VP9 인코더 튜닝의 de facto 평가 도구.

“AWS MediaConvert는 ffmpeg + 매니지드”

MediaConvert는 내부적으로 Elemental Server (AWS가 인수한 회사)의 인코더 사용. 핵심 차별점:

  • 자동 ABR ladder (콘텐츠 분석)
  • QVBR (Quality-Defined Variable Bit Rate) — Elemental 고유 rate control
  • DRM packaging 통합 (Widevine·FairPlay·PlayReady 한번에)
  • per-job pricing — 사용한 만큼만 → 자체 ffmpeg 클러스터 운용보다 총비용 더 쌀 가능성 — 규모에 따라.

“YouTube의 trick — Two-pass with cluster”

YouTube는 영상 한 편을 청크로 쪼개 수천 GPU에 병렬 인코딩. 각 청크가 독립적으로 2-pass 후 다시 합침. 1시간 영상이 수 분 만에 인코딩. 이게 가능한 이유: GOP 경계에서 청크를 나누면 디코딩 호환성 유지.

“라이브 vs VOD의 진짜 차이는 Rate Control”

VOD: CRF (사이즈 가변, 품질 일정) 라이브: CBR (비트 고정, 품질 가변) 왜 라이브는 비트 고정? — 인터넷 송출 시 대역폭 예측 가능성이 가장 중요. 갑자기 비트 폭증하면 ABR 전환이 어긋남.

“인코딩은 비대칭 비용 게임”

한 번 인코딩 = O(시간 × 1) 재생 = O(시간 × 사용자 수) = 수백만 배. 그래서 OTT는 인코딩에 시간을 더 쓰는 결정이 합리적 — libsvtav1 preset 4preset 9보다 4배 느려도 대역폭 5% 절감이면 회수.


요약 + Mermaid

인코딩 파이프라인은 6단계(수신 → 분석 → 정규화 → 인코딩 → 패키징 → 배포)이며, 각 단계는 최종 소비자에서 거꾸로 추론된다. CRF는 마스터링·VOD, CBR은 라이브, VBR/CapVBR은 일반 OTT. ABR ladder는 모든 변형의 key frame 위치 일치 필수. Per-Title encoding과 VMAF가 모던 OTT의 표준이고, MediaConvert는 매니지드 옵션. 마스터는 영구 보관, ladder는 재생성 가능한 derivative.