FFmpeg를 사용하여 VP9로 실시간 인코딩

인코딩 매개변수

VP9는 라이브 인코딩을 최적화하기 위한 다양한 매개변수를 제공합니다. 이러한 원칙의 일부는 비트 전송률 모드에 설명되어 있습니다.

FFmpeg VP9 인코딩 예

아래 표에서는 VP9 인코딩의 예시 ffmpeg 호출의 매개변수를 설명합니다.

매개변수 설명
-quality realtime realtime는 라이브 스트리밍과 5 이상의 속도에 필수적입니다.
-speed 6 속도 5~8은 라이브 / 실시간 인코딩에 사용해야 합니다. 숫자가 낮을수록 (5 또는 6) 품질이 높지만 더 많은 CPU 성능이 필요합니다. 높은 수 (7 또는 8)는 품질이 낮지만 지연 시간이 짧은 사용 사례와 모바일과 같은 CPU 성능이 낮은 기기에서 더 쉽게 관리할 수 있습니다.
-tile-columns 4 타일링은 동영상을 직사각형 영역으로 분할하여 인코딩 및 디코딩을 위한 멀티 스레딩을 지원합니다. 타일 수는 항상 2의 거듭제곱입니다. 0 = 1타일, 1 = 2, 2 = 4, 3 = 8, 4 = 16, 5 = 32
-frame-parallel 1 병렬 디코딩 가능성 기능을 사용 설정합니다.
-threads 8 사용할 최대 스레드 수입니다.
-static-thresh 0 움직임 감지 기준입니다.
-max-intra-rate 300 최대 i-프레임 비트 전송률(%)
-deadline realtime -quality realtime의 대체 (기존) 버전
-lag-in-frames 0 지연시킬 최대 프레임 수
-qmin 4 -qmax 48 양자화기의 최솟값 및 최댓값입니다. 여기에 표시되는 값은 제안일 뿐이며, 이 값을 조정하면 압축 효율성을 희생하여 동영상 품질을 높이거나 낮출 수 있습니다.
-row-mt 1 행 멀티스레딩을 사용 설정합니다. 최대 2배의 스레드를 타일 열로 사용할 수 있습니다. 0 = 사용 중지, 1 = 사용 설정
-error-resilient 1 오류 복원력 기능을 사용 설정합니다.

인코딩 매개변수 선택

아래 정보에서는 라이브 적응형 비트 전송률 (ABR) 스트리밍에 고정 비트 전송률 (CBR) 인코딩을 사용합니다. 여기서 각 타겟 비율은 패키저의 매니페스트에 명시적으로 설정됩니다. 이렇게 하면 클라이언트의 요금 간 '전환'이 더 명확해집니다. 비트 전송률이 더 유연하거나 인코딩이 청크로 처리되는 경우 가변 비트 전송률 (VBR) 인코딩과 CQ 모드도 옵션입니다. Q 모드는 라이브 동영상에 필요한 실시간 인코딩에 어려움을 겪습니다. 자세한 내용은 비트 전송률 모드를 참고하세요.

VP9 조작 방법에 대한 자세한 내용은 VOD 설정에 관한 관련 도움말을 참고하세요. 단, CBR에 중점을 두어야 합니다.

도움말 및 유용한 정보

라이브 스트리밍 시 모든 것이 최소 실시간 인코딩 속도 1x로 제한됩니다 (FFmpeg는 진행에 따라 인코딩 속도를 보고함). 인코딩 속도가 1배 미만으로 떨어지면 인코딩 프로세스가 라이브 동영상 입력에 따라가지 못하고 사용자가 버퍼링을 경험하게 되며 전송이 중단되어 라이브 방송 중에 스트림을 사용할 수 없게 됩니다(보관 파일은 일반적으로 사용할 수 있음).

실제 인코딩 매개변수 예

다음은 Linux를 실행하는 쿼드 코어 i5 3.6Ghz 데스크톱에서 다양한 프레임 크기에 대한 25fps의 CPU 사용률을 보여줍니다.

타겟 해상도 FFmpeg VP9 매개변수 CPU / 속도 (예)
3840x2160 (2160p) -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k ~88% 0.39배
2560x1440 (1440p) -r 30 -g 90 -s 2560x1440 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 6000k ~86% 0.68배
1920x1080 (1080p) -r 30 -g 90 -s 1920x1080 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 4500k ~82% 1.04배
1280x720 (720p) -r 30 -g 90 -s 1280x720 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 3000k ~78% 1.77배
854x480 (480p) -r 30 -g 90 -s 854x480 -quality realtime -speed 6 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 1800k 약 64% 3.51배
640x360 (360p) -r 30 -g 90 -s 640x360 -quality realtime -speed 7 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 730k ~62% 5.27배
426x240 (240p) -r 30 -g 90 -s 426x240 -quality realtime -speed 8 -threads 2 -row-mt 1 -tile-columns 0 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 365k ~66% 8.27배

FFmpeg의 예는 다음과 같습니다.

ffmpeg -stream_loop 100 -i /home/id3as/Videos/120s_tears_of_steel_1080p.webm \
  -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 \
  -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k -c:v libvpx-vp9 \
  -b:a 128k -c:a libopus -f webm pipe1

