FFmpeg의 커맨드는 언뜻 보기에는 복잡한 형식을 갖추고 있어 초심자가 익숙해지기까지 다소 시간이 걸리는 편이다. 나 또한 영상 위에 글귀와 이미지를 삽입하기 위해서, 올바른 커맨드 작성법을 찾아 수없이 조사하고 또 시행착오를 겪었다. 그러나 처음엔 복잡해보여도 천천히 내용을 이해해보며 프로젝트에 적용을 거듭하다보면 쉽고 편안해지기 시작하는 시점이 분명히 온다.
직접 부딫히며 알게 된 FFmpeg 커맨드에 관한 기본지식과 유의사항들을 모아서 기록해본다. 시간이 지난 후의 나 자신, 그리고 다른 FFmpeg에 입문하는 초심자에게 이 글이 도움이 되면 좋겠다.
기본적으로 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",
"아웃풋파일경로"
]
각 요소 내 스트링에는 공백이 없어야하는 점에 유의하자.
FFmpeg 커맨드는 반드시 인풋파일경로 => 편집관련 각종 옵션 => 아웃풋파일경로 순서를 지켜주어야 한다.
"-i",
"인풋파일경로",
// 미디어를 인풋.
"-r",
"25",
// 초당 프레임 매수
"-vf",
"scale=1280:720",
// 비디오필터로 스케일 옵션적용
"-y",
// 덮어쓰기 허용
"아웃풋파일경로/%01d.png"
// 저장할 경로를 지정 & 결과파일 이름설정. (%01d를 줌으로써 자동 넘버링)
"-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"),
// 저장할 경로를 지정 & 결과파일 이름설정
한가지 처리만 해주는 정적인 커맨드를 작성할 경우 크게 헷갈일 일은 없다.
다만 유저의 요청에 따라서 각종 필터를 동적으로 배열에 추가해주는 로직을 제작하는 경우가 있다. 이 때 꼭 순서대로 커맨드가 작성되도록 유의하도록 하자.
세미콜론(;)은 스트림별 편집을 구분한다.
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. 결과물을 받는다.
(...는 문법이 아닌 말줄임표이므로 유의)
글귀와 박스같이 두 종류의 필터를 함께 적용할 때 아래와 같은 실수는 피하자.
// bad
"-vf",
"drawbox...",
"-vf",
"drawtext...",
위처럼 -vf옵션과 파라미터를 한 쌍 이상 작성해줄 경우, 뒤쪽에 작성된 필터만이 적용된다.
// good
"-vf",
"drawbox...,drawtext...",
따라서 "-vf"와 파라미터는 한 쌍만 작성하고, 파라미터내부에 필터들을 콤마(,)로 분리해 나열해주도록 한다.
두 옵션의 차이점을 먼저 알아보자.
따라서 영상과 이미지를 합성하고자하는 경우, -filter_complex가 이용된다고 볼 수 있다. 그렇다면 합성된 결과물에 글귀를 삽입하고 싶다면 어떻게 할까?
// bad
"-filter_complex",
"...;[영상][이미지]overlay=옵션내용",
"-vf",
"drawtext...",
이렇게 작성하면 아름다운 에러를 볼 수 있을 것이다.
// good
"-filter_complex",
"...;[영상][이미지]overlay=옵션내용,drawtext...",
정답: -filter_complex의 합성 커맨드 뒤에 콤마로 추가.
위와 같이 [영상][이미지]overlay=옵션내용
뒤에 콤마(,)를 넣고 원하는 필터를 이어서 작성해주면 원하는 대로 적용된다.
만약 합성 전 단계의 이미지에 미리 글귀를 넣어주고 싶다면 어떻게 할까?
[이미지]drawtext...[글귀가있는이미지];[영상][글귀가있는이미지]overlay...
위와 같이 필터적용 구문을 작성한 후 세미콜론(;)으로 마쳤음을 알려준다. 이어서 합성단계가 진행된다. 글귀를 넣고난 이미지를 다음단계에서 활용하고 싶다면 [글귀가있는이미지]
처럼 결과물을 변수에 저장하는 것을 잊지말자.
당연하지만 먼저 작성된 필터요소가 가장 아래에 위치하게 된다. 따라서 각 요소를 작성할 때는 그 렌더링 순서를 고려하여 아규먼트를 작성해야 한다.
예를 들어 도형 위에 글씨를 렌더하고 싶을 경우, 도형 => 글씨 순서로 아규먼트를 작성해준다. 만약 이를 역순으로 작성한다면, 글씨가 도형 뒤에 숨겨져 보이지 않을 것이다.
이 정도의 내용만 알고 있어도 코드를 긁어와 적용하는 레벨은 졸업하고 어느 정도 스스로 명령어를 직접 짜거나 수정할 수 있게 된다. FFmpeg는 모든 영상편집도구의 기둥이라고 해도 과언이 아닌 중요한 프레임워크이니만큼 옵션과 필터 종류가 어마 무시할 정도로 많다. 따라서 원하는 편집이 있다면 공식문서에서 잘 찾아보고 코드에 적용해보자.
FFmpeg에 관해 퀄리티 높은 질답 게시글이 많은 웹사이트 소개