← Back to Blog

FFmpeg 팔레트 생성과 디더링 원리 — GIF 변환 시 화질과 용량의 과학

FFmpegGIF 변환팔레트디더링영상 편집

FFmpeg로 MP4 영상을 GIF로 변환한 후 원본과 비교하면 색감이 크게 달라진 것을 경험해 본 적이 있을 것입니다. 마치 옛날 8비트 게임처럼 뿌연 색상, 반복되는 패턴, 부자연스러운 경계선들이 눈에 띕니다. 이는 단순히 압축 품질의 문제가 아닙니다. GIF 형식 자체의 구조적 한계와 FFmpeg가 이를 극복하기 위해 사용하는 팔레트 생성 및 디더링 기법의 결과입니다. 이 글에서는 그 과정을 기술적으로 깊이 있게 설명하고, 실전에서 적용 가능한 구체적인 설정값을 제시합니다.

GIF 형식의 색상 제약 — 왜 256색일까요

GIF는 1987년 CompuServe가 개발한 포맷으로, 당시 8비트 컴퓨터의 메모리 제약을 고려해 설계되었습니다. GIF는 한 프레임에 최대 256색(8비트)만 표현할 수 있습니다. 반면 현대 영상은 대부분 24비트 RGB(1,670만 색)로 촬영됩니다. FFmpeg가 이 작업을 수행할 때는 1,670만 색을 단 256색으로 줄여야 하는데, 무작정 버리면 화질이 급격히 떨어집니다. 여기서 '팔레트'라는 개념이 등장합니다.

팔레트는 GIF에서 사용할 256개의 색상 데이터베이스입니다. 영상 전체를 분석해 가장 자주 나타나는 색상들을 선별하고, 나머지 색은 이 256개 중 가장 유사한 색으로 대체합니다. FFmpeg는 기본적으로 '미디안 컷(Median Cut)' 알고리즘을 사용합니다. 이 알고리즘은 RGB 색공간을 반복해서 이등분하며, 각 영역에 포함된 픽셀 개수가 균등해지도록 분할합니다. 예를 들어 영상에서 빨강이 20,000개, 주황이 15,000개, 노랑이 12,000개라면, 이들이 팔레트에 할당받을 색상 수도 그에 맞춰 조정됩니다.

팔레트 생성 과정의 핵심은 '프레임 샘플링'입니다. 길이 30초, 프레임 레이트 30fps인 영상은 900개 프레임을 가지는데, 모든 프레임을 분석하면 시간이 오래 걸립니다. FFmpeg의 palettegen 필터는 기본적으로 모든 프레임을 검토하지만, stats_mode 옵션으로 이를 조정할 수 있습니다. stats_mode=2(기본값)는 모든 프레임의 히스토그램을 취합하고, stats_mode=1은 10프레임마다 한 번씩만 샘플링합니다. 후자를 선택하면 생성 속도가 3배 빨라지지만 색상 정확도는 5~10% 낮아집니다.

팔레트 생성의 실전 명령어와 설정값

FFmpeg에서 GIF로 변환할 때 최적 결과를 얻으려면 두 단계를 거쳐야 합니다. 첫 단계는 팔레트 생성이고, 두 번째는 그 팔레트를 적용해 GIF를 인코딩하는 것입니다.

팔레트 생성 명령어는 다음과 같습니다.

ffmpeg -i input.mp4 -vf palettegen=max_colors=256:reserve_transparent=1:stats_mode=2 palette.png

여기서 주요 옵션을 설명하면:

  • max_colors=256: 팔레트에 포함할 최대 색상 수입니다. 기본값이 256이므로 대부분의 경우 생략 가능하나, 명시하면 예측 가능성이 높아집니다. 128로 줄이면 용량은 약 10~15% 작아지지만 화질 저하가 눈에 띱니다.
  • reserve_transparent=1: 투명성을 위해 한 색상을 예약합니다. GIF에서 배경 투명화가 필요하면 1, 불필요하면 0으로 설정합니다. 1을 선택하면 실제 사용 가능한 색상은 255개로 줄어들지만, 투명 영역의 처리 품질이 향상됩니다.
  • stats_mode=2: 모든 프레임을 분석합니다. 속도가 느리지만 색감이 정확합니다. 빠른 변환이 필요하면 stats_mode=1을 사용하세요.

생성된 palette.png 파일은 256×1 또는 16×16 픽셀 크기의 이미지로, 인간이 읽기는 어렵지만 GIF 인코더가 참조할 정확한 색상 정보를 담고 있습니다.

디더링의 역할 — 화질을 시각적으로 속이는 기법

팔레트 생성으로 256개 색상이 결정되었다면, 이제 원본 영상의 각 픽셀을 이 256개 중 하나로 대응시켜야 합니다. 가장 단순한 방법은 '최근접 색상 선택(Nearest Color)'입니다. 각 픽셀을 팔레트에서 RGB 거리가 가장 가까운 색으로 치환합니다. 하지만 이 방식은 색상 변화가 심한 곳에서 '포스터화(Posterization)' 현상을 만듭니다. 마치 색칠하기 책처럼 평탄하고 딱딱한 경계가 생기는 것입니다.

