Codificação ao vivo com VP9 usando FFmpeg
Parâmetros de codificação
O VP9 oferece uma variedade de parâmetros para otimizar a codificação ao vivo. Alguns princípios gerais são discutidos em Modos de taxa de bits.
Exemplo de codificação VP9 do FFmpeg
A tabela abaixo descreve os parâmetros de um exemplo de chamada ffmpeg
para codificação VP9.
Parâmetro | Descrição |
---|---|
-quality realtime |
realtime é essencial para transmissões ao vivo e velocidades acima de 5 . |
-speed 6 |
A velocidade 5 a 8 deve ser usada para codificação ao vivo / em tempo real. Números menores (5 ou 6 ) têm qualidade melhor, mas exigem mais poder de CPU. Números mais altos (7 ou 8 ) terão qualidade inferior, mas serão mais fáceis de gerenciar para casos de uso de baixa latência e também para dispositivos com menor capacidade de CPU, como dispositivos móveis. |
-tile-columns 4 |
O mosaico divide o vídeo em regiões retangulares, o que permite multithreading para codificação e decodificação. O número de blocos é sempre uma potência de dois. 0 = 1 bloco, 1 = 2, 2 = 4, 3 = 8, 4 = 16, 5 = 32. |
-frame-parallel 1 |
Ative os recursos de decodificação paralela. |
-threads 8 |
Número máximo de linhas de execução a serem usadas. |
-static-thresh 0 |
Limite de detecção de movimento. |
-max-intra-rate 300 |
Taxa de bits máxima de frame-I (pct) |
-deadline realtime |
Versão alternativa (legada) do -quality realtime |
-lag-in-frames 0 |
Número máximo de frames a serem atrasados |
-qmin 4 -qmax 48 |
Valores mínimo e máximo para o quantizador. Os valores aqui são apenas uma sugestão, e o ajuste deles ajuda a aumentar/diminuir a qualidade do vídeo às custas da eficiência da compactação. |
-row-mt 1 |
Ativa o multithreading de linhas. Permite o uso de até 2x de linhas como colunas de blocos. 0 = off, 1 = on. |
-error-resilient 1 |
Ative os recursos de capacidade de recuperação de erros. |
Escolher parâmetros de codificação
As informações abaixo usam a codificação de taxa de bits constante (CBR) para transmissão adaptativa de taxa de bits (ABR) ao vivo, em que cada taxa de destino é definida explicitamente no manifesto do empacotador. Isso vai resultar em uma "troca" mais limpa entre as taxas para os clientes. A codificação de taxa de bits variável (VBR) e o modo CQ também são opções se a taxa de bits puder ser mais flexível ou se a codificação estiver sendo dividida em partes. O modo Q terá dificuldades com a codificação em tempo real necessária para vídeos ao vivo. Consulte Modos de taxa de bits para mais informações.
Para mais detalhes sobre como manipular o VP9, consulte o artigo complementar sobre configurações de VOD, mas considerando o foco no CBR.
Dicas e sugestões
Ao fazer transmissões ao vivo, tudo é limitado a uma velocidade mínima de codificação em tempo real de 1x (o FFmpeg informa a velocidade de codificação à medida que ela avança). Se a velocidade de codificação cair abaixo de 1x, o processo não vai acompanhar a entrada de vídeo ao vivo, e os usuários vão ter problemas de buffer. Além disso, interrupções na transmissão vão tornar o stream inutilizável durante a transmissão ao vivo (embora o arquivo geralmente possa ser usado).
Exemplos de parâmetros de codificação em ação
A seguir, mostramos a utilização da CPU a 25 fps para vários tamanhos de frame em um desktop quad-core i5 de 3,6 GHz executando o Linux:
Resolução desejada | Parâmetros VP9 do FFmpeg | CPU / Velocidade (exemplo) |
---|---|---|
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,39x |
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,68x |
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,04x |
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,77x |
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,51x |
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,27x |
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,27x |
Um exemplo de FFmpeg seria assim:
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
Dicas e sugestões
Aqui, estamos gerando saída para um pipe FIFO ("pipe1"), que precisa ser criado antes da execução, antes de executar o comando FFmpeg. Para fazer isso, execute o comando
mkfifo pipe1
no diretório de trabalho. Ao usar o Shaka Packager, ele vai detectar esse pipe como origem de entrada para o stream especificado. Outros modelos de embalagem podem exigir um método diferente.Para garantir que os comandos
-row-mt
sejam reconhecidos, use a versão estável mais recente do FFmpeg (atualmente 3.3.3) em https://www.ffmpeg.org/download.html
Exemplo de conjunto de taxa de bits adaptável
Dependendo da capacidade da máquina que executa a codificação FFmpeg, pode ser possível ou não entregar todas as codificações a seguir ao mesmo tempo. Portanto, um subconjunto adequado aos seus recursos disponíveis e públicos-alvo precisa ser selecionado na lista.
Conjunto completo de ABR do FFmpeg
Em um cenário ideal, combinamos os exemplos de codificação descritos na seção anterior para criar um único comando que os produza todos ao mesmo tempo:
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
No entanto, o conjunto completo acima vai exigir uma CPU muito potente ou talvez suporte de descarga de GPU de hardware, como alguns chipsets oferecem cada vez mais. O Intel Kabylake (e versões mais recentes) tem um pipeline completo de codificação de hardware. A GPU Kabylake pode fazer codificação VP9 de 8 bits, mas não de 10 bits.
Um exemplo prático para computador usando o Shaka Packager
Um exemplo mais prático para máquinas desktop comuns pode usar o Shaka Packager. Uma maneira simples de configurar o Shaka é instalá-lo em um contêiner Docker usando a imagem do DockerHub do Google. Confira as instruções aqui:
https://github.com/google/shaka-packager#using-docker-for-testing--development
Neste exemplo, usamos uma máquina com a seguinte configuração:
Sistema | Host: obs Kernel: 4.4.0-91-lowlatency x86_64 (64 bits) |
Computador | Xfce 4.12.3 Distro: SO: https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/ |
CPU | Intel Core i5-6500 (-MCP-) com quatro núcleos cache: 6144 KB velocidades de clock: máx.: 3600 MHz 1: 800 MHz 2: 800 MHz 3: 800 MHz 4: 800 MHz |
Placa de vídeo | Placa de vídeo integrada Intel Skylake |
Memória | 8 GB de RAM |
Na prática, essa máquina pode produzir de maneira ideal o seguinte intervalo útil de codificações ABR, com o FFmpeg informando consistentemente uma velocidade de codificação de 1x:
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
As configurações de -speed
são bastante altas. Essas configurações foram estabelecidas experimentalmente e vão variar de máquina para máquina.
Sobrecarga do Shaka Packager
O empacotamento não é uma atividade que exige muito da CPU. O Shaka Packager pode ser configurado para detectar todas as saídas, mesmo que apenas um subconjunto esteja sendo entregue pelo FFmpeg. Estas são as configurações do empacotador testadas na máquina descrita acima:
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