본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Node.js

Node.js ffmpeg(노드 ffmpeg 이미지, 워터마크, 섬네일, 구간 자르기, 영상 합치기)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2021. 7. 28.

 

Nodejs를 활용하여 동영상을 편집(이미지, 워터마크, 섬네일, 구간 자르기, 영상 합치기)하는 방법 입니다.

영상처리의 대가 ffmpeg를 사용하여 구현된 기능 입니다.

 

사전 작업으로 운영체제에 ffmpeg가 설치 되어 있어야 합니다.

해당 포스팅에서는 윈도우 환경에 ffmpeg를 다운로드 받아서 환경변수에 등록하여 사용 하였습니다.

환경변수에서 bin 디렉토리까지 잡아주면 됩니다.

 

아래 사이트에서 자신의 운영체제에 맞는 파일을 다운받아서 적용하세요.

https://ffmpeg.org/download.html

 

그리고 나서 2개의 라이브러리를 설치 합니다.

 * npm install ffmpeg

 * npm install fluent-ffmpeg

 

먼저 살펴볼 기능은 동영상에서 이미지를 추출하는 방법입니다.

기본적으로 ffmpeg 객체는 아래처럼 사용 합니다.

const ffmpeg = require('ffmpeg')

const targetMP4File = '디렉토리/sample.mp4'  //영상 파일

new ffmpeg( targetMP4File,  (err, video)=>{  //ffmpeg 객체 생성
    if (!err) {
    
    }
})

 

첫번째 파라미터로 영상이 위치하는 곳을 지정하여 주며 두번째 파라미터로는 콜백 행위를 지정 합니다.

new로 생성한 ffmpeg 객체는 Promise 형태의 값을 반환 하므로 then - catch 형식으로 작업 하여도 무방 합니다.

여기서는 콜백 행위를 통하여 기능을 설명 하겠습니다.

콜백에서도 Video 객체를 사용할 수 있고, Promise를 통해서도 Video라는 결과를 사용 할 수 있습니다.

 

동영상에서 이미지를 추출하려면 Video 객체에서 fnExtractFrameToJPG 함수를 호출하면 됩니다.

시간, 길이, 이름 등을 전부 지정하여 사용 할 수 있습니다.

 

기본적으로 3개의 파라미터가 필요 합니다.

  1) 이미지를 저장할 디렉토리 위치

  2) 이미지를 추출할 옵션

  3) 콜백함수

const ffmpeg = require('ffmpeg')

const targetMP4File = '디렉토리/sample.mp4'  //영상 파일
const to_img_file = '저장할디렉토리'
new ffmpeg( targetMP4File,  (err, video)=>{  //ffmpeg 객체 생성
    if (!err) {
        console.log(video.metadata)  //비디오 메타정보(시간, 길이, 형식 등등)

        //#0. 이미지 추출 옵션
        let img_option = {
            start_time : 0,
            frame_rate : 1,
            number : video.metadata.duration.seconds,
            file_name : 'file_%t_%s'
        }
        //#1. 동영상에서 이미지를 추출하기 (비동기 방식)
        video.fnExtractFrameToJPG(to_img_file, img_option, (error, files)=>{
            if(!error) console.log('finish imgs!')
        });       
    }
})

 

위 옵션은 시작시간(start_time) 0초, 자르는 프레임 비율(frame_rate)을 1초, 종료시간(number)을 비디오의 마지막  길이 까지로 지정한 모습 입니다.

파일이름(file_name)은 형식('%t')과 생성된 순서('%s')가 붙도록 하였습니다.

이를 실행하면 이미지 파일이 1초 단위로 잘려서 나오게 됩니다.

샘플 동영상에서 1초단위로 잘라서 이미지를 추출하여 보았습니다.

 

다음으로 동영상에서 오디오파일을 분리하는 방법 입니다.

오디오를 분리하는 함수는 fnExtractSoundToMp3라는 함수를 사용하면 되며, 이미지를 분리하였던 방식과 동일한 형태로 구현하면 됩니다.

2개의 파라미터가 필요 합니다.

  1) 오디오 파일 위치 + 파일명

  2) 콜백 함수

const ffmpeg = require('ffmpeg')

const targetMP4File = '디렉토리/sample.mp4'  //영상 파일
const to_audio_file = '디렉토리/sample.mp3'  //오디오 파일

new ffmpeg( targetMP4File,  (err, video)=>{  
    if (!err) {
        //#2. 동영상에서 이미지를 추출하기 (비동기 방식)
        video.fnExtractSoundToMP3(to_audio_file, (error, files)=>{
            if(!error) console.log('finish audio!')
        });       
    }
})

 

오디오 파일을 mp3형태로 분리하기 때문에 "디렉토리+파일명"을 첫번째 파라미터로 대입하였습니다.

옵션값은 따로 존재하지는 않습니다.

 

다음으로 워터마크(waterMark)를 추가하는 방법 입니다.

워터 마크는 동영상에 이미지를 추가하는 방법으로 4개의 파라미터가 필요 합니다.

  1) 워터마크 이미지 위치

  2) 워터마크를 추가한 뒤 동영상이 있는 곳 + 파일명

  3) 워터마크 옵션

  4) 콜백 함수

const ffmpeg = require('ffmpeg')

const targetMP4File = '디렉토리/sample.mp4'  //영상 파일
const water_mark_img = '디렉토리/이미지파일명.png'  //이미지 파일
const to_mp4_with_water_mark = '디렉토리/영상.mp4'  //영상 파일

