JS 공부/NestJS

[NestJS] Team NDD. 영상 인코딩~클라우드 업로딩까지의 험난한 여정(그리고 쓰지 못한 이유...)

장아장 2023. 12. 10. 15:59

오랜만에 올려보는 한짤 요약...

간단하게 팀 NDD에 대해서 설명을 해...주진 않겠다. 

궁금하면 팀 블로그를 보는 것도 방법이지!!!

 


왜 우리는 인코딩을 해서 클라우드 스토리지에 올리려는 계획을 세웠을까?

기존에는 클라이언트에서 녹화한 webm파일을 바로 클라우드 스토리지에 전송시키는 방식을 이용했다. 

이 방식은 

  1. 클라이언트가 백엔드에게 녹화한 면접 영상의 이름을 만들기 위한 데이터를 준다(우리는 질문 이름과 jwt토큰을 주었다)
  2. 백엔드에서는 해당 정보로 영상 이름(key : 회원이름_질문내용_uuidv4()을 url에 받을 수 있게 파싱했다)와, presigned-url(영상을 저장할 권한을 미리 담아둔 url)을 보내주었다. 
  3. 클라이언트에서 presigned url로 영상 저장을 요청하면 저장한 영상의 주소가 나온다. 
  4. 영상의 주소와 필요한 정보들을 담아 백엔드에 요청하면 백엔드는 이를 테이블에 담는다. 

이러한 과정이었다. 

분명 잘 될줄 알았다. 

근데 모바일 사파리에서 영상의 재생이 안된다!

 

 

실제로 사파리 환경에서는 webm이 아닌, mp4파일만을 재생 가능하게 지원해준다.

 

다른 애들은 다 지원해주는데...safari만 안해줘..

그래서!! 우리는 인코딩을 해보기로 했다. 


인코딩은 어케하누?

인코딩을 위한 과정을 생각해보았다.

  1. 클라이언트가 보내준 파일을 로컬에 받는다.
  2. 로컬에 받은 파일을 mp4(인코딩된 영상), png(썸네일)로 만들어준다. (이 때 webm파일을 지운다)
  3. 해당 파일들을 s3에 저장해준다. (이 때 mp4, png파일을 지운다)
  4. 저장된 경로로 객체를 만들어, type-orm으로 저장한다. 

이를 위해 우리가 준비해야 할 여러 라이브러리(nest 라이브러리로 안끝난다 젠장...)가 존재했다. 

 

  • ffmpeg : 리눅스 환경에서 파일을 인코딩해주는 역할을 한다. 
  • fluent-ffmpeg : nodejs환경에서 ffmpeg를 동작하게 해준다.(ffmpeg가 외부 환경에 존재해야 한다. 외부라고 말한 이유는 후에 보면 안다)
  • multer-s3, multer, s3 : 대용량 파일을 처리하고, 이를 s3(클라우드 스토리지는 모두 s3 라이브러리를 통해 동작 가능하다)로 처리할 수 있다. 

이제 이걸로 멧챠쿠챠 해보자!

하나씩 과정을 만들었다. 

1단계로 영상을 담아둘 디렉토리를 있는지 확인하고, 없다면 만들게 했다. 

이후에, 영상을 저장하는 로직을 진행시켰다. 

이후에 영상을 fluent-ffmpeg를 통해 인코딩해 저장하게했다. 

쓸모를 다한 webm파일은 가차없이 버리자. 

 

로컬에 존재하는 인코딩된 파일들을 s3를 이용해 전송시켜주자. 

 

우리는 AWS S3가 아닌, Idrive e2라는 클라우드 스토리지를 사용하는데, 해당 스토리지도 s3라이브러리로 동작 가능하다. 

region에 e2를 작성하고, endpoint를 해당 클라우드의 저장 경로로, 그다음에 credentials에 인증 정보를 담아준다. 

 

params를 정리해보자. 

{
    Bucket // 저장할 버킷의 이름,
    ACL //해당 파일의 공개여부,
    ContentType //저장할 확장자,
    Key //스토리지에서 파일을 저장할 이름,
    Body //저장할 데이터
}

 

이렇게 해서 저장을 하고, 완료된 인코딩 파일을 삭제시킨다. 

삭제 후, 실제 클라우드 스토리지의 공개된 파일 경로를 반환하는 방식으로 구현했다. 

 

군단해본사람? 악사 키워본사람?

이제 모든건 준비되었다. 

기존 로직에 이를 이어붙여 사용했다. 

이렇게 파일을 받고, 인코딩하고, 클라우드에 저장하고, 경로를 받고, 경로를 이용해서 테이블에 저장하는 로직까지 끝냈다. 

아래의 createVideo의 복잡한 부분은 기존 로직을 재사용하기 위해 이렇게 구현했다. 

이렇게 해서 컨트롤러에서 파일을 받아 저장을 진행했다. 

미들웨어를 등록해, 토큰을 파싱해 회원 정보로 만들어주는 로직도 이전에 등록해두었다. (이번 주제가 아니니 언급은 안하겠다)

영상 인코딩이 잘 되고, 테이블에도 저장이 잘 되는 것을 확인했다. 

 

문제는 이걸 도커로 배포할 때, 우리는 이를 사용할 수 없다. 

왜일까?

 

도커는 독립적인 작업 환경이다. 

즉, 도커 환경에서도 ffmpeg를 등록해주어야 한다.

 

도커 환경에서, 자신의 상황에 맞게 ffmpeg를 등록해주자.

이렇게 해서 배포 서버의 도커 환경에서도 진행이 가능하게 되었다.


근데 왜 안쓰는가?

 

돈은 중요하지 않지만, 계산상으로 너무 많은 돈이었다. 

무슨 뜻인가?

 

우리가 인코딩을 직접 해서 서버에서 처리할 경우,

서버비가 얼마나 나올까? 그리고 인코딩된 파일을 담아주는 클라우드 스토리지 비용도 있지 않을까?

 

여기에서 우리 팀은 크게 3가지 방향을 잡았다. 

  1. 인코딩 서버의 스케일 업
  2. 인코딩을 처리해주는 클라우드 스토리지를 사용하기
  3. webm파일을 유지하고 후에 전용 플레이어등을 구하기

라고 생각했을 때, 1번은 현재의 트래픽에서는 추가비용이 제일 클 것이라는 계산이 들었다

(당연한게, Idrive는 1년에 1TB를 사용해도 3만원밖에 청구하지 않는다. 서버비 >>>>>>>>> 클라우드 스토리지 상태이다)

 

그래서, 현재에서는 이전의 로직들과 이번에 만든 로직을 모두 유지하고 더 나은 방향성을 가지고 계산할 생각이다. 


앞으로는?

앞으로 이에 대한 비용 비교, 화질 개선 여부등을 파악해야 한다. 

현재 인코딩은 서버 기준으로 (비트레이트를 낮췄음에도) 영상 총 길이의 1.2배정도가 최소한으로 필요했다. 

이를 개선시킬 방법, 비용 계산등을 하고 더 나은 방향을 찾아야 할 것 같다. 

기술적으로 새로운 방향성을 만들어볼 좋은 기회였지만, 실 사용되지 못한 아쉬움은 어쩔 수  없다. 

 

그래도 공부했으니 다행이다. 

  • 도커 환경에서 리눅스 라이브러리 등록 방법
  • ffmpeg의 기능
  • 웹 브라우저들이 지원하는 영상 타입
  • 인코딩을 위한 플로우

를 공부해볼 수 있었다. 

 

앞으로도 재밌는거 많이 넣어봐야게따..

 

그럼...twenty thousand...🔥