<Express.js> fluent-ffmpeg

김민석·2021년 1월 20일
0

YouTube clone

목록 보기
29/54

youtube-clone을 진행하면서 문제를 만나게 됐는데요. 바로 사파리 브라우저에서의 영상 재생 문제입니다. 분명히 크롬에서는 정상적으로 재생이됐기 때문에 영상 자체의 문제는 아니라고 판단했습니다. 검색 결과 사파리에서 포맷형식에 따라 재생이 안된다는걸 알았고 저장한 영상을 mp4로 인코딩해주기로 생각하였습니다. 인코딩을 위한 도구로 fluent-ffmpeg를 찾았습니다.

설치

ffmpeg

%brew tap homebrew-ffmpeg/ffmpeg
%brew options homebrew-ffmpeg/ffmpeg/ffmpeg
그리고 마지막으로 원하는 옵션을 넣어서 다운 받으시면 됩니다. 원하는 옵션이 없으시다면 저랑 동일하게 입력해주세요.
%brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-fdk-aac

fluent-ffmpeg

ffmpeg를 쉽게 사용할 수 있게 도와주는 라이브러리 입니다.
%npm install fluent-ffmpeg

project

youtube
  |controllers
   *|videoController.js

videoController.js

import ffmpeg from 'fluent-ffmpeg';
//아래에서 이미 path라는 변수를 사용해서 stream이라는 변수명에 할당
import stream from 'path';

export const postUpload = (req, res) => {
    const {body:{title, description}, file:{path}} = req;
    // `../`를 넣어준건 __dirname은 videoController가 포함된 controllers까지 반환해주기 때문입니다.
    const command = ffmpeg(stream.join(__dirname, "../", path))
      .format('mp4')
      .save(`${stream.join(__dirname, "../", path)}.mp4`);
  
    const newVideo = await Video.create({
      fileUrl: `${path}.mp4`,
      title,
      description
    })  
    console.log(newVideo);
    res.redirect(`${routes.videoDetail(newVideo.id)}`);
}

보완

위에까지하고 정상적으로 사파리 브라우저에서도 동영상이 재생되는걸 확인했는데요. 한가지 문제가 인코딩에 걸리는 시간이 존재해서 인코딩 과정동안 동영상이 재생안되는 문제가 있습니다.문서를 더 읽어보고 fluent-ffmpeg process end를 찾았는데요. process가 끝나면 end event를 보내주는겁니다. 이걸 이용해서 process가 끝난후에 database에 video element를 등록하고 videoDetail로 redirect시켜 재생에 문제가 없도록 하겠습니다.

project

youtube
 *|middlewares.js
  |routers
   *|videoRouter.js
  |controllers
   *|videoController.js

middlewares.js

encodingVideo라는 middleware를 새로 정의해줍니다.
end event가 발생하면 next()를 실행합니다.

import ffmpeg from 'fluent-ffmpeg';
import stream from 'path';

export const encodingVideo = (req, res, next) => {
    const {file:{path}} = req;
    console.log(path);
    const command = ffmpeg(stream.join(__dirname, path))
    .format('mp4')
    .on('end', (stdout, stderr)=>{
        next();
    })
    .save(`${stream.join(__dirname, path)}.mp4`);
}

videoController.js

export const postUpload = (req, res) => {
    const {body:{title, description}, file:{path}} = req;
    
    const newVideo = await Video.create({
      fileUrl: `${path}.mp4`,
      title,
      description
    })  
    console.log(newVideo);
    res.redirect(`${routes.videoDetail(newVideo.id)}`);
}

videoRouter.js

encodingVideo를 middlewares로부터 임포트하여 middleware로 넣어줍니다.

import {encodingVideo} from '../middlewares.js';

videoRouter.post(routes.uploadVideos, uploadVideoMiddleware, encodingVideo, postUpload);

추가사항으로는 fluent-ffmpeg를 통해서 process-percentage도 받아올 수 있는데요. 업로드 하는 동안 퍼센티지를 띄울 수 있도록 하는것도 기회되면 추가하겠습니다.

profile
누구나 실수 할 수 있다고 생각합니다. 다만 저는 같은 실수를 반복하는 사람이 되고 싶지 않습니다. 같은 실수를 반복하지 않기 위해 기록하여 기억합니다.🙃

0개의 댓글