도움말 및 유용한 정보

  • 여기서는 FFmpeg 명령어를 실행하기 전에 실행 전에 생성해야 하는 FIFO 파이프 ('pipe1')에 출력합니다. 이렇게 하려면 작업 디렉터리에서 mkfifo pipe1 명령어를 실행하세요. Shaka Packager를 사용하는 경우 지정된 스트림의 입력 소스로 해당 파이프를 수신합니다. 다른 패키징 모델에는 다른 방법이 필요할 수 있습니다.

  • -row-mt 명령어가 인식되도록 하려면 https://www.ffmpeg.org/download.html에서 FFmpeg의 최신 안정화 버전 (현재 3.3.3)을 사용하세요.

적응형 비트 전송률 설정의 예

FFmpeg 인코드를 실행하는 머신의 성능에 따라 다음 인코딩을 모두 동시에 제공하지 못할 수도 있으므로 사용 가능한 리소스와 타겟 잠재고객에 적합한 하위 집합을 목록에서 선택해야 합니다.

FFmpeg 전체 ABR 세트

이상적인 시나리오에서는 앞 섹션에 설명된 인코딩 예시를 결합하여 모든 예시를 동시에 생성하는 단일 명령어를 만듭니다.

ffmpeg -stream_loop 100 -i lakes1080p.mp4 \
  -y -r 25 -g 75 -s 3840x2160 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 7800k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe1 \
  -y -r 25 -g 75 -s 2560x1440 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 6000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe2 \
  -y -r 25 -g 75 -s 1920x1080 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe3 \
  -y -r 25 -g 75 -s 1280x720 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe4 \
  -y -r 25 -g 75 -s 854x480 -quality realtime -speed 6 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 2000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe5 \
  -y -r 25 -g 75 -s 640x360 -quality realtime -speed 7 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe6 \
  -y -r 25 -g 75 -s 426x240 -quality realtime -speed 8 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 365k -c:v libvpx-vp9 -b:a 64k -c:a libopus -f webm pipe7

하지만 위의 전체 세트에는 매우 강력한 CPU가 필요하거나 일부 칩셋에서 점점 더 많이 제공하는 하드웨어 GPU 오프로드 지원이 필요할 수 있습니다. Intel Kabylake 이상에는 전체 하드웨어 인코딩 파이프라인이 있습니다. Kabylake GPU는 8비트 VP9 인코딩을 할 수 있지만 10비트는 할 수 없습니다.

Shaka Packager를 사용하는 실제 데스크톱 예시

일반적인 데스크톱 머신의 더 실용적인 예에서는 Shaka Packager를 사용할 수 있습니다. Shaka를 설정하는 간단한 방법은 Google의 DockerHub 이미지를 사용하여 Docker 컨테이너 내에 설치하는 것입니다. 안내는 여기에서 확인할 수 있습니다.

https://github.com/google/shaka-packager#using-docker-for-testing--development

이 예에서는 다음 구성의 머신을 사용했습니다.

시스템 호스트: obs 커널: 4.4.0-91-lowlatency x86_64 (64비트)
데스크톱 Xfce 4.12.3 배포판: OS: https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/
CPU 쿼드 코어 Intel Core i5-6500 (-MCP-)
캐시: 6144KB
클럭 속도: 최대: 3600MHz 1: 800MHz 2: 800MHz 3: 800MHz 4: 800MHz
그래픽 카드 Intel Skylake 통합 그래픽
메모리 8GB RAM

실제로 이 머신은 FFmpeg가 일관되게 1x 인코딩 속도를 보고하는 가운데 다음의 사용 가능한 ABR 인코딩 범위를 최적으로 생성할 수 있습니다.

ffmpeg -stream_loop 100 -i 120s_tears_of_steel_1080p.webm \
  -y -r 30 -g 90 -s 1920x1080 -quality realtime -speed 7 -threads 8 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe1 \
  -y -r 30 -g 90 -s 1280x720 -quality realtime -speed 8 -threads 6 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe2 \
  -y -r 30 -g 90 -s 640x360 -quality realtime -speed 8 -threads 2 \
  -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe3

-speed 설정이 상당히 높습니다. 이러한 설정은 실험적으로 설정되었으며 머신마다 다를 수 있습니다.

Shaka Packager 오버헤드

패키징은 CPU를 많이 사용하는 활동이 아닙니다. FFmpeg에서 일부만 제공하는 경우에도 모든 출력을 수신하도록 Shaka Packager를 설정할 수 있습니다. 위에서 설명한 머신에서 테스트한 패키저 설정은 다음과 같습니다.

packager \
  in=pipe1,stream=audio,init_segment=livehd-audio-1080.webm,segment_template=livehd-audio-1080-\$Number\$.webm \
  in=pipe1,stream=video,init_segment=livehd-video-1080.webm,template=livehd-video-1080-\$Number\$.webm \
  in=pipe2,stream=audio,init_segment=livehd-audio-720.webm,segment_template=livehd-audio-720-\$Number\$.webm \
  in=pipe2,stream=video,init_segment=livehd-video-720.webm,template=livehd-video-720-\$Number\$.webm \
  in=pipe3,stream=audio,init_segment=livehd-audio-360.webm,segment_template=livehd-audio-360-\$Number\$.webm \
  in=pipe3,stream=video,init_segment=livehd-video-360.webm,template=livehd-video-360-\$Number\$.webm \
  --mpd_output livehd.mpd --dump_stream_info --min_buffer_time=10 --time_shift_buffer_depth=300 \
  --segment_duration=3 --io_block_size 65536