본문 바로가기
Dev/Go

FFmpeg 라이브러리로 구현하는 동영상 처리 모듈: 문제 해결 전략 및 분석

by Sovereign 2024. 8. 11.

기능 요구 사항 정의

  • 동영상 업로드
  • `명령` 동영상 컷 편집 (Trim)
  • `명령` 동영상 이어 붙이기 (Concat)
  • `명령` 작업 수행
  • 최종 동영상 다운로드
  • 동영상 및 작업 조회

위와 같은 6가지의 기능 요구 사항이 주어졌다.

 

주목해서 살펴본 점은 `명령` 관련 요구사항이다.

모든 `명령`은 즉각적으로 ffmpeg command를 실행하여 연산을 수행하지 않습니다.
별도의 `명령 작업 수행`이 있어야 concat, trim 등의 연산을 수행합니다.

 

`명령 작업 수행`은 Queue 개념과 유사하다고 판단했는데 그 근거는 다음과 같다.

 

여러 개의 동영상 처리 작업을 순차적 또는 동시에 실행하는 프로세스이며, 작업이 완료될 때까지 대기하거나, 작업이 실패했을 때의 상태 관리 등이 Queue 시스템과 유사하다.

 

Queue 개념을 유사한 점을 살펴보면 다음과 같다.

 

 

작업 큐잉: 여러 작업(예: Trim, Concat 등)이 요청되면, 이를 Queue에 넣고 하나씩 순차적으로 처리하거나 동시에 병렬 처리할 수 있다.

 

상태 관리: 동영상의 상태가 pending, in_progress, completed, failed와 같이 관리되며, 이는 Queue에서 작업의 상태를 모니터링하는 것과 비슷하다.

 

 

핵심 비즈니스 로직의 포인트를 판단했으니 API Endpoint를 설계해 보자.

 

 

API Endpoint

| HTTP Method | URI                       | Description              |
|-------------|---------------------------|--------------------------|
| `POST`      | `/api/videos`               | 동영상 업로드                  |
| `POST`      | `/api/videos/{id}/trim`     | `명령` 동영상 컷 편집 (Trim)     |
| `POST`      | `/api/videos/concat`        | `명령` 동영상 이어 붙이기 (Concat) |
| `POST`      | `/api/jobs/execute`         | `명령` 작업 수행                 |
| `GET`       | `/api/videos/{id}/download` | 최종 동영상 다운로드              |
| `GET`       | `/api/videos`               | 동영상 및 작업 조회              |

 

구현해야 되는 분량 자체는 많지 않다.

 

API Endpoint 설계를 진행하며, 간략하게 내부 비즈니스 로직을 어떻게 구현할까 고민해 봤는데 Go 언어에서 os/exec 패키지를 활용해 FFmpeg 명령어들을 실행할 수 있다. 덕분에 별도의 FFmpeg 라이브러리를 학습할 리소스 누수를 방지할 수 있었다.

 

기능 요구 사항 결론

  • 구현하기 크게 난해한 요구 사항은 없지만 ffmpeg (영상 스트림) 도구를 처음 사용해 보기에 별도의 POC가 필요해 보인다.

  • 기능 요구 사항을 깊게 이해하기 위해서는 해당 도메인에 대한 이해도가 필수적이다.
    • 유사 플랫폼 및 도메인 용어에 대해 학습이 필요하다.

 

 

 

기술 요구 사항 정의

개발 언어를 선택한 이유

Go (Golang)을 선택했다. 실무에서 현재 사용 중인 언어이기도 하며, os/exec 패키지를 활용해 FFmpeg 명령어들을 실행할 수 있기 때문에 제한된 리소스 (일정)를 고려했을 때 가장 퍼포먼스가 좋게 나올 것이라 판단했기 때문이다.

 

 

API 특성을 고려하여 API Endpoint를 설계한 방법

RESTful API 원칙을 지키기 위해 적용된 3가지 요소를 적용했다.

 

자원의 명사 사용

  • 모든 URI는 자원(videos, jobs)을 명사로 명확하게 표현했다.
  • 예를 들어, /api/videos는 동영상 자원을 의미하며, /api/jobs는 작업 자원을 의미한다.


HTTP 메서드의 적절한 사용

  • 각 URI에 적절한 HTTP 메서드를 사용했다.
  • 예를 들어, 동영상 업로드를 위한 POST, 동영상 목록 조회를 위한 GET 등 적절하게 매핑했다.

 

