[2026] H.264 코덱 완벽 가이드 | NAL·SPS·PPS·프로파일·레벨 심층 분석
이 글의 핵심
H.264 코덱 NAL Unit, SPS, PPS, Slice 구조부터 프로파일, 레벨, 실전 인코딩까지. 왜 아직도 H.264가 표준인지 기초부터 실무까지.
들어가며
H.264 (AVC, MPEG-4 Part 10)는 가장 널리 사용되는 비디오 코덱입니다. YouTube, Netflix, Zoom 등 대부분의 영상 서비스가 H.264를 사용합니다. 비유로 말씀드리면, H.264는 영상 압축의 만능 열쇠입니다. H.265가 더 효율적이지만, H.264는 모든 기기에서 작동하고 특허 문제가 없어 여전히 표준입니다.
이 글을 읽으면
- H.264의 구조와 원리를 이해합니다
- NAL Unit, SPS, PPS 등 헤더 정보를 파악합니다
- 프로파일과 레벨을 선택할 수 있습니다
- 실전 인코딩과 디코딩을 구현합니다
실무에서 마주한 현실
개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.
목차
- H.264 기초
- NAL Unit 구조
- SPS (Sequence Parameter Set)
- PPS (Picture Parameter Set)
- Slice와 Macroblock
- 프로파일과 레벨
- 비트스트림 분석
- 실전 인코딩
- 왜 아직도 H.264인가
- 트러블슈팅
- 마무리
H.264 기초
H.264란?
H.264 (Advanced Video Coding)는 2003년 ITU-T와 ISO/IEC가 공동 개발한 비디오 압축 표준입니다. 별칭:
- H.264 (ITU-T 명칭)
- AVC (Advanced Video Coding)
- MPEG-4 Part 10
H.264의 압축 원리
1. 공간적 중복 제거 (Intra Prediction) 아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
원본 프레임:
■■■■■■■■
■■■■■■■■
■■■■■■■■
인접 픽셀이 비슷함 → 차이만 저장
→ 압축!
2. 시간적 중복 제거 (Inter Prediction) 아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 실행 예제
프레임 1: 공이 왼쪽에
프레임 2: 공이 오른쪽으로 이동
전체 프레임 저장 X
→ "공이 오른쪽으로 10픽셀 이동" 만 저장
→ 압축!
3. 변환 및 양자화 (DCT + Quantization)
픽셀 값 → 주파수 변환 (DCT)
→ 중요하지 않은 고주파 제거 (Quantization)
→ 압축!
H.264 프레임 타입
I-Frame (Intra Frame)
- 독립적인 완전한 프레임
- 압축률 낮음, 용량 큼
- 시크(Seek) 포인트 P-Frame (Predicted Frame)
- 이전 프레임 참조
- 압축률 중간
- I-Frame보다 작음 B-Frame (Bi-directional Frame)
- 이전 + 이후 프레임 참조
- 압축률 높음, 용량 작음
- 인코딩 복잡 아래 코드는 text를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
GOP (Group of Pictures):
I P P P P P P P I P P P P P P P
I: 키프레임 (독립적)
P: 이전 프레임 참조
B: 양방향 참조 (선택적)
NAL Unit 구조
NAL Unit이란?
NAL (Network Abstraction Layer) Unit은 H.264 비트스트림의 기본 단위입니다. 구조:
[Start Code] [NAL Header] [NAL Payload]
3-4 bytes 1 byte 가변 길이
Start Code
Annex B 포맷:
0x00 0x00 0x00 0x01 (4 bytes, 일반적)
또는
0x00 0x00 0x01 (3 bytes, 짧은 형식)
AVCC 포맷 (MP4):
[Length] [NAL Data]
4 bytes 가변 길이
Length: NAL Unit 크기 (빅 엔디안)
NAL Header (1 byte)
아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
7 6 5 4 3 2 1 0
┌─┬─────┬─────────┐
│F│ NRI │ Type │
└─┴─────┴─────────┘
F (Forbidden Zero Bit): 항상 0
NRI (NAL Ref IDC): 중요도 (0-3)
Type (NAL Unit Type): NAL 타입 (0-31)
NAL Unit 타입
| 타입 | 이름 | 설명 |
|---|---|---|
| 0 | Unspecified | 미정의 |
| 1 | Coded Slice (Non-IDR) | P/B 프레임 슬라이스 |
| 2 | Coded Slice (Partition A) | 데이터 분할 A |
| 3 | Coded Slice (Partition B) | 데이터 분할 B |
| 4 | Coded Slice (Partition C) | 데이터 분할 C |
| 5 | Coded Slice (IDR) | I 프레임 (키프레임) |
| 6 | SEI (Supplemental Enhancement) | 부가 정보 |
| 7 | SPS | 시퀀스 파라미터 세트 |
| 8 | PPS | 픽처 파라미터 세트 |
| 9 | Access Unit Delimiter | AU 구분자 |
| 10 | End of Sequence | 시퀀스 종료 |
| 11 | End of Stream | 스트림 종료 |
| 12 | Filler Data | 채우기 데이터 |
| 예시: | ||
| 다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다. |
0x67: NAL Type 7 (SPS)
Binary: 0110 0111
F: 0
NRI: 11 (중요도 3, 최고)
Type: 00111 (7, SPS)
0x68: NAL Type 8 (PPS)
Binary: 0110 1000
F: 0
NRI: 11 (중요도 3)
Type: 01000 (8, PPS)
0x65: NAL Type 5 (IDR)
Binary: 0110 0101
F: 0
NRI: 11 (중요도 3)
Type: 00101 (5, IDR 프레임)
0x41: NAL Type 1 (Non-IDR)
Binary: 0100 0001
F: 0
NRI: 10 (중요도 2)
Type: 00001 (1, P/B 프레임)
SPS (Sequence Parameter Set)
SPS란?
SPS는 전체 비디오 시퀀스의 설정을 담고 있습니다. 디코더가 영상을 해석하는 데 필수적입니다. 포함 정보:
- 프로파일 (Profile)
- 레벨 (Level)
- 해상도 (Width, Height)
- 프레임 레이트
- 색상 정보
- 비트 깊이
SPS 구조
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
SPS NAL Unit:
[Start Code] [NAL Header (0x67)] [SPS Data]
SPS Data (비트 단위):
- profile_idc (8 bits)
- constraint_set_flags (8 bits)
- level_idc (8 bits)
- seq_parameter_set_id (ue(v))
- chroma_format_idc (ue(v))
- bit_depth_luma_minus8 (ue(v))
- bit_depth_chroma_minus8 (ue(v))
- log2_max_frame_num_minus4 (ue(v))
- pic_order_cnt_type (ue(v))
- max_num_ref_frames (ue(v))
- pic_width_in_mbs_minus1 (ue(v))
- pic_height_in_map_units_minus1 (ue(v))
- frame_mbs_only_flag (1 bit)
- ...
ue(v): Exp-Golomb 가변 길이 인코딩
SPS 예시 분석
SPS 바이트:
00 00 00 01 67 64 00 1F AC D9 40 50 05 BB 01 6A 02 02 02 80 00 00 03 00 80 00 00 19 47 8C 18 CB
분석: 다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
00 00 00 01: Start Code
67: NAL Header (Type 7, SPS)
64: profile_idc = 100 (High Profile)
00: constraint_set_flags
1F: level_idc = 31 (Level 3.1)
AC D9 40 50 05 BB 01 6A 02 02 02 80 ...
→ 비트 단위로 파싱:
seq_parameter_set_id = 0
chroma_format_idc = 1 (4:2:0)
bit_depth_luma_minus8 = 0 (8-bit)
bit_depth_chroma_minus8 = 0 (8-bit)
log2_max_frame_num_minus4 = 0 (max_frame_num = 16)
pic_order_cnt_type = 0
max_num_ref_frames = 4
pic_width_in_mbs_minus1 = 79 (width = 1280)
pic_height_in_map_units_minus1 = 44 (height = 720)
SPS 추출 (FFmpeg)
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# SPS/PPS 추출
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f h264 - | \
xxd | head -50
# 또는 MediaInfo로 확인
mediainfo input.mp4 --Details=1
PPS (Picture Parameter Set)
PPS란?
PPS는 각 픽처(프레임)의 설정을 담고 있습니다. SPS보다 자주 변경될 수 있습니다. 포함 정보:
- Entropy 코딩 모드 (CAVLC/CABAC)
- 슬라이스 그룹 정보
- 양자화 파라미터
- 디블로킹 필터 설정
PPS 구조
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
PPS NAL Unit:
[Start Code] [NAL Header (0x68)] [PPS Data]
PPS Data:
- pic_parameter_set_id (ue(v))
- seq_parameter_set_id (ue(v))
- entropy_coding_mode_flag (1 bit)
→ 0: CAVLC, 1: CABAC
- pic_order_present_flag (1 bit)
- num_slice_groups_minus1 (ue(v))
- num_ref_idx_l0_active_minus1 (ue(v))
- num_ref_idx_l1_active_minus1 (ue(v))
- weighted_pred_flag (1 bit)
- weighted_bipred_idc (2 bits)
- pic_init_qp_minus26 (se(v))
- deblocking_filter_control_present_flag (1 bit)
- ...
PPS 예시
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
00 00 00 01 68 EE 3C 80
00 00 00 01: Start Code
68: NAL Header (Type 8, PPS)
EE 3C 80:
→ 비트 단위 파싱:
pic_parameter_set_id = 0
seq_parameter_set_id = 0
entropy_coding_mode_flag = 1 (CABAC)
pic_order_present_flag = 0
num_slice_groups_minus1 = 0
num_ref_idx_l0_active_minus1 = 3
num_ref_idx_l1_active_minus1 = 1
weighted_pred_flag = 0
weighted_bipred_idc = 0
pic_init_qp_minus26 = 0 (QP = 26)
deblocking_filter_control_present_flag = 1
Slice와 Macroblock
Slice란?
Slice는 프레임을 독립적으로 디코딩 가능한 단위로 나눈 것입니다. Slice 타입:
| 타입 | 이름 | 설명 |
|---|---|---|
| I | Intra Slice | I-Frame (독립적) |
| P | Predicted Slice | P-Frame (이전 참조) |
| B | Bi-directional Slice | B-Frame (양방향 참조) |
| SI | Switching I | 스위칭용 I |
| SP | Switching P | 스위칭용 P |
Slice 구조
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
Slice NAL Unit:
[Start Code] [NAL Header] [Slice Header] [Slice Data]
Slice Header:
- first_mb_in_slice (ue(v))
- slice_type (ue(v))
- pic_parameter_set_id (ue(v))
- frame_num (u(v))
- pic_order_cnt_lsb (u(v))
- ...
Slice Data:
- Macroblock 1
- Macroblock 2
- ...
Macroblock이란?
Macroblock은 16×16 픽셀 블록으로, H.264의 기본 처리 단위입니다. 아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
프레임 (1920×1080):
→ 120 × 68 = 8,160개의 Macroblock
각 Macroblock:
- 16×16 Luma (Y)
- 8×8 Chroma (Cb, Cr) × 2
Macroblock 파티션: 다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
16×16 (전체)
┌────────────────┐
│ │
│ │
│ │
│ │
└────────────────┘
16×8 (상하 분할)
┌────────────────┐
│ │
├────────────────┤
│ │
└────────────────┘
8×16 (좌우 분할)
┌────────┬───────┐
│ │ │
│ │ │
│ │ │
│ │ │
└────────┴───────┘
8×8 (4분할)
┌────────┬───────┐
│ │ │
├────────┼───────┤
│ │ │
└────────┴───────┘
프로파일과 레벨
프로파일 (Profile)
프로파일은 사용 가능한 기능의 집합입니다. 주요 프로파일:
| 프로파일 | profile_idc | 특징 | 용도 |
|---|---|---|---|
| Baseline | 66 | B-Frame 없음, CAVLC | 모바일, 화상 통화 |
| Main | 77 | B-Frame, CABAC | 방송, 스트리밍 |
| High | 100 | 8×8 변환, 양자화 | Blu-ray, HDTV |
| High 10 | 110 | 10-bit | 전문가용 |
| High 4:2:2 | 122 | 4:2:2 색상 | 방송 스튜디오 |
| High 4:4:4 | 244 | 4:4:4 색상, 무손실 | 전문가용 |
| 프로파일 선택: | |||
| 다음은 간단한 code 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요. |
모바일/WebRTC: Baseline
YouTube/Netflix: Main 또는 High
Blu-ray: High
전문가: High 10 이상
레벨 (Level)
레벨은 해상도, 프레임 레이트, 비트레이트 제한을 정의합니다. 주요 레벨:
| 레벨 | level_idc | 최대 해상도 | 최대 fps | 최대 비트레이트 |
|---|---|---|---|---|
| 3.0 | 30 | 720×576 | 30 | 10 Mbps |
| 3.1 | 31 | 1280×720 | 30 | 14 Mbps |
| 4.0 | 40 | 1920×1080 | 30 | 20 Mbps |
| 4.1 | 41 | 1920×1080 | 30 | 50 Mbps |
| 5.0 | 50 | 2560×1920 | 30 | 135 Mbps |
| 5.1 | 51 | 3840×2160 (4K) | 30 | 240 Mbps |
| 5.2 | 52 | 4096×2160 (4K) | 60 | 240 Mbps |
| 레벨 계산: | ||||
| 아래 코드는 code를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다. |
MacroBlocks per Second (MBPS):
= (Width / 16) × (Height / 16) × FPS
예시: 1920×1080 @ 30fps
= (1920/16) × (1080/16) × 30
= 120 × 68 × 30
= 244,800 MBPS
Level 4.0: 최대 245,760 MBPS
→ 1920×1080 @ 30fps 가능!
비트스트림 분석
실제 H.264 비트스트림 예시
다음은 간단한 code 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
00 00 00 01 67 64 00 1F AC D9 40 50 05 BB 01 6A ....gd..@P...j
00 00 00 01 68 EE 3C 80 ....h.<.
00 00 00 01 65 88 84 00 .... ....e...
00 00 00 01 41 9A 21 .... ....A.!.
분석: 다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
1. SPS (00 00 00 01 67 ...)
- Start Code: 00 00 00 01
- NAL Header: 67 (Type 7)
- Profile: High (100)
- Level: 3.1
- 해상도: 1280×720
2. PPS (00 00 00 01 68 ...)
- Start Code: 00 00 00 01
- NAL Header: 68 (Type 8)
- Entropy: CABAC
3. IDR Frame (00 00 00 01 65 ...)
- Start Code: 00 00 00 01
- NAL Header: 65 (Type 5, IDR)
- I-Frame 데이터
4. P Frame (00 00 00 01 41 ...)
- Start Code: 00 00 00 01
- NAL Header: 41 (Type 1, Non-IDR)
- P-Frame 데이터
비트스트림 분석 도구
1. FFmpeg: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# NAL Unit 정보 출력
ffmpeg -i input.mp4 -c copy -bsf:v trace_headers -f null - 2>&1 | grep -A 10 "nal_unit_type"
# 상세 분석
ffprobe -show_packets -show_data -print_format json input.mp4 > analysis.json
2. H264Naked (Python): 다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 필요한 모듈 import
from h264_naked import H264Parser
parser = H264Parser()
with open('video.h264', 'rb') as f:
data = f.read()
for nal in parser.parse(data):
print(f"NAL Type: {nal.type}")
print(f"Size: {nal.size}")
if nal.type == 7: # SPS
print(f"Profile: {nal.profile}")
print(f"Level: {nal.level}")
print(f"Width: {nal.width}")
print(f"Height: {nal.height}")
3. MediaInfo:
mediainfo input.mp4 --Details=1 | grep -A 20 "Video"
실전 인코딩
FFmpeg로 H.264 인코딩
기본 인코딩: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
ffmpeg -i input.mp4 \
-c:v libx264 \
-crf 23 \
-preset medium \
-c:a aac -b:a 128k \
output.mp4
프로파일과 레벨 지정: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v high \
-level 4.1 \
-crf 23 \
-preset medium \
output.mp4
고급 설정: 다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v high \
-level 4.1 \
-crf 23 \
-preset slow \
-tune film \
-x264-params "keyint=60:min-keyint=30:scenecut=40:ref=4:bframes=3:b-adapt=2:me=umh:subme=8:trellis=2:aq-mode=3" \
-c:a aac -b:a 192k \
output.mp4
# 설명:
# keyint=60: GOP 크기 (2초 @ 30fps)
# min-keyint=30: 최소 GOP 크기
# scenecut=40: 장면 전환 감지
# ref=4: 참조 프레임 수
# bframes=3: B-Frame 수
# b-adapt=2: 적응형 B-Frame
# me=umh: 움직임 추정 알고리즘
# subme=8: 서브픽셀 정밀도
# trellis=2: Trellis 양자화
# aq-mode=3: 적응형 양자화
프리셋 비교
| 프리셋 | 속도 | 품질 | 파일 크기 | 용도 |
|---|---|---|---|---|
| ultrafast | 매우 빠름 | 낮음 | 큼 | 실시간 스트리밍 |
| superfast | 빠름 | 낮음 | 큼 | 라이브 |
| veryfast | 빠름 | 중간 | 중간 | 일반 스트리밍 |
| faster | 빠름 | 중간 | 중간 | 일반 |
| fast | 보통 | 좋음 | 중간 | 일반 |
| medium | 보통 | 좋음 | 작음 | 기본값 |
| slow | 느림 | 매우 좋음 | 작음 | VOD |
| slower | 매우 느림 | 최고 | 매우 작음 | 아카이브 |
| veryslow | 극도로 느림 | 최고 | 매우 작음 | 전문가 |
CRF (Constant Rate Factor)
CRF는 품질 기반 인코딩입니다. 아래 코드는 code를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
CRF 값:
0 = 무손실 (매우 큼)
18 = 시각적 무손실
23 = 기본값 (권장)
28 = 낮은 품질
51 = 최악의 품질
권장:
애니메이션: CRF 15-20
영화: CRF 18-24
웹 비디오: CRF 23-28
2-Pass 인코딩
더 나은 품질을 위한 2단계 인코딩: 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Pass 1: 분석
ffmpeg -i input.mp4 \
-c:v libx264 \
-b:v 5M \
-pass 1 \
-f null /dev/null
# Pass 2: 인코딩
ffmpeg -i input.mp4 \
-c:v libx264 \
-b:v 5M \
-pass 2 \
-c:a aac -b:a 192k \
output.mp4
왜 아직도 H.264인가
H.264 vs H.265 (HEVC)
| 특성 | H.264 | H.265 |
|---|---|---|
| 압축률 | 기준 | 50% 더 효율적 |
| 인코딩 속도 | 빠름 | 느림 (10배) |
| 디코딩 부하 | 낮음 | 높음 |
| 하드웨어 지원 | 모든 기기 | 최신 기기만 |
| 브라우저 지원 | 100% | 제한적 |
| 특허 | 만료 (무료) | 복잡 (유료) |
| 파일 크기 | 기준 | 50% 작음 |
H.264를 선택하는 이유
1. 범용성 아래 코드는 code를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
H.264 지원:
- 모든 스마트폰 (iPhone 3GS 이후)
- 모든 브라우저
- 모든 스마트 TV
- 모든 게임 콘솔
- 모든 카메라
H.265 지원:
- 최신 스마트폰만
- 일부 브라우저 (Safari만)
- 최신 TV만
2. 하드웨어 가속 아래 코드는 code를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
H.264 하드웨어 디코딩:
- CPU 사용률: 5-10%
- 배터리 소모: 낮음
- 발열: 적음
H.265 소프트웨어 디코딩:
- CPU 사용률: 80-100%
- 배터리 소모: 높음
- 발열: 많음
3. 인코딩 비용 아래 코드는 code를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
1시간 영상 인코딩:
H.264 (preset=medium):
- 시간: 10분
- 비용: $0.10 (AWS)
H.265 (preset=medium):
- 시간: 100분
- 비용: $1.00 (AWS)
10배 차이!
4. 특허 문제 아래 코드는 code를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
H.264:
- 2023년 특허 만료
- 무료 사용 가능
- 법적 리스크 없음
H.265:
- 특허 유효
- 로열티 필요
- 특허 풀 복잡
실제 사용 현황 (2026년)
다음은 code를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
YouTube:
- 기본: H.264
- 4K: VP9 또는 AV1
- 8K: AV1
Netflix:
- 1080p 이하: H.264
- 4K: H.265 (지원 기기만)
- 4K: H.264 (나머지 기기)
Twitch:
- 모든 스트림: H.264
Zoom:
- 모든 통화: H.264
트러블슈팅
1. “Unsupported codec” 에러
문제: 일부 기기에서 재생 안됨 원인: 높은 프로파일/레벨 해결: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Baseline Profile로 재인코딩
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v baseline \
-level 3.0 \
-pix_fmt yuv420p \
output.mp4
2. 파일 크기가 너무 큼
문제: 인코딩 후 파일이 원본보다 큼 원인: CRF 값이 너무 낮음 해결: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# CRF 값 증가 (23 → 28)
ffmpeg -i input.mp4 \
-c:v libx264 \
-crf 28 \
-preset medium \
output.mp4
3. 인코딩 속도가 너무 느림
문제: 인코딩에 시간이 너무 오래 걸림 해결: 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 빠른 프리셋 사용
ffmpeg -i input.mp4 \
-c:v libx264 \
-preset veryfast \
-crf 23 \
output.mp4
# 또는 하드웨어 인코더 사용
ffmpeg -i input.mp4 \
-c:v h264_nvenc \ # NVIDIA GPU
-preset fast \
-crf 23 \
output.mp4
4. SPS/PPS 추출 실패
문제: MP4에서 SPS/PPS를 찾을 수 없음 해결: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Annex B 포맷으로 변환
ffmpeg -i input.mp4 \
-c copy \
-bsf:v h264_mp4toannexb \
output.h264
# 첫 100바이트 확인
xxd -l 100 output.h264
마무리
H.264는 2026년에도 여전히 표준입니다. 핵심 요약:
- NAL Unit: H.264 비트스트림의 기본 단위
- SPS: 전체 비디오 설정 (해상도, 프로파일, 레벨)
- PPS: 프레임별 설정 (엔트로피 코딩, 양자화)
- 프로파일: Baseline (모바일), Main (스트리밍), High (고품질)
- 레벨: 해상도와 프레임 레이트 제한 H.264를 선택하는 이유:
- ✅ 모든 기기 지원
- ✅ 하드웨어 가속
- ✅ 빠른 인코딩
- ✅ 특허 만료 (무료)
- ✅ 검증된 안정성 H.265를 선택하는 경우:
- 4K/8K 고해상도
- 저장 공간 중요
- 최신 기기만 지원
- 인코딩 시간 충분 실전 추천: 다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# 범용 웹 비디오 (YouTube, 블로그)
# 실행 예제
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v high \
-level 4.1 \
-crf 23 \
-preset medium \
-c:a aac -b:a 128k \
output.mp4
# 모바일 호환 (최대 호환성)
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v baseline \
-level 3.0 \
-crf 28 \
-preset fast \
-pix_fmt yuv420p \
-c:a aac -b:a 96k \
output.mp4
# 고품질 아카이브
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v high \
-level 5.1 \
-crf 18 \
-preset slow \
-c:a aac -b:a 192k \
output.mp4
다음 단계:
- 영상 스트리밍 프로토콜
- WebM 컨테이너 포맷
- FFmpeg 완벽 가이드 H.264는 앞으로도 수년간 표준으로 남을 것입니다! 🎬