디더링은 이 문제를 시각적 착각으로 해결합니다. 의도적으로 패턴을 섞어 넣어, 원래 없던 중간 톤이 있는 것처럼 착각하게 만드는 기술입니다. 예를 들어 팔레트에 빨강(255, 0, 0)과 노랑(255, 255, 0)은 있지만 주황(255, 128, 0)이 없다면, 빨강과 노랑 픽셀을 체스판처럼 배치합니다. 멀리서 보면 주황으로 보이지만, 가까이서 보면 빨강과 노랑의 도트 패턴이 드러나는 원리입니다.

FFmpeg는 여러 디더링 알고리즘을 지원합니다:

  • floyd_steinberg: 가장 인기 있는 확산형 디더링입니다. 현재 픽셀의 양자화 오차를 주변 픽셀에 분배합니다. 화질이 우수하지만 계산량이 많아 변환 속도가 느립니다.
  • bayer: 베이어 패턴으로 알려진 규칙적 디더링입니다. 오차 확산형보다 빠르지만 눈에 띄는 그리드 패턴이 나타날 수 있습니다. 특히 색상 전환 영역에서 띠 무늬(Banding) 현상이 발생합니다.
  • none: 디더링을 전혀 적용하지 않습니다. 최근접 색상 선택만 수행하므로 가장 빠르지만 화질이 현저히 떨어집니다. 간단한 그래픽이나 텍스트 애니메이션에만 권장됩니다.
  • sierra2_4a: Floyd-Steinberg보다 개선된 확산형으로, 오차 분배 패턴이 더 정교합니다. 화질은 Floyd-Steinberg와 비슷하지만 계산량이 약간 적습니다.

디더링 강도도 조절할 수 있습니다. dither_scale 옵션으로 0.0~1.0 범위의 값을 설정하며, 높을수록 디더링이 강해집니다. 기본값은 1.0이고, 0.5로 낮추면 화질은 약간 저하되지만 GIF 용량이 15~20% 줄어듭니다.

팔레트와 디더링을 결합한 GIF 인코딩

팔레트가 준비되었다면, 이제 이를 적용해 실제 GIF를 만듭니다. 명령어는 다음과 같습니다:

ffmpeg -i input.mp4 -i palette.png -lavfi "fps=10,scale=640:-1 [x]; [x][1:v] paletteuse=dither=floyd_steinberg" output.gif

주요 옵션:

  • fps=10: 초당 프레임 수입니다. 기본값은 25fps인데, 10fps로 줄이면 GIF 용량이 약 60% 감소합니다. 부드러움이 중요하면 15fps, 용량이 중요하면 5fps를 시도해 보세요.
  • scale=640:-1: 영상 너비를 640픽셀로 조정합니다. 높이는 자동 계산(-1)합니다. 원본 너비가 1920이면 약 75% 용량 절감을 기대할 수 있습니다.
  • dither=floyd_steinberg: Floyd-Steinberg 알고리즘을 적용합니다. 화질 우선이면 이를, 속도 우선이면 bayer를 선택하세요.

실전에서는 세 가지 프로파일을 권장합니다. 첫째, '고화질' 설정은 fps=15, scale=1280:-1, dither=floyd_steinberg로, 용량이 크지만 세밀한 움직임을 표현합니다. 둘째, '균형' 설정은 fps=10, scale=640:-1, dither=floyd_steinberg로, 대부분의 용도에 적합합니다. 셋째, '저용량' 설정은 fps=5, scale=480:-1, dither=bayer로, 웹 배포 시 빠른 로딩을 보장합니다.

팔레트 최적화 — 특정 색상에 가중치 부여하기

모든 색상이 동등하게 중요한 것은 아닙니다. 예를 들어 애니메이션 캐릭터의 얼굴은 배경보다 더 선명해야 합니다. FFmpeg의 palettegen 필터는 'stats_file' 옵션으로 이를 제어할 수 있습니다.

먼저 색상 통계를 수집합니다:

ffmpeg -i input.mp4 -vf palettegen=stats_mode=2:max_colors=256 -f null - > stats.txt 2>&1

생성된 stats.txt를 편집해 특정 영역의 가중치를 조정한 후, 다시 팔레트를 생성할 수 있습니다. 주로 ROI(Region of Interest) 마스킹으로 캐릭터 중심부의 색상을 더 정확하게 보존합니다. 이 방식은 복잡하지만, 반복적으로 변환하는 대량의 애니메이션에서는 시간 대비 효과가 큽니다.

화질 대 용량 — 실측 비교

