FFmpeg — 25년간 미디어 세계를 지탱해온 스위스 아미 나이프
아키텍처, 코덱 추상화, 필터 체인, 하드웨어 가속까지 — FFmpeg의 내부 구조 해부
FFmpeg이 뭔가
FFmpeg은 CLI 도구이자 라이브러리 집합이다. "FF"는 Fast Forward, "mpeg"은 동영상 표준 그룹 이름에서 왔다. 2000년 Fabrice Bellard가 만들었고, 이후 Michael Niedermayer를 비롯한 수백 명의 기여자가 개발을 이어왔다.
한 줄로 요약하면: 거의 모든 미디어 포맷을 입력받아, 거의 모든 미디어 포맷으로 출력할 수 있다.
ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4
이 한 줄이 MOV 파일을 H.264 비디오 + AAC 오디오의 MP4로 변환한다.
핵심 컴포넌트
FFmpeg 프로젝트는 여러 바이너리와 라이브러리로 구성된다.
바이너리:
ffmpeg— 미디어 변환·인코딩의 메인 CLIffprobe— 미디어 파일의 메타데이터·스트림 정보 조회ffplay— SDL 기반 간이 미디어 플레이어
라이브러리 (libav*):
libavcodec— 코덱 구현체 (H.264, H.265/HEVC, VP9, AV1, AAC, Opus 등)libavformat— 컨테이너 포맷 처리 (MP4, MKV, WebM, FLV, HLS 등)libavfilter— 필터 그래프 (스케일링, 크롭, 오버레이, 색보정 등)libavutil— 공통 유틸리티 (수학, 픽셀 포맷, 에러 코드 등)libswscale— 픽셀 포맷 변환 + 스케일링libswresample— 오디오 리샘플링 + 포맷 변환libavdevice— 캡처 장치 입출력 (카메라, 마이크, 화면 캡처)
처리 파이프라인
FFmpeg의 데이터 흐름은 이렇다:
입력 → 디먹싱 → 디코딩 → 필터링 → 인코딩 → 먹싱 → 출력
- Demuxing (libavformat) — 컨테이너에서 개별 스트림(비디오, 오디오, 자막)을 분리. 압축된 패킷 단위로 추출한다
- Decoding (libavcodec) — 압축된 패킷을 raw 프레임으로 디코딩. 비디오는 YUV/RGB 픽셀 데이터, 오디오는 PCM 샘플로 변환
- Filtering (libavfilter) — raw 프레임에 필터 체인 적용. 스케일링, 크롭, 색보정, 텍스트 오버레이, 노이즈 제거 등
- Encoding (libavcodec) — 처리된 프레임을 다시 압축. 타겟 코덱·비트레이트·품질 설정에 따라 인코딩
- Muxing (libavformat) — 인코딩된 스트림을 컨테이너에 담아 출력 파일로 쓰기
스트림 복사(-c copy) 모드에서는 디코딩/인코딩을 건너뛰고 패킷을 그대로 재먹싱한다. 품질 손실 없이 컨테이너만 바꿀 때 쓴다.
코덱 추상화 구조
libavcodec의 핵심은 AVCodec 구조체다. 모든 코덱(H.264, HEVC, VP9, AV1, ...)이 동일한 인터페이스를 구현한다.
typedef struct AVCodec {
const char *name; // "libx264", "h264_nvenc" 등
enum AVMediaType type; // AVMEDIA_TYPE_VIDEO, AUDIO 등
enum AVCodecID id; // AV_CODEC_ID_H264 등
int (*init)(AVCodecContext *);
int (*encode2)(AVCodecContext *, AVPacket *, const AVFrame *, int *);
int (*decode)(AVCodecContext *, AVFrame *, int *, AVPacket *);
int (*close)(AVCodecContext *);
// ...
} AVCodec;
같은 코덱 ID(예: H.264)에 대해 여러 구현체가 존재할 수 있다:
libx264— 소프트웨어 인코더 (CPU)h264_nvenc— NVIDIA GPU 하드웨어 인코더h264_qsv— Intel Quick Synch264_vaapi— VA-API (Linux)h264_videotoolbox— macOS 하드웨어 인코더
사용자는 -c:v libx264처럼 인코더 이름만 바꾸면 된다. 나머지 파이프라인은 동일하게 동작한다.
필터 그래프
libavfilter는 방향 그래프(directed graph) 구조로 필터를 연결한다.
ffmpeg -i input.mp4 -vf "scale=1280:720,fps=30,eq=brightness=0.1" output.mp4
이건 세 개의 필터가 체인으로 연결된 것이다:
1. scale — 해상도를 1280x720으로 조정
2. fps — 프레임레이트를 30fps로 변환
3. eq — 밝기를 0.1만큼 올림
복잡한 필터 그래프는 여러 입력·출력을 가질 수 있다:
ffmpeg -i main.mp4 -i logo.png \
-filter_complex "[0:v][1:v]overlay=10:10[out]" \
-map "[out]" output.mp4
메인 영상 위에 로고를 오버레이하는 구조. [0:v]와 [1:v]는 각 입력의 비디오 스트림, [out]은 필터 그래프의 출력 라벨이다.
하드웨어 가속
FFmpeg은 하드웨어 가속을 hwaccel API로 추상화한다.
NVIDIA — NVDEC(디코딩) + NVENC(인코딩) + CUDA 필터
Intel — QSV (Quick Sync Video)
AMD — AMF (Advanced Media Framework)
VA-API — Linux 범용 하드웨어 가속
VideoToolbox — macOS/iOS
Vulkan — 크로스플랫폼 GPU 컴퓨팅
GPU 디코딩 → GPU 필터 → GPU 인코딩 파이프라인을 구성하면, 프레임이 GPU 메모리에서 벗어나지 않아 CPU-GPU 간 데이터 전송 오버헤드가 사라진다.
ffmpeg -hwaccel cuda -hwaccel_output_format cuda \
-i input.mp4 \
-vf scale_cuda=1280:720 \
-c:v h264_nvenc -preset p4 output.mp4
누가 FFmpeg을 쓰나
사실상 미디어를 다루는 거의 모든 서비스와 도구가 쓴다.
YouTube — 업로드된 영상의 트랜스코딩
Netflix — 콘텐츠 인코딩 파이프라인
Meta — 하루 수백억 회 실행 (VOD + 라이브스트리밍)
VLC — 재생 엔진의 핵심
OBS Studio — 스트리밍/녹화
HandBrake — 데스크톱 트랜스코딩
Plex/Jellyfin — 미디어 서버 트랜스코딩
FFmpeg 없이 현대의 미디어 인프라는 돌아가지 않는다. 25년 넘게 C로 작성된 300만 줄 이상의 코드베이스가 이 모든 걸 지탱하고 있다.
동작 흐름
Demuxing — 컨테이너에서 비디오·오디오·자막 스트림을 분리
Decoding — 압축 패킷을 raw 프레임(YUV/PCM)으로 디코딩
Filtering — 필터 그래프로 스케일링·크롭·색보정 등 적용
Encoding — 처리된 프레임을 타겟 코덱으로 재압축
Muxing — 인코딩된 스트림을 컨테이너(MP4/MKV/WebM)에 담아 출력