Trawling

아무도 설명해 주지 않는 ffmpeg 파이프라인 — 플래그 암기 대신 구조를 이해하기

ffmpeg 명령을 외워서 쓰는 대신, 내부의 7단계 파이프라인 구조를 이해하면 대부분의 플래그가 자연스럽게 읽힌다는 해설 기사입니다. demux·decode·filter·encode·mux 각 단계의 역할과, -c copy가 왜 순식간에 끝나는지 같은 실용적 판단 기준을 담고 있습니다.

본문

개발자라면 누구나 Stack Overflow에서 복사한 ffmpeg 명령 한 줄을 아무 이해 없이 실행해 본 경험이 있습니다. ffmpeg -i input.mov -vcodec h264 -acodec mp2 output.mp4 같은 주문은 동작하지만, 왜 어떤 변환은 눈 깜짝할 새에 끝나고 어떤 것은 CPU를 10분씩 갉아먹는지는 알려 주지 않습니다. 이 글은 그 답이 ffmpeg 내부의 파이프라인 구조에 있다고 설명합니다. ffmpeg는 Fabrice Bellard가 2000년에 만든 도구로, 이름은 'fast forward'와 MPEG(Moving Picture Experts Group)의 합성어이며, Chrome, Blender, YouTube, Vimeo 등 수많은 제품 안에서 인코드·디코드 엔진으로 동작하고 있습니다.

7단계 파이프라인

저자는 ffmpeg가 하나의 연산이 아니라 파이프라인이며, 모든 플래그는 그중 한 단계를 조정하는 것일 뿐이라고 말합니다. 단계는 다음과 같습니다. 첫째, Input으로 파일이 들어옵니다. 둘째, Demux 단계에서 demultiplexer가 컨테이너를 개별 스트림으로 분리합니다. 우리가 '비디오 파일'이라 부르는 것은 사실 비디오 트랙, 오디오 트랙, 자막 등이 하나의 파일에 인터리브된 것입니다. 셋째, Decode 단계에서 압축된 패킷이 무압축 원본 프레임으로 풀리며, 이것이 CPU를 많이 쓰는 구간입니다. 넷째, Filter 단계는 선택 사항으로, 밝기·대비·스케일링·자막 삽입처럼 실제 픽셀이나 오디오 샘플을 건드리는 유일한 단계입니다. 다섯째, Encode 단계에서 원본 프레임이 지정된 코덱으로 다시 압축됩니다. 여섯째, Mux 단계에서 인코딩된 스트림이 하나의 출력 컨테이너로 다시 인터리브됩니다. 일곱째, Output으로 결과 파일이 나옵니다. ffmpeg -i in.mp4 out.mp4는 이 전체를 합리적인 기본값으로 돌리는 것이고, ffprobe가 순식간에 끝나는 이유는 앞쪽 단계만 실행해 메타데이터를 출력하기 때문입니다.

-c copy가 빠른 이유

파이프라인을 이해하면 decode와 encode만이 비용이 큰 단계이고, demux와 mux는 바이트를 옮기는 부기 작업에 불과하다는 점이 드러납니다. ffmpeg -i input.mp4 -c copy output.mkv는 스트림을 건드리지 말고 재포장하라는 뜻으로, demux 직후 바로 mux로 넘어갑니다. 실제 비디오 바이트가 변하지 않으므로 품질 손실도 없고 즉시 끝납니다. mp4→mkv가 빠르고 mp4→webm이 느린 이유도 여기서 나옵니다. mp4와 mkv는 둘 다 H.264를 담을 수 있어 순수 재포장이 가능하지만, webm은 VP8/VP9/AV1을 요구하므로 전 프레임을 디코드 후 재인코드해야 합니다.

같은 원리로 읽히는 레시피들

이 원리를 적용하면 흔한 명령들이 주문이 아니라 자명한 조합이 됩니다. ffmpeg -i input.mov -c copy -ss 00:00:30 -t 00:00:10 clip.mov는 코덱을 바꾸지 않으므로 -c copy로 즉시 0:30부터 10초를 자릅니다. 여러 클립을 이어 붙일 때는 파일 목록을 concat demuxer에 넘기는 ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4를 쓰며, 역시 재인코드가 없습니다. 반면 ffmpeg -i input.mp4 -vf "scale=1280:720" -r 30 -b:v 2M -c:v libx264 output.mp4처럼 픽셀이나 코덱을 바꾸는 경우에는 -vf로 리사이즈하고, -r로 프레임레이트, -b:v로 비트레이트, -c:v libx264로 인코더를 지정하는데, 이들 모두 실제 decode→filter→encode를 강제하므로 느려집니다. 자막 입히기도 같은 원리로, .srt를 .ass로 변환한 뒤 -vf subtitles 필터로 프레임에 소각합니다.

판단 기준과 주변 도구들

저자가 제시하는 의사결정 트리는 단순합니다. 컨테이너만 바꾸면 -c copy, 코덱이나 크기를 바꾸면 -c:v libx264 -c:a aac, 구간만 자르면 -ss와 -t에 -c copy, 클립 결합은 concat demuxer, 해상도·프레임레이트·비트레이트 변경은 -vf scale·-r·-b:v, 자막 소각은 srt→ass 변환 후 -vf subtitles입니다. 또한 ffprobe는 코덱·해상도·길이·비트레이트 같은 메타데이터를 확인하는 도구이고, ffplay는 같은 라이브러리 기반의 최소 플레이어입니다. 이들 아래에는 libavcodec, libavformat, libavfilter 등의 라이브러리가 있어, 다른 소프트웨어가 CLI를 호출하는 대신 직접 링크해 씁니다. ffmpeg가 Chrome의 미디어 재생과 Blender의 비디오 편집을 떠받치게 된 이유도, 사실 CLI 도구가 아니라 CLI를 정문으로 가진 미디어 엔진이기 때문입니다.

원문: dev.to / 번역·요약: Trawling

참고 자료

오류 제보