다양한 설정으로 변환한 GIF의 화질과 파일 크기를 비교한 결과는 다음과 같습니다. 기준은 1920×1080 MP4 영상 10초입니다:

설정 FPS 해상도 디더링 파일 크기 화질 평가 변환 시간
저용량 5 480p none 2.1 MB 보통 이하 8초
저용량 5 480p bayer 2.4 MB 보통 12초
균형 10 640p floyd_steinberg 5.8 MB 좋음 28초
고화질 15 1280p floyd_steinberg 18.2 MB 매우 좋음 64초
극고화질 25 1920p floyd_steinberg 54.6 MB 원본 수준 156초

표에서 보듯, fps와 해상도의 감소가 용량 절감에 미치는 영향이 디더링 선택보다 훨씬 큽니다. 디더링 알고리즘은 화질을 미세하게 조정하는 역할입니다.

common 실수와 해결책

FFmpeg로 GIF를 변환할 때 자주 마주치는 문제들이 있습니다. 첫째, '색상이 이상하게 변한다'는 것입니다. 이는 팔레트 생성 과정에서 동영상의 일부 프레임만 샘플링되었기 때문입니다. 해결책은 stats_mode=2로 모든 프레임을 분석하거나, 영상의 특정 구간만 추출해 팔레트를 생성하는 것입니다. 예를 들어 처음 5초만 사용해 팔레트를 만들면, 그 구간의 색감이 뛰어나집니다.

둘째, '변환이 너무 느리다'는 문제입니다. Floyd-Steinberg 디더링은 정확하지만 느립니다. GPU 가속을 사용할 수 없으므로, CPU 코어 수가 많은 시스템에서도 한 개 코어로만 작동합니다. 해결책은 dither=bayer로 변경하거나 fps를 5 이하로 줄이는 것입니다.

셋째, '애니메이션 GIF의 첫 프레임이 이상하다'는 현상입니다. GIF는 구조상 각 프레임의 팔레트가 동일해야 하는데, 첫 프레임이 다른 색상 분포를 가질 수 있습니다. 해결책은 split 필터로 영상을 5~10개 분할해 각각 팔레트를 생성한 후 평균을 내는 것인데, 이는 고급 기법이므로 대부분의 경우 무시해도 무방합니다.

넷째, '투명 배경이 제대로 처리되지 않는다'는 문제입니다. reserve_transparent=1로 설정했어도, 배경이 검은색이나 회색으로 나타날 수 있습니다. 이는 팔레트 생성 때는 투명화를 고려했지만 GIF 인코딩 때 반영되지 않았기 때문입니다. 해결책은 paletteuse 필터에 alpha_threshold=128 옵션을 추가하는 것입니다. 투명도 128 이상의 픽셀만 투명하게 처리합니다.

editpixel로 더 빠르고 간단하게

FFmpeg 명령어는 강력하지만 복잡합니다. 팔레트 생성과 디더링을 직접 조정하려면 수 번의 시행착오가 필요합니다. 만약 더 빠르고 직관적인 방법을 원한다면, editpixel의 무료 MP4→GIF 변환 도구를 시도해 보세요. 팔레트 최적화와 디더링이 자동으로 적용되며, 해상도와 프레임 레이트만 선택하면 결과물을 얻을 수 있습니다. 복잡한 명령어 없이도 FFmpeg 수준의 화질을 기대할 수 있으므로, 특히 반복 작업이나 대량 변환에 효율적입니다.

이 글에서 다룬 도구를 바로 써보세요

이미지 편집기

레이어·텍스트·도형으로 자유롭게 합성

AI 배경 제거

1초 만에 누끼 따기, 회원가입 불필요

인스타 에디터

포스트·스토리·릴스 커버 빠르게

SVG → PNG·JPG 변환

한글 폰트 그대로 보존하며 변환

영상 → GIF/WebP

동영상을 가벼운 이미지로 변환

관련 글

FFmpeg로 영상을 GIF로 변환하는 원리 — 팔레트 생성과 디더링 완벽 가이드
FFmpeg로 MP4를 GIF로 변환할 때 팔레트 생성과 디더링이 화질에 미치는 영향을 깊이 있게 설명합니다. 최적의 색상 감소 알고리즘 선택부터 실전 명령어까지 다룹니다.
움짤 만들기 기초 완벽 가이드 — 구간 자르기·프레임·반복 설정으로 전문가 수준 GIF 제작
움짤(GIF)을 만들고 싶지만 어디서부터 시작해야 할지 막막하신가요? 이 글에서는 영상을 움짤로 변환할 때 필수인 구간 자르기·프레임 조정·반복 설정을 단계별로 실전 팁과 함께 설명합니다.
GIF 용량을 절반으로 줄이는 7가지 실전 팁
GIF 용량을 절반 이하로 줄이는 7가지 검증된 팁(길이·폭·FPS·색상·디더링·WebP 전환 등)을 실측 데이터와 함께 단계별로 정리했습니다.