콘텐츠로 건너뛰기
Home » 예제로 알아보는 ffmpeg 필터 사용법

예제로 알아보는 ffmpeg 필터 사용법

ffmpeg는 비디오, 오디오, 이미지등 사람이나 기계로 만든 거의 모든 포맷의 미디어 데이터를 인코딩/디코딩/필터링할 수 있는 멀티미디어 프레임워크로 미디어 관련한 소프트웨어들에 거의 기본적으로 탑재되어 있다. ffmpeg는 명령줄 도구 형식으로도 사용할 수 있어서 간단한 사용법만 익혀 두면 은근 유용하게 사용할 수 있다.

ffmpeg는 실제로 엄청나게 많은 옵션들을 지원하며, 웬만한 영상 편집/변환 프로그램이 할 수 있는 일을 거의 다 할 수 있다고 보면 된다. 전체 옵션들은 문서화가 잘되어 있으며, 공식 위키에서도 굉장히 유용한 팁들을 찾을 수 있다. (영문임)

기본적인 변환 방법은 다음과 같다.

$ ffmpeg -i 소스파일  출력파일

특이하게 소스 파일앞에 -i 옵션을 붙여주고, 출력파일을 생성하도록 한다. 소스와 출력의 포맷은 파일의 것을 그대로 사용하고, 출력 파일의 경우에는 확장자를 보고 자동으로 처리해주기 때문에 실제로는 엄청 간단하게 사용할 수 있다.

  • ffmpeg -i source.mp4 sound.mp3 : 소스 영상의 오디오만 mp3 형식으로 추출한다.
  • ffmpeg -i source.mp4 img.gif : 소스 영상을 GIF 애니메이션으로 변환한다.

물론 GIF 이미지를 MP3오디오로 변환한다든가… 이런 건 안되겠지만, 거꾸로 GIF 이미지와 mp3 음원을 합쳐서 영상으로 생성하는 작업은 가능하다. 그외에 크기 변경, 워터마크 삽입, 영상연결등 웬만한 영상 편집 프로그램이 제공하는 기능을 명령줄에서 수행할 수 있다.


gif를 mp4 비디오로 변환하기

gif를 비디오로 변환하기 위해서는 다음과 같이 명령을 주면 된다. 이 때 -c:v h264는 비디오 인코딩에 H.264 코덱을 사용하겠다고 지정하는 것으로 생략하면 기본 인코더를 사용하게 된다. mp4가 아닌 다른 포맷 비디오로도 만들 수 있으며, 포맷을 직접 지정해도 되지만, ffmpeg는 생성할 파일의 확장자를 보고 자동으로 판단해준다. avi, mkv 등의 포맷으로도 만들 수 있다.

$ ffmpeg -i input.gif  -c:v h264 output.mp4

비디오를 GIF 파일로 변환

반대로 영상을 gif 파일로 변환하는 것도 가능하다. ffmpeg -i video.mp4 output.gif 이라고만 쓰면 된다. 다만, 현세대 대부분의 비디오는 극도로 높은 비율로 압축된 데이터이므로 이렇게 만든 GIF 파일은 엄청 크기가 커지게 된다. 따라서 크기를 변경하거나, fps를 조정하거나, 시작/끝 범위를 지정하는 등의 조정이 필요할 수 있다.

다음은 특정 비디오를 320px 폭으로 축소하고, 00분 24초부터 00분 40초까지의 구간을 초당 10프레임으로 변환하여 GIF로 바꾸는 예이다.

ffmpeg -ss 00:24 -to 00:40 -i input.mp4 -vf "fps=10,scale=320:-1" output.gif

그런데 이렇게 만들면 의외로 화질이 많이 떨어진다. 화질을 최대한 유지하고 싶다면 (그러면 그만큼 다시 용량은 커지겠지만) 몇 가지 방법이 있다.

  1. scale 필터를 사용할 때, flags=lanczos 옵션을 사용해서 보간 시 화질을 최대한 쨍하게 만든다.
  2. palettegen 필터를 사용해서, 사용될 컬러 팔레트를 만들어 디더링을 최소화한다.
  3. 생성된 팔레트를 palettgen 필터를 통해 사용한다.

이 동작은 단일 필터 파이프가 아닌 복합 필터 그래프를 사용해야 한다. 이 과정은 제법 복잡할 수 있다.

ffmpeg -ss 00:24 -to 00:40 -i input.mp4 \
  -lavfi "[0:v]fps=10,scale=320:-1:flags=lanczos,split=2[a][b];\
          [a]palettegen[c];\
          [b][c]paletteuse[d]"\
  -map "[d]" output.gif

필터그래프는 세미콜론(;)으로 구분되는 필터체인들로 구성된다.

  1. fps + scale + split 필터를 거쳐서 원본 비디오를 조정하고, [a], [b] 라는 두 개의 결과를 만든다.
  2. [a]를 사용해서 팔레트를 만들고 이를 [c]라 한다.
  3. 다시 [b][c]를 사용해서 팔레트를 적용해서 [d]를 만든다. 이 [d]가 팔레트의 최종 결과물이며, 이를 GIF 형식으로 저장하게 된다.

이렇게 복잡한 필터 그래프를 사용하지 않고 두 번에 걸쳐서 팔레트를 생성하고, 다시 팔레트와 비디오를 사용해서 GIF를 변환하는 작업도 할 수 있지만 (참고), 동일한 필터를 두 번씩 입력해야하는 부분은 번거롭다.

위의 명령을 간단히 msdos창에서 실행할 수 있도록 bat 파일로 작성하면 다음과 같다.