자원 기반의 URI 설계

  • URI는 명확하게 자원과 하위 자원의 관계를 표현했다.
  • 예를 들어, /api/videos/{id}/trim는 특정 동영상의 트림 작업을 의미하며, /api/videos/{id}/download는 특정 동영상의 다운로드를 의미한다.

 

 

FFmpeg (영상) 스트림 도구를 어떻게 사용할 것인가

  • 본 내용은 "FFmpeg 및 ffprobe 명령어 분석" 섹션에서 다루겠다.

 

 

데이터 저장소를 선택한 이유

데이터 저장소 선택과 관련하여 로컬 환경에서 작업을 진행하기로 결정했다.

코딩 테스트의 주요 평가 포인트가 기술 스택의 복잡성보다는 핵심 기능 구현에 있다고 판단했기 때문이다.

 

데이터베이스로는 현업에서 사용 중인 MariaDB를 선택하였으며, 이를 기반으로 데이터 모델링을 설계 및 로컬 환경에서의 동영상 저장 및 관리 기능을 간단하게 구현했다.

 

 

 

문서화 도구를 선택한 이유

문서 자동화 도구로는 Swagger를 선택했다.

 

Local 환경 및 Dev 환경에서는 Postman이 개발자 입장에서는 더욱 친숙하지만 평가자 입장에서는 Swagger UI가 좀 더 가독성 있을 것이라 판단해 선택했다. Postman 실행시켜서 body 섹션에서 일일이 JSON 작성하면서 동작을 평가하기에는 너무 가혹하지 않은가.

 

 

 

FFmpeg 및 ffprobe 명령어 분석

FFmpeg는 다양한 멀티미디어 파일을 처리하기 위한 강력한 도구이며, ffprobe는 멀티미디어 파일의 정보를 분석하는 도구이다.

 

FFmpeg 및 ffprobe 명령어를 Go 언어에서 활용하는 방법을 알아보자.

 

 

FFmpeg 명령어로 동영상 자르기 (Trim)

cmd := exec.Command(FFMPEG_PATH, "-i", inputPath, "-ss", startTime, "-to", endTime, "-c:v", "libx264", "-c:a", "aac", "-strict", "-2", outputPath, "-y")

 

동영상을 특정 구간만 자르는 작업은 위와 같은 FFmpeg 명령어로 수행할 수 있다.

`os/exec` 패키지를 사용해 실행되며, 동영상을 지정한 구간으로 자르고, 원하는 코덱으로 인코딩하여 결과를 저장한다.

 

  • -i: 입력 파일을 지정합니다.
  • -ss: 시작 시간을 설정합니다.
  • -to: 종료 시간을 설정합니다.
  • -c:v, -c:a: 비디오와 오디오 코덱을 설정합니다.
  • -strict -2: 오래된 옵션을 허용하기 위한 플래그입니다.
  • -y: 출력 파일이 이미 존재할 경우 덮어쓰기를 허용합니다.

 

 

 

FFmpeg 명령어로 동영상 결합하기 (Concat)

cmd := exec.Command(FFMPEG_PATH, "-f", "concat", "-safe", "0", "-i", listFilePath, "-c:v", "libx264", "-c:a", "aac", "-strict", "-2", "-movflags", "+faststart", outputPath, "-y")

 

여러 개의 동영상을 하나의 파일로 결합하는 작업 역시 FFmpeg를 통해 가능하다. 입력 파일 리스트를 텍스트 파일에 작성하고, 해당 리스트를 FFmpeg로 전달한다.

 

  • -f concat: 입력 파일이 결합할 파일 리스트임을 지정합니다.
  • -safe 0: 파일 경로에 특수문자가 포함될 수 있음을 허용합니다.
  • -movflags +faststart: 웹에서 스트리밍 될 수 있도록 MP4 파일을 준비합니다.

 

 

 

FFprobe 명령어로 동영상 길이 추출하기

cmd := exec.Command("ffprobe", "-i", filePath, "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1")

 

동영상의 길이를 추출하려면 위와 같은 명령어를 사용하면 된다. 파일의 길이를 초 단위로 반환하며 출력을 파싱 하여 파일의 길이를 얻을 수 있다.

 

  • -i: 입력 파일을 지정합니다.
  • -v error: 오류 메시지만 출력하고 나머지는 무시합니다.
  • -show_entries format=duration: 파일의 전체 길이를 출력합니다.
  • -of default=noprint_wrappers=1:nokey=1: 출력 형식을 설정합니다.

 

 

 

동영상 플랫폼 도메인 지식 정리

FFmpeg

FFmpeg는 동영상 플랫폼의 핵심 도구 중 하나로, 비디오와 오디오 파일의 변환, 스트리밍, 인코딩, 디코딩 등 다양한 작업을 수행할 수 있다. 많은 포맷과 코덱을 지원하며, 특히 서버 사이드에서 비디오를 처리하는 데 적합하다.

 

오픈 소스라는 이점이 있으며, 플랫폼에서 사용자 업로드 비디오의 포맷 변환, 해상도 변경, 비트레이트 조절, 특정 구간 트리밍 및 결합 등을 수행하는 데 주로 사용된다.

 

 

FFprobe

FFprobe는 비디오 파일의 메타데이터를 분석하고 정보를 추출하는 데 사용된다. 비디오의 해상도, 코덱, 비트레이트, 프레임 레이트 등의 정보는 서버에서 비디오를 처리하거나 최적화할 때 사용된다. 예를 들어 사용자가 업로드한 비디오의 기본 정보를 추출해 데이터베이스에 저장하고, 이후 비디오 처리에 사용할 수 있다.

 

매우 상세한 메타데이터를 제공하며, JSON이나 XML 등 다양한 포맷으로 출력할 수 있어 시스템과의 연동이 용이하다는 장점이 있다.

 

 

Video Encoding/Decoding

비디오 인코딩은 비디오 데이터를 압축하여 저장하거나 전송할 수 있는 형태로 변환하는 과정이며, 디코딩은 이를 다시 원래의 형태로 복원하는 과정이다. 고효율 비디오 코덱(HEVC, H.264, VP9 등)은 대역폭을 줄이고, 저장 공간을 효율적으로 사용하면서도 높은 화질을 유지한다.

 

코덱: 비디오 코덱은 인코딩 및 디코딩의 규칙을 정의한다. H.264는 현재 가장 널리 사용되는 코덱 중 하나로, 대부분의 기기에서 지원된다. VP9와 H.265(HEVC)는 고효율 압축을 제공하지만, 지원 범위가 H.264에 비해 제한적일 수 있다.

 

스트리밍 플랫폼에서 사용자가 업로드한 비디오를 다양한 해상도와 비트레이트로 인코딩하여, 네트워크 조건에 따라 적절한 품질로 스트리밍 한다.

 

 

Video Editing Concept (trim and concat)

비디오 편집은 사용자가 업로드한 비디오 파일을 특정 요구사항에 맞게 수정하는 과정이다. 가장 기본적인 작업으로는 비디오의 특정 구간을 잘라내는 트리밍(Trim)과 여러 비디오 파일을 하나로 결합하는 콘캣(Concat)이 있다. 실시간 스트리밍 서비스에서 사용자가 요청한 구간만 스트리밍 하거나, 다수의 비디오 파일을 하나의 콘텐츠로 제공할 때 주로 사용된다.

 

Trim: 비디오의 시작 시간과 종료 시간을 지정하여 불필요한 부분을 제거한다. 이 작업은 비디오를 필요한 구간으로 축소하여 스트리밍이나 다운로드에 최적화할 수 있다.

 

Concat: 여러 비디오 파일을 순차적으로 결합하여 하나의 파일로 만든다. 이 작업은 여러 클립을 하나의 비디오로 제공하거나, 에피소드 시리즈를 결합하는 데 사용된다.

 

 

Video File Formats

비디오 파일 포맷은 비디오 데이터를 저장하는 컨테이너의 종류를 의미한다. MP4, AVI, MOV, MKV 등이 대표적인 비디오 포맷이다. 각각의 포맷은 호환성, 압축 효율성, 기능 지원 측면에서 차이가 있으며, 플랫폼의 목적에 맞는 비디오 포맷을 선택하는 것이 중요하다. 예를 들어, MP4는 대부분의 기기에서 호환되므로 스트리밍과 다운로드에 적합하다.

 

MP4: 가장 널리 사용되는 비디오 포맷 중 하나로, 대부분의 플랫폼과 기기에서 지원됩니다. H.264 코덱과 자주 사용되며, 스트리밍과 다운로드에 적합하다.

 

MOV: 애플의 QuickTime 포맷으로, 주로 Mac 환경에서 사용되며, 고품질의 비디오를 지원한다.

 

MKV: 오픈 소스 포맷으로, 다수의 오디오 트랙, 자막 등을 하나의 파일에 포함할 수 있다. 품질 유지가 뛰어나지만, 모든 기기에서 지원되지 않을 수 있다.