new ffmpeg( targetMP4File,  (err, video)=>{  
    if (!err) {
    
        //#3. 워터마크 옵션
        let water_option = {
            position : 'SE',   //south east (남동쪽)
            margin_east : video.metadata.video.resolution.w * 0.1,  
            margin_sud : video.metadata.video.resolution.h * 0.1
        }    
    
        //#4. 동영상에 워터마크 추가하기 (비동기 방식)
        video.fnAddWatermark(water_mark_img, to_mp4_with_water_mark, water_option, (error, file)=>{
            if(!error) console.log('finish watermark!')
        })
    }
})

 

워터마크 옵션에서의 position 값은 영문 동서남북의 명칭에서 대문자를 표기한 내용 입니다.

총 9개의 값으로 되어 있습니다.

* 동서남북 : NE NC NW SE SC SW C CE CW

또한 여백(margin) 값을 줄 수 있으며 여백은 4개의 형태로 줄 수 있습니다.

해당 값은 픽셀값을 숫자로 대입 할 수 있습니다.

* 여백 : margin_nord, margin_sud, margin_east, margin_west

이를 적용한 동영상의 모습 입니다.

"마샤와 곰" 이라는 이미지를 넣어보았습니다..ppt로 작업한 이미지 입니다.. : - )

 

이제 동영상에서 시간을 설정하여 설정된 시간만큼 분리하는 방법 입니다.

시작 시간은 setVideoStartTime 함수를 사용하여 지정하여 주면 되고, 종료 시간은 setVideoDuration 함수를 호출하여 줄여주면 됩니다.

그리고 나서 마지막에 save 함수를 호출하면 파일이 저장되게 됩니다.

const ffmpeg = require('ffmpeg')

const targetMP4File = '디렉토리/sample.mp4'  //영상 파일
const to_changed_time_mp4 = '디렉토리/영상.mp4'  //영상 파일

new ffmpeg( targetMP4File,  (err, video)=>{  
    if (!err) {
    
        //#5. 시간 변경 하기 (비동기 방식)
        video
        .setVideoStartTime(3)  //시작시간
        .setVideoDuration(video.metadata.duration.seconds * 0.6)    //종료시간
        .save(to_changed_time_mp4, (error, file)=>{
            if(!error) console.log('change time!')
        })
    }
})

 

위 코드는 시작시간을 3초로 하고, 종료시간은 동영상 총 길이에서의 60%만큼만 구간을 설정하여 준 모습 입니다.

그렇게 하고 나서 저장을 통해 새로운 동영상 파일이 만들어지게 됩니다.

 

마지막으로 영상과 영상을 합치는 방법(concat, combine) 입니다.

영상을 합치는 경우에는 반드시 동영상 끼리의 인코딩, 형식유의하여야 합니다.

* 동영상 인코딩 변환 내용은 구글링하면 쉽게 찾을 수 있습니다.

그렇지 않는 경우 아래와 같은 에러를 만나게 됩니다.

영상 끼리의 인코딩 무척 중요 합니다!!!

 

동영상을 합치기 위해 fluent-ffmpeg 라이브러리를 사용 합니다.

해당 라이브러리에서 합칠 동영상을 넣어주고(add input) 마지막에 합치기(merge)를 하면 영상 n개가 1개의 파일로 합쳐지는 것을 볼 수 있습니다.

//#6. 동영상 병합하기
const fluent_ffmpeg = require('fluent-ffmpeg')

const concatMP4FileTmpPath = './tmp'   //임시 저장 디렉토리
const concatMP4FilePath = './concat/output.mp4'  //합쳐질 파일 위치,이름
const targetFiles = [  //합칠 파일 목록
    './one.mp4',
    './two.mp4',
]

let mergedVideo = fluent_ffmpeg()

targetFiles.forEach(element => {  //목록 추가하기
    mergedVideo = mergedVideo.addInput(element)    
})

mergedVideo.mergeToFile(concatMP4FilePath, concatMP4FileTmpPath) //파일 1개로 만들기
.on('error', function(err) {
    console.log('Error ::::  ' + err.message)
})
.on('end', function() {
    console.log('Finished!')
})

 

파일 입출력(file stream)에 의해서 해당 함수들 전부 비동기 방식으로 동작을 합니다.

필요에 따라 async, await, promise, 콜백 함수 등을 사용하면 되겠습니다.

관련된 소스코드를 아래 깃허브에 올려놓았습니다.

https://github.com/TaeSeungRyu/sample

 

이상으로 Nodejs를 통하여 간단하게 할 수 있는 영상처리 방법에 대해서 살펴보았습니다.

npm 사이트를 통해서 위 내용보다 훨씬 많은 사용방법, 함수 및 옵션에 대해 알 수 있습니다.

궁금한점 또는 틀린부분은 언제든 댓글, 메일로 연락주세요! 👻

 

* 위 내용을 응용하여 웹에서 영상을 간단하게 편집 할 수 있는 기능을 구현 해 보았습니다.

 - 웹 비디오 에디터 : https://lts0606.tistory.com/518

 

 

* ffmpeg 라이브러리 : https://www.npmjs.com/package/ffmpeg

* fluent-ffmpeg 라이브러리 : https://www.npmjs.com/package/fluent-ffmpeg

 

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글