@setlocal
@set filter1="fps=10,scale=320:-1:flags=lanczos,split=2[a][b]"
@set filter2="[a]palettegen[c]"
@set filter3="[b][c]paletteuse[d]"
@ffmpeg -v warning -ss 0:0 -i %1 ^
	-lavfi "[0:v]%filter1%;%filter2%;%filter3%" -map "[d]"^
	-y %2
@endlocal

심화 – 필터의 작성 문법

심플 필터 그래프

1개의 필터 체인만을 사용하는 선형 필터 그래프를 심플 필터 그래프라고 한다. 심플 필터 그래프는 -vf 옵션이나 -af 옵션에서 사용되며, 개별 필터가 콤마로 연결된다. 오른쪽에 오는 필터는 왼쪽의 필터의 출력을 입력으로 받게 된다. 개별 필터는 양쪽에 입출력 전극이 달려 있는 장치로 보면 된다.

각 필터의 문법은 대략 다음과 같은 형태이다. 대괄호로 감싼 부분은 선택적이라는 뜻이며, 각 파트의 작성문법은 아래에 설명했다.

[LINKLABELS]FILTERNAME["="FILTER_ARGS][LINKLABELS]
  • 링크레이블은 필터가 받는 입력 및 출력의 이름을 정의한다. 입출력 레이블은 각각 대괄호로 감싸서 표시하며, 두 개 이상인 경우에는 별도의 구분자 없이 대괄호로 둘러싼 레이블들을 붙여서 쓴다. 앞서 처리된 필터에서 출력 이름으로 지정한 것이거나, [0:v]와 같이 “파일 인덱스:비디오/오디오구분”의 형식을 쓸 수 있다.
  • 필터이름은 적용할 필터의 이름이다. 간혹 뒤에 “@아이디”가 붙기도 한다.
  • 필터를 설정하는 파라미터가 있는 경우, 필터이름 뒤에 =을 쓰고 뒤에 붙인다.
    • 필터 파라미터가 단일 값으로 된 경우, 값만 쓴다.
    • 필터 파라미터가 키-값 쌍으로 된 경우 key=value 의 형식을 쓴다.
    • 여러 파라미터를 쓰는 경우에는 :으로 구분한다. (e.g. scale=scale:320:-1)
  • 필터의 출력에 레이블을 써서 이름을 붙일 수 있다. 출력이 여러 개인 필터의 경우 일부 출력에만 레이블을 지정할 수 있다.
  • 각각의 필터는 ,로 연결할 수 있다.

, 각 필터의 앞뒤로 대괄호로 둘러진 링크 이름이 오간다. 이를 통해 이전, 다음 필터에서 연결한다. 생략되는 경우, 다음 필터로 직접 연결된다. 또한 필터에서 지정한 레이블은 필터 옵션 구문 외에 다른 파라미터 구문에서도 사용될 수 있다.

ffmpeg -i input -vf "fps=10,scale=640:-1,hflip" output.mp4

위 예에서는 3개의 필터가 직렬로 연결되어 있다. 영상을 초당 10프레임으로 조정하고, 다시 640:-1로 조정한다. (세로가 -1이라는 것은 원본 비율을 유지한다는 의미이다.) 그리고 다운스케일된 영상은 다시 좌우를 뒤집는 필터로 넘겨저서 좌우가 반전된다.

복합 필터 그래프

복합 필터 그래프는 조금 더 복잡한 문법이나, 심플 필터그래프를 여러 개 사용하는 것이다. 단순 필터 그래프 내의 필터들이 직렬로 연결되어 있는데 비해, 복합 필터 그래프는 입력과 출력의 레이블을 지정하고, 입력 레이블을 출력하는 단순 필터 그래프를 먼저 실행하는 식으로 순서가 결정된다.

복합 필터 그래프는 여러 파일을 한 번에 연결/합성하거나, 혹은 출력이 2개 이상인 필터를 사용할 때 적용하며, -vf 대신 -lavfi 혹은 -filter_complex 옵션을 사용한다. 아래 예제는 split 필터를 사용해서 출력된 두 개의 소스를 각각 변환한 다음, hstack 필터를 사용해서 가로로 연결한 비디오를 만드는 예이다.

ffmpeg -i input -lavfi "[0:v]fps=10,scale=320:-1,split=2[x][y];\
  [x]hflip[a];\
  [y]detectedge[b];\
  [a][b]hstack=2[c]" -map "[c]" -y out.mp4

ffmpeg의 작동 방식

ffmpeg를 미디어 데이터를 처리하는 환경이라는 시점에서 볼 때, 미디어 데이터는 ffmpeg를 거치면서 다음과 같은 식으로 변환된다.

  1. 입력파일을 demuxer가 열어서 각 채널별로 인코딩된 데이터 패킷으로 변경한다.
  2. 다시 인코딩된 패킷은 각각의 디코더에 의해서 프레임으로 변환된다.
  3. 프레임에 대해 필터링을 적용한다. 필터는 프레임의 내부를 변환하여 다른 프레임을 생성한다.
  4. 변환된 프레임들을 다시 인코더가 패킷으로 변환한다.
  5. muxer에 의해 인코더가 뱉은 패킷을 파일 포맷에 맞게 싸넣는다.

프레임에 대한 데이터 변환처리와, 인코더를 변경하거나, 파일 포맷을 변경하는 등의 조작을 통해서 영상을 편집/합성하거나 트랜스코딩할 수 있다. 만약 같은 코덱으로 인코딩된 여러 파일을 하나로 합치거나, 혹은 영상의 오디오를 다른 트랙으로 변경하는 등의 편집을 하는 경우에는 디코딩/인코딩 과정을 생략할 수 있으므로 demuxer/muxer만 이 과정에 관여하게 되므로 처리 시간이 별로 소요되지 않을 것임을 예상할 수 있다.

태그: