FFmpeg 커맨드, 이해하며 쓰자

유키미아우·2023년 12월 8일
0

FFmpeg의 커맨드는 언뜻 보기에는 복잡한 형식을 갖추고 있어 초심자가 익숙해지기까지 다소 시간이 걸리는 편이다. 나 또한 영상 위에 글귀와 이미지를 삽입하기 위해서, 올바른 커맨드 작성법을 찾아 수없이 조사하고 또 시행착오를 겪었다. 그러나 처음엔 복잡해보여도 천천히 내용을 이해해보며 프로젝트에 적용을 거듭하다보면 쉽고 편안해지기 시작하는 시점이 분명히 온다.
직접 부딫히며 알게 된 FFmpeg 커맨드에 관한 기본지식과 유의사항들을 모아서 기록해본다. 시간이 지난 후의 나 자신, 그리고 다른 FFmpeg에 입문하는 초심자에게 이 글이 도움이 되면 좋겠다.


1. 형식을 이해하기.

기본적으로 FFmpeg 커맨드는 스트링과 공백(" ")으로 이루어져 있다.

  • 영상의 프레임을 이미지로 저장하는 커맨드 예시:
-i 인풋파일경로 -r 25 -vf "scale=1280:720" -y 아웃풋파일경로

그러나 자바스크립트을 이용한 프로젝트에서 FFmpeg를 이용할 때는 어떻게 해야할까?

NodeJS환경에서 child_process를 이용해 FFmpeg를 실행하는 경우, 스트링형태의 커맨드를 배열 내부에 적절히 담아 execFile함수의 두번째 파라미터로 전달하게 된다.

const 편집완료된파일 = execFile(ffmpegPath, 배열);

각 커맨드 옵션과 값은 공백을 기준으로 배열의 개별 요소가 된다.
따라서 위에 작성한 예시를 자바스크립트의 배열형식으로 아래와 같이 작성해줄 수 있다.

[
  "-i",
  "인풋파일경로",
  "-r",
  "25",
  "-vf",
  "scale=1280:720",
  "-y",
  "아웃풋파일경로"
]

각 요소 내 스트링에는 공백이 없어야하는 점에 유의하자.


2. 순서를 지켜서 작성하기.

FFmpeg 커맨드는 반드시 인풋파일경로 => 편집관련 각종 옵션 => 아웃풋파일경로 순서를 지켜주어야 한다.

예시 1 - 영상의 프레임을 이미지로 저장하는 커맨드:

"-i",
"인풋파일경로",
// 미디어를 인풋.
"-r",
"25",
// 초당 프레임 매수
"-vf",
"scale=1280:720",
// 비디오필터로 스케일 옵션적용
"-y",
// 덮어쓰기 허용
"아웃풋파일경로/%01d.png"
// 저장할 경로를 지정 & 결과파일 이름설정. (%01d를 줌으로써 자동 넘버링)

예시 2 - 영상의 프레임을 이미지로 저장하는 커맨드:

"-i",
"인풋파일경로",
// 0번째 미디어: 비디오
"-i",
"인풋파일경로",
// 1번째 미디어: 이미지
"-filter_complex",
`[1:v]scale=150:-1[scaled_sticker];[0:v][scaled_sticker]overlay=x=${stickerX}:y=${stickerY}`,
// 0번째 미디어(비디오) 위에 1번째 미디어(스티커)를 오버레이하는 파라미터. 스티커의 스케일 조절과 좌표 적용을 함께 해주고 있다.
"-y",
// 덮어쓰기 허용
"아웃풋파일경로/파일이름.mp4"),
// 저장할 경로를 지정 & 결과파일 이름설정

한가지 처리만 해주는 정적인 커맨드를 작성할 경우 크게 헷갈일 일은 없다.
다만 유저의 요청에 따라서 각종 필터를 동적으로 배열에 추가해주는 로직을 제작하는 경우가 있다. 이 때 꼭 순서대로 커맨드가 작성되도록 유의하도록 하자.


3. 필터에 사용되는 구분자들을 이해하기.

  • 세미콜론(;)은 스트림별 편집을 구분한다.
    ex) 자기소개 영상을 원본과 복제본으로 나누기;복제본을 편집하기;원본과 복제본을 blend
    자바스크립트의 ;와 닮은 구석이 있다.

  • 콤마(,)는 필터의 종류를 구분한다.
    ex) 글귀 삽입,도형 삽입

  • 콜론(:)은 필터의 세부내용을 표현하거나 구분한다.
    ex) 글귀X좌표:글귀Y좌표:글귀크기:글귀색상

