지난 몇 년간 저는 오디오 편집, 영상 편집 등 갖가지 멀티미디어 작업을 할 일이 정말 많았습니다. 유튜브 채널에 올릴 클립 제작, 음악 추출 및 변환, 자막 삽입까지 말이죠. 그럴 때마다 저는 명령줄에서 ffmpeg를 사용했고, 이 겸손한 프로그램의 놀라운 능력에 매번 새롭게 감탄하곤 했습니다.
그래서 이번에는 ffmpeg에 대한 좀 더 포괄적인 가이드를 작성해 보기로 했습니다. 다양한 작업과 기능을 목록화하고, 실제 사례와 활용 예시와 함께 설명해 보려는 것이죠. 2008년 플래시 편집 튜토리얼에서 ffmpeg를 처음 언급한 이후로 시간이 꽤 흘렀으니, 이제 최신 내용을 담은 새 글이 나올 때가 된 것 같습니다. 명령줄 기반이고 상당히 '덕후스러운' 주제이긴 하지만, 그만큼 재미있을 거라고 약속합니다. 함께 따라와 보세요.
기본 사항
ffmpeg는 사실상 모든 리눅스 배포판에서 사용할 수 있으며, 윈도우와 맥용 빌드도 존재합니다. 이 프로그램이 무엇을 할 수 있는지 알고 싶다면, 인수 없이 실행하거나 선택적으로 -hide_banner 플래그를 붙여서 실행하면 됩니다. 메인 프로그램뿐 아니라 수많은 하위 명령어에 대해서도 help 옵션을 사용할 수 있습니다. 처음에는 눈부시게 많은 기능 목록이 부담스러울 수 있지만, 천천히 차근차근 살펴보겠습니다. 그리고 공식 문서도 꼭 참고하세요. 생각보다 깔끔하게 정리되어 있습니다.
파일 변환과 트랜스코딩
가장 흔한 작업 중 하나는 파일을 한 형식에서 다른 형식으로 변환하는 것입니다. FLV 클립에서 오디오 파일을 추출하는 예제를 기억하시나요? 바로 그런 것입니다. 카메라로 촬영한 영상을 MP4로 변환하거나, OGG 파일을 MP3로 바꾸는 등 활용 시나리오는 무궁무진하며, ffmpeg가 지원하는 모드와 포맷 역시 끝없이 다양합니다. 일반적으로 다음과 같은 순서로 진행합니다:
- 입력 파일을 지정한다.
- 원하는 비디오/오디오 코덱을 지정한다.
- 출력 파일을 지정한다.
비디오 스트림을 건드리고 싶지 않다면 copy 코덱을 사용할 수 있으며, 오디오도 마찬가지입니다. 실제 인코딩은 변경하지 않은 채 컨테이너만 MOV에서 MP4로 바꾸고 싶을 때 특히 유용한 옵션입니다.
ffmpeg -i MVI_1348.MOV -c:v copy -c:a copy new.mp4
단, 모든 포맷이 모든 코덱과 옵션을 지원하지는 않기 때문에 항상 동작하는 것은 아닙니다. 예를 들면 다음과 같은 오류가 발생할 수 있습니다:
[mp4 @ 0x55a21519fb20] Could not find tag for codec vp8 in stream #0, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Last message repeated 1 time
특정 스트림(오디오, 비디오, 자막, 데이터)만 추출하고 싶다면, 나머지 스트림의 처리를 생략하여 시간과 CPU 자원을 절약할 수 있습니다. 예컨대 복합 미디어 파일에서 오디오만 뽑아내고 싶다면 -vn(비디오 없음) 옵션을 사용하면 됩니다.
ffmpeg -i MVI_1348.MOV -vn -ar 44100 -ab 192k sound-only.mp3
이 훌륭한 도구는 작업 방식에 있어 상당한 유연성을 제공합니다. 예를 들어 codec:v, vcodec, c:v는 모두 동일한 옵션이며, 어떤 것을 사용해도 무방합니다. 위처럼 오디오만 출력하고 싶다고 하면 ffmpeg는 의도를 추론해서 자동으로 -vn을 적용해 줍니다. -f 플래그로 출력 포맷을 강제 지정할 수도 있지만, 이 경우에도 도구가 명령어를 분석해 결과물을 추측해 줍니다. 예를 들어 -f mp3 또는 acodec mp3처럼 쓸 수 있습니다.
코덱마다 지원하는 옵션이 다릅니다. 오디오 파일이라면 샘플링 레이트, 비트레이트, 채널 수 등을 지정할 수 있죠. 일부 옵션을 생략하면 명령이 실패하거나 기본값이 적용됩니다.
크기 조절과 화질 설정
또 하나의 흔한 작업은 영상 크기(해상도)와 스트림 화질을 변경하는 것입니다. ffmpeg는 이를 여러 방식으로 수행할 수 있게 해 줍니다. 비율을 강제 지정하여(기본 종횡비를 깨면서) 설정할 수도 있고, 세로 또는 가로 값에 마법의 한정자를 붙여 종횡비를 유지할 수도 있습니다. 영상 테두리를 잘라내거나(crop), 스트림을 재인코딩하는 것도 가능합니다. 구체적인 예제를 살펴보겠습니다.
ffmpeg -i input.avi -c:v mpeg4 -vtag xvid -qscale:v 3 -c:a libmp3lame -qscale:a 4 output.avi
이 명령어가 하는 일을 분석해 보겠습니다. AVI 입력 파일을 MPEG4 비디오 스트림으로 트랜스코딩하며, 화질(qscale)을 3으로 설정했습니다. 일부 코덱의 경우 화질 범위는 1~31이며 1이 가장 높습니다. 여러 일반적인 입력 파일로 테스트해 본 결과, 최고 화질은 대체로 용량이 두 배가량 되었고, 3~4 수준에서는 약 20~30% 감소했습니다. vtag xvid는 MPEG-4 전용 옵션이며, 오디오에는 LAME를 사용했습니다.
ffmpeg -i MVI_1348.MOV -vfilters scale=1280:-1 -c:a copy scaled.mp4
이 예제는 비디오 스케일링(-vf 또는 -vfilters 사용 가능)을 보여주며, -1 한정자 덕분에 종횡비가 유지됩니다. 스트림 화질은 변경하지 않았고, 오디오 스트림은 단순히 출력 컨테이너로 복사됩니다. 원본 영상의 해상도가 지정한 값보다 높으면 다운스케일링, 낮으면 업스케일링이 됩니다.
이미지 추출, 결합, GIF 생성
ffmpeg는 미디어 유틸리티이지만 사진도 다룰 수 있습니다. 어차피 사진도 미디어이고, 영상이란 결국 움직이는 사진이니까요! 여러분이 원할 만한 작업들로는 영상에서 프레임을 추출해 고품질 썸네일을 만드는 것(동영상을 일시정지하며 허둥대거나 화면 캡처를 남발하는 것보다 훨씬 낫죠)이 있습니다. 반대로 정지 이미지들을 스톱모션 영상으로, 혹은 완전한 영상으로 합칠 수도 있습니다. 그리고 영상을 애니메이션 GIF로 변환하는 기능도 있는데, 웹에서 밈을 만들 때 상당히 유용합니다. 역시나 '밈스러운' 예제로 시연해 보겠습니다.
ffmpeg -i input.mp4 -r 1 -f image2 thumb-%3d.png
입력 파일을 지정하고, 프레임 레이트(여기서는 영상 1초당 이미지 1장)를 지정하고, 포맷(image2)과 출력 형식을 지정합니다. 여기서 약간의 트릭을 쓰는데, C 언어 코드를 본 적이 있다면 익숙할 겁니다. 썸네일 번호를 세 자리 숫자로 매기겠다는 뜻입니다. 자릿수는 원하는 만큼 정할 수 있지만, 추출될 이미지 개수보다 많게 잡는 것이 이상적입니다.

반대로 이미지를 영상으로 합치는 것도 매우 유사합니다:
ffmpeg -f image2 -i thumb-%3d.png stopmotion.mp4
프레임 레이트(24 또는 30 FPS 정도)를 지정할 수도 있지만, 이 부분은 가이드 후반부의 영상 속도 조절 섹션에서 더 자세히 다루겠습니다. 이미지 이야기가 나온 김에 크기 조절도 가능합니다:
ffmpeg -i thumb-004.png -vf scale=400:-1 test.png
애니메이션 GIF는 정말 흥미로운 주제인데, 만들기도 꽤 간단합니다. 입력 파일을 지정하고 출력 확장자만 .gif로 설정하면 됩니다. ffmpeg가 나머지를 자동으로 판단해 고품질 애니메이션 GIF를 만들어 줍니다.
ffmpeg -i MVI_6654.MOV test.gif

마지막으로 GIF의 반대 경우도 있습니다. 단일 이미지로 구성된 영상, 즉 고정된 미리보기 화면 위에 배경 음악이나 팟캐스트가 흐르는 영상을 만들고 싶을 수도 있죠. ffmpeg는 영리한 트릭으로 이것도 가능하게 해 줍니다.
ffmpeg -loop 1 -i thumb-001.png -i sound-only.mp3 -c:v libx264 -shortest video-static-image.mp4
두 개의 입력을 제공하는데, 첫 번째는 무한 반복(loop)되는 이미지입니다. 비디오도 재인코딩합니다. 이미지가 무한히 반복되도록 설정했기 때문에 -shortest 옵션이 필요합니다. 이 옵션은 가장 짧은 클립이 끝날 때 작업을 종료시키는데, 이 경우에는 오디오가 해당됩니다.
영상 분할과 결합
이것 역시 매우 유용한 시나리오입니다. 아주 긴 클립에서 필요한 몇 분, 혹은 몇 초만 잘라내야 한다면 ffmpeg가 필요한 부분을 잘라 줍니다. 반대로 여러 파일을 하나의 스트림으로 합치는 것도 가능합니다. 비디오와 오디오 모두요. ffmpeg는 시작과 끝 타임스탬프를 자유롭게 지정할 수 있어서 작업 방식에 폭넓은 선택권을 줍니다.
-t duration record or transcode "duration" seconds of audio/video
-to time_stop record or transcode stop time
-fs limit_size set the limit file size in bytes
-ss time_off set the start time offset
-sseof time_off set the start time offset relative to EOF
-seek_timestamp enable/disable seeking by timestamp with -ss
-timestamp time set the recording timestamp ('now' to set the
current time)
그러므로 다음과 같은 명령어를 시도해 볼 수 있습니다:
ffmpeg -i MVI_1348.MOV -ss 4 -t 4 spliced.mp4
이 명령은 입력 클립의 4초 지점부터 4초 길이만큼을 추출합니다. 짧은 표기법(4 = 4초)을 쓸 수도 있고, hh:mm:ss.mmm 형태의 전체 표기를 쓸 수도 있습니다. 밀리초 단위의 정밀도를 제공하므로 실무적으로 충분합니다.
파일을 합치는 것은 조금 더 복잡합니다. 기술적으로는 연결(concatenation, concat)이라 불리며, 잘라내기와는 작동 방식이 다릅니다. 명령줄에 합칠 파일들을 직접 나열하는 게 아니라, 아주 특정한 문법으로 파일 안에 기록한 뒤 ffmpeg가 그 파일을 읽도록 해야 합니다. 예를 들면:
ffmpeg -f concat -i list.txt -codec copy joined.mp4
list.txt 파일의 내용은 다음과 같습니다:
file 'part-1.mp4'
file 'part-2.mp4'
file 'part-3.mp4'
'file'이라는 단어와 작은따옴표 사용에 주의하세요. 절대 경로와 상대 경로 모두 사용할 수 있습니다. 파일 형식에 오류가 있으면 다음과 같은 에러가 표시됩니다:
[concat @ 0x555ca89c38c0] Line 1: unknown keyword 'part-1.mp4'
list.txt: Invalid data found when processing input
텍스트 파일 대신 명령줄에 파일 목록을 직접 넣으려고 하면:
part-1.mp4: Invalid data found when processing input
자막 삽입과 추출
VLC & 자막 관련 글을 기억하시나요? 명령줄이 겁나지 않는다면 ffmpeg로도 똑같은 일을 할 수 있습니다. 간단한 예로, 오디오와 자막 파일이 따로 있다면 추가 처리 없이 비디오 필터링 옵션만으로 해결할 수 있습니다:
ffmpeg -i input.avi -vf subtitles=subtitle.srt output.avi
좀 더 복잡한 사례로, 아래 명령어는 별개의 MP4 파일과 자막 파일을 받아 비디오를 트랜스코딩하면서 하나의 출력 파일로 합칩니다. -map 옵션(두 번 나오는 것이 오류가 아님)은 스트림들이 출력에 매핑되는 순서를 정의합니다. 그 다음에는 다소 헷갈릴 수 있는 코덱 지정이 등장합니다. 여러 스트림이 있기 때문에 우리는 비디오 부분만 조작하고 싶고, 오디오나 자막은 그대로 두고 싶은 것이죠.
이를 위해 -c copy로 모든 코덱을 복사하도록 지정한 뒤, -c:v로 이를 덮어쓰면 비디오 스트림만 트랜스코딩됩니다. libx264 코덱을 사용하기 때문에 가변 비트레이트를 위한 CRF(Constant Rate Factor) 옵션도 함께 쓰는데, 23으로 설정했습니다(손실 없는 0부터 최저 화질인 51까지). veryfast 프리셋은 상대적으로 작은 출력 파일을 만들어 줍니다.
ffmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4
자막 추출은 다음 형태로 수행합니다:
ffmpeg -txt_format text -i input.file out.srt
영상 빠르게 / 느리게 재생하기
이것도 흥미로운 활용 사례입니다. 누구든 영상을 2배속으로 돌린 뒤 Benny Hill 음악을 얹으면 크게 웃음거리가 되곤 하죠. 반대로 동작을 슬로모션으로 만들고, 여기에 스무딩 효과까지 더해 뚝뚝 끊기는 느낌 없이 자연스럽게 만들 수도 있습니다.
예를 들어 스톱모션 영상이 썸네일 15~20장으로만 구성되어 있다면 재생 시간이 1초밖에 되지 않습니다. 이를 5초로 늘리면 각 프레임이 5배 longer 표시되겠죠. 대신 추가 프레임을 '삽입'해 부드러운 슬로모션처럼 보이게 만들 수 있습니다. 과거 인테리어 디자인 갤러리 프로젝트에서 이런 작업을 한 적이 있는데, 당시에는 AviSynth와 VirtualDub를 사용했습니다.
비디오 속도 필터는 각 프레임의 PTS(Presentation Timestamp, 표시 타임스탬프)를 변경하는 방식으로 작동합니다. 간단히 말해, 1보다 작은 값은 영상을 빠르게 하고, 1보다 큰 배율은 느리게 합니다. 속도를 높이면 ffmpeg가 프레임을 버리는데, 더 높은 프레임레이트를 지정할 수도 있습니다. 원본을 유지하려면 입력 FPS에 사용 중인 1/PTS 값을 곱하면 됩니다. 24FPS 클립을 2배속으로 만든다면 48FPS 레이트를 사용해야 하는 식입니다.
ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4
ffmpeg -i input.mp4 -r 96 -filter:v "setpts=0.25*PTS" output.mp4
ffmpeg -i input.mp4 -filter:v "setpts=2*PTS" output.mp4
영상 스무딩은 좀 더 복잡합니다. 필자도 문서를 참고해야 했습니다. 본질적으로 5배 느려진 영상(원본보다 5배 길어짐)에는 비디오 보간(interpolation)을 사용해 스무딩 효과를 만듭니다. 여기서도 FPS를 지정해야 ffmpeg가 프레임 사이를 추론할 충분한 데이터를 확보합니다. 5배 슬로모션의 경우 원본 속도의 5배인 5x24 FPS, 즉 120FPS가 필요합니다.
ffmpeg -i input.mp4 -filter:v "minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120'" output.mp4
이 작업은 CPU를 집중적으로 사용하며 완료까지 시간이 걸릴 수 있습니다. 필자는 ffplay로 영상을 미리 확인해 봤는데 결과가 꽤 괜찮았습니다. 다만 무에서 유를 창조할 수는 없으므로, 이 기능은 누락된 데이터가 적을 때(매 2초마다 프레임 1개씩 사라지는 수준이 아니라면) 잘 작동합니다.
오디오에는 atempo를 사용할 수 있습니다. 이 옵션의 범위는 0.5~2.0으로, 최대 절반 또는 2배 속도까지만 지원하지만, 여러 atempo 필터를 연결(chaining)하면 추가적인 속도 변경이 가능합니다. 예를 들면 아래와 같습니다:
ffmpeg -i input.mp4 -filter:a "atempo=2.0,atempo=2.0" -vn output.mp4
이것으로 이번 튜토리얼을 마치겠습니다.
마무리
이 글이 유익하고 즐겁고 실질적인 도움이 되었기를 바랍니다. ffmpeg는 리눅스에서 오디오·비디오 작업을 위한 일꾼입니다. 아니, 기병대 전체라고 해도 좋죠. 실용적인 도구, 옵션, 설정이 너무 많아서 입문 자체가 혼란스럽고 위압적으로 느껴질 수 있습니다. 하지만 이 튜토리얼을 끝까지 읽으셨다면 그런 감정은 이미 사라졌을 겁니다.
이번 글에서는 변환과 트랜스코딩, 크기 조절과 화질, 이미지 추출·결합·GIF 생성, 영상 분할과 결합, 자막 추출과 삽입, 영상 속도 조절 등을 다뤘습니다. 한동안 여러분을 즐겁게 바쁘게 해 줄 만한 내용들입니다. ffmpeg 관련 요청이나 질문이 있다면 언제든지 메일로 연락해 주세요. 그리고 이 튜토리얼이 정말 유용했다면, 약간의 사랑을 보내 주시는 것도 잊지 마세요.
감사합니다.