ToyProject

[GAMST] VideoWriter와 fourCC, 코덱

Omoknooni 2024. 7. 5. 22:22

프로젝트 진행 중 input 영상 스트림에서 위험 구간을 탐지해 새로운 비디오 Clip 파일로 생성해주는 구간이 있었다.

이 부분에서는 OpenCV의 VideoWriter 클래스를 이용해 파일을 생성했다. 

# VideoWriter 객체 선언
out = cv2.VideoWriter(filename='out.mp4', fourcc=cv2.VideoWriter_fourcc(*'mp4v'), fps, frameSize)

# frame을 VideoWriter에 저장 (프레임 저장)
out.write(frame)

# 비디오 파일로 저장
out.release()

 

VideoWriter 객체 생성에는 저장될 영상의 파일명을 포함한 속성값을 지정해주어야한다.

  • filename : 파일명
  • Video_Writer_fourcc : FOURCC 코드
  • fps : 영상의 fps
  • (width, height) : 영상 프레임의 크기, 튜플값으로 정수값을 입력할 수 있으나, VideoCapture 객체에서의 width,height 값을 가져와 그대로 사용해줄 수 있다.

 

이렇게 VideoWriter 객체를 생성하고, frame을 write한 뒤, 객체를 release하면 비로소 비디오 파일이 생성된다.

비디오 Clip을 생성하는 파트에서 조금 고생했는데, 여기서 고민했던 부분은 다름 아닌 fourCC 코드 부분이였다. 

 

fourCC

이 fourCC는 저장될 비디오의 코덱을 지정하는 부분이다. 이는 "four Character Code"의 약자로, 4바이트 코드를 이용해 해당 비디오의 코덱을 나타낸다.

 

주요 fourCC 코드는 아래와 같다.

코덱명 fourCC 코드 컨테이너
MP4V mp4v .mp4
DivX MPEG-4 divx .avi, .mkv, .mp4
XVID MPEG-4 xvid .avi, .mkv, .mp4
Motion-JPG mjpg .mp4
H.264/AVC x264 .avi, .mkv, .mp4
AV1 avc1 .mp4, .webm

 

이밖에도 해당 사이트를 참고할 수 있다.

 

 

처음에는 이 값의 중요성을 크게 신경 쓰지 않고, mp4 파일 생성에 예시로 사용되는 값(`*(mp4v)`)을 그냥 가져다 썼었다.

그 결과 파일은 생성이 되었고, 내 로컬에서도 재생되는 것도 확인했었다. 

 

그러나 이 파일이 버킷 스토리지에 올라가고, 재생이 되지 않는 문제를 발견했다. 처음에는 버킷에 올릴때 Content-Type을 맞춰주지 않아 발생한 문제라고 생각했으나 결국 생성된 비디오 파일의 코덱의 문제인 것으로 확인되었다.

 

우리 프로젝트는 생성된 Clip파일을 웹 브라우저에서 재생할 수 있어야 했다. 즉, 웹 브라우저가 비디오 파일을 재생할 수 있는 코덱으로 파일이 생성되어야 한다는 것이다.

 

 

코덱과 컨테이너

비디오 파일을 처리함에 있어, 비디오 코덱을 알 필요가 있다. 코덱(Codec)은 영상 파일의 인코딩(Encode)과 디코딩(Decode) 작업을 처리하는 방식을 정의한 것이다.

즉, 코덱은 비디오 인코딩과 디코딩의 알고리즘으로 볼 수 있다.

 

그리고 컨테이너는 비디오, 오디오 등의 리소스를 하나로 묶어주기 위한 형태로, 껍데기로 볼 수 있다.

이러한 컨테이너는 우리가 흔히 아는 비디오 파일의 확장자 형태로 볼 수 있다. (.mp4, .wmv, .webm 등)

하나의 컨테이너는 여러 개의 코덱을 지원한다. 예를 들어 MP4 컨테이너는 H.264, AV1, MPEG-4 동영상 코덱을 지원하는 것을 볼 수 있다.

따라서 우리는 비디오 파일의 확장자만 보고 코덱을 직접 확인 할 수는 없는 것이다. 

코덱과 컨테이너

 

 

 

웹 브라우저에서의 비디오 재생과 지원하는 코덱과 컨테이너 타입에 관한 MDN 공식 문서를 참조하도록 하자

 

웹 비디오 코덱 가이드 - 웹 미디어 기술 | MDN

압축되지 않은 비디오 데이터는 그 크기가 엄청나기 때문에, 저장하거나 네트워크를 통해 전송하기 위해서는 아주 작게 압축해야 합니다. 압축되지 않은 비디오를 저장하는 과정을 상상해 봅시

developer.mozilla.org

 

그렇게 생성한 영상의 코덱이 문제인 것을 알고, 웹 브라우저에서 재생이 가능한 코덱 목록을 확인해 VideoWriter의 fourCC에 넣고 테스트를 해보았다.

그러나 python-opencv가 모든 코덱을 지원하지 않는다는 점을 알게 되었다.

 

 

그리고 코덱 별로 라이센스가 존재한다는 문제에 또 직면하게 되었다.

가장 먼저 생각했던 H.264(h264)는 코덱의 라이센스 문제 때문에 PIP로 설치한 openCV(python-opencv)에서 사용할 수 없다는 것이였다.

굳이 H.264 코덱을 사용하겠다라고 하면, 먼저 opencv에서 mp4v와 같은 코덱으로 비디오 파일을 생성한 뒤, ffmpeg로 H.264 코덱으로 변환을 해주는 작업을 해줘야한다는 것이다. 

이와 같은 작업은 매우 번거로울 뿐만 아니라 처리 속도가 우선시되는 우리 프로젝트에는 적합하지 않은 것으로 판단되어 제외를 시켰다.

 

그 다음으로 찾은 것이 VP9(vp09)이다. 코덱 라이센스 관련해서 찾아본 결과, 비슷한 이슈를 VP9로 해결한 경우를 발견하게 되었다. VP9의 경우, VideoWriter 동작이 되고, 브라우저상에서 재생이 가능한 것까지 확인하였으나, 처리 속도가 매우 떨어졌었다. 

 

그래서 마지막으로 찾은 것이 AV1(avc1)이였다.

이 코덱 역시, PIP로 설치한 python-opencv에서는 지원하지 않는 코덱이다. 하지만 conda 환경에서 conda-forge channel을 통해 opencv를 설치하면 사용할 수 있다는 것을 발견했다.

 

OpenCV video writer unable to find codec or "avc1"

I am trying to write a video with cv2 in Python3 and I get the following message: "Could not find encoder for codec id 27: Encoder not found". Here's my code: video_writer = cv2.VideoWriter()

stackoverflow.com

 

실제로 conda 가상환경을 만들고 requirements를 설치, conda-forge channel을 통해 opencv를 설치한 뒤 몇 가지 패키지를 더 설치하면 AV1 코덱을 사용할 수 있는 것을 발견했다.

apt install libegl1 libopengl0

 

AV1 코덱을 통해 Clip 파일을 생성하고 브라우저에서 재생할 수 있는 것을 볼 수 있다.