위 이해를 토대로 공식문서에 올라와 있는 예시를 해부해보자.

ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT

ffmpeg -i INPUT
1. 여느 때처럼 -i 커맨드를 통해 INPUT을 받고 있다.

-vf "split [main][tmp];
2. -vf 옵션과 split [main][tmp]파라미터를 적용한 후 ; 세미콜론으로 편집을 마친다. 여기서부터 미디어가 두개로 쪼개져 main과 tmp으로 스트림분리가 되었다.

[tmp] crop=iw:ih/2:0:0, vflip [flip];
3. [tmp] 미디어에 크롭과 플립을 적용한다. 이후 결과물을 [flip]이라는 미디어명에 할당해주고 편집을 마친다.
여기서 두 필터를 콤마(,) 구분자로 열거해주고 있는 것을 볼 수 있다.

[main][flip] overlay=0:H/2"
4. [main]스트림과 [flip]스트림을 overlay해주었다.

OUTPUT
5. 결과물을 받는다.


4. 여러 필터를 적용할 때 주의사항

(...는 문법이 아닌 말줄임표이므로 유의)

필터와 파라미터 커맨드는 한 쌍만 작성한다.

글귀와 박스같이 두 종류의 필터를 함께 적용할 때 아래와 같은 실수는 피하자.

// bad

"-vf",
"drawbox...",
"-vf",
"drawtext...",

위처럼 -vf옵션과 파라미터를 한 쌍 이상 작성해줄 경우, 뒤쪽에 작성된 필터만이 적용된다.

// good

"-vf",
"drawbox...,drawtext...",

따라서 "-vf"와 파라미터는 한 쌍만 작성하고, 파라미터내부에 필터들을 콤마(,)로 분리해 나열해주도록 한다.

"-filter_complex"옵션과 "-vf"옵션은 중복사용하지 않는다.

두 옵션의 차이점을 먼저 알아보자.

  • -filter_complex는 여러개의 미디어를 이용한 편집에 사용한다.
  • -vf는 한가지 미디어를 이용한 편집에 사용한다.

따라서 영상과 이미지를 합성하고자하는 경우, -filter_complex가 이용된다고 볼 수 있다. 그렇다면 합성된 결과물에 글귀를 삽입하고 싶다면 어떻게 할까?

// bad

"-filter_complex",
"...;[영상][이미지]overlay=옵션내용",
"-vf",
"drawtext...",

이렇게 작성하면 아름다운 에러를 볼 수 있을 것이다.

// good

"-filter_complex",
"...;[영상][이미지]overlay=옵션내용,drawtext...",

정답: -filter_complex의 합성 커맨드 뒤에 콤마로 추가.

위와 같이 [영상][이미지]overlay=옵션내용 뒤에 콤마(,)를 넣고 원하는 필터를 이어서 작성해주면 원하는 대로 적용된다.

만약 합성 전 단계의 이미지에 미리 글귀를 넣어주고 싶다면 어떻게 할까?

[이미지]drawtext...[글귀가있는이미지];[영상][글귀가있는이미지]overlay...

위와 같이 필터적용 구문을 작성한 후 세미콜론(;)으로 마쳤음을 알려준다. 이어서 합성단계가 진행된다. 글귀를 넣고난 이미지를 다음단계에서 활용하고 싶다면 [글귀가있는이미지] 처럼 결과물을 변수에 저장하는 것을 잊지말자.


5. 렌더링 순서 지정.

당연하지만 먼저 작성된 필터요소가 가장 아래에 위치하게 된다. 따라서 각 요소를 작성할 때는 그 렌더링 순서를 고려하여 아규먼트를 작성해야 한다.
예를 들어 도형 위에 글씨를 렌더하고 싶을 경우, 도형 => 글씨 순서로 아규먼트를 작성해준다. 만약 이를 역순으로 작성한다면, 글씨가 도형 뒤에 숨겨져 보이지 않을 것이다.


이 정도의 내용만 알고 있어도 코드를 긁어와 적용하는 레벨은 졸업하고 어느 정도 스스로 명령어를 직접 짜거나 수정할 수 있게 된다. FFmpeg는 모든 영상편집도구의 기둥이라고 해도 과언이 아닌 중요한 프레임워크이니만큼 옵션과 필터 종류가 어마 무시할 정도로 많다. 따라서 원하는 편집이 있다면 공식문서에서 잘 찾아보고 코드에 적용해보자.

FFmpeg에 관해 퀄리티 높은 질답 게시글이 많은 웹사이트 소개

https://video.stackexchange.com/questions

profile
능동적인 마음

0개의 댓글