Desempenho de várias saídas do FFMPEG (instância única versus instâncias múltiplas)

5

Estou trabalhando na criação de vários fluxos codificados a partir da entrada de arquivo único (.mp4). Fluxo de entrada não tem áudio. Cada fluxo codificado é criado cortando uma parte diferente da entrada e, em seguida, codificado com a mesma taxa de bits no sistema de 32 núcleos.

Aqui estão os cenários que estou tentando, como explicado no ffmpeg wiki, para criar múltiplas saídas. link

Scenario1 (usando uma única instância do ffmpeg)

ffmpeg -i input.mp4 \

-filtro: v crop = iw / 2: ih / 2: 0: 0 -c: v libx264 -b: v 5M out_1.mp4 \

-filtro: v cultura = iw / 2: ih / 2: iw / 2: 0 -c: v libx264 -b: v 5M out_2.mp4 \

-filtro: v crop = iw / 2: ih / 2: 0: ih / 2 -c: v libx264 -b: v 5M out_3.mp4

Neste caso, estou assumindo que o ffmpeg decodificará a entrada apenas uma vez e será fornecido a todos os filtros de cultura. Por favor, corrija-me se isso não estiver certo.

Scenario2 (Usando várias instâncias do ffmpeg e, portanto, três processos separados)

ffmpeg -i input.mp4 -filtro: v crop = iw / 2: ih / 2: 0: 0 -c: v libx264 -b: v 5M out_1.mp4

ffmpeg -i input.mp4 -filtro: v cultura = iw / 2: ih / 2: iw / 2: 0 -c: v libx264 -b: v 5M out_2.mp4

ffmpeg -i input.mp4 -filtro: v crop = iw / 2: ih / 2: 0: ih / 2 -c: v libx264 -b: v 5M out_3.mp4

No meu caso, eu realmente preciso codificar um número ainda maior de fluxos cortando seções diferentes do vídeo de entrada. Estou mostrando três aqui apenas para simplificar este exemplo.

Agora, em termos de desempenho do fps, vejo que o cenário 2 tem melhor desempenho. Ele também usa cpu ao máximo (mais de 95% de utilização da cpu). O cenário 1 tem menos fps e a utilização da CPU é muito menor (perto de 65%). Além disso, neste caso, como eu aumento o número de fluxos a serem codificados, a utilização da CPU não aumenta linearmente. quase se torna 1,5x quando eu vou de um fluxo para dois. Mas depois disso, os incrementos são muito baixos (provavelmente 10% e até menos com mais streams).

Então, minha pergunta é: Eu quero usar ffmpeg de instância única porque evita a decodificação várias vezes e também, porque a entrada que eu tenho poderia ser tão grande quanto 4K ou até maior. O que devo fazer para obter melhor utilização da CPU (> 90%) e, consequentemente, melhores fps? também, por que a utilização da cpu não está aumentando linearmente com o número de fluxos a serem codificados? Por que a instância única do ffmpeg não é tão boa quanto várias instâncias? Parece-me que, com uma única instância do ffmpeg, todos os códigos não estão sendo executados em paralelo.

Editar: Aqui está a maneira mais simples possível de reproduzir e explicar o problema, caso as coisas não sejam tão claras. Tenha em mente que isso é apenas para fins experimentais para entender o problema.

Instância única: ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f null - -c: v libx264 -x264opts threads = 1 -b: v 1M -f null - -c: v encadeamentos libx264 -x264opts = 1 -b: v 1M -f nulo -

Várias Instâncias: ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f null - | ffmpeg -y -i input.mp4 -c: v encadeamentos libx264 -x264opts = 1 -b: v 1M -f null - | ffmpeg -y -i input.mp4 -c: v encadeamentos libx264 -x264opts = 1 -b: v 1M -f nulo -

Note que estou limitando x264 a um único thread. No caso de instância única, eu esperaria que o ffmpeg gerasse um encadeamento de codificação para cada codificação x264 e os executasse em paralelo. Mas vejo que apenas um núcleo de cpu é totalmente utilizado, o que me faz acreditar que apenas uma sessão de codificação está sendo executada por vez. Por outro lado, com o caso de várias instâncias, vejo que três núcleos cpu são totalmente utilizados, o que significa que todos os três códigos estão sendo executados em paralelo.

Eu realmente espero que alguns especialistas possam participar e ajudar com isso.

    
por shalin 13.06.2017 / 21:36

3 respostas

1

Um problema menos óbvio é que dependendo da sua entrada / saída ou filtros ffmpeg pode precisar fazer conversão de formato de pixel internamente e em certos casos isso se torna um gargalo ao usar saídas paralelas se feito em cada fluxo separadamente.

A ideia é fazer a conversão do formato de pixel uma vez, se possível, como:

-filter_complex '[0:v]format=yuv420p, split=3[s1][s2][s3]' \
-map '[s1]' ... \
-map '[s2]' ... \
-map '[s3]' ... \

Os mesmos filtros aplicados a todas as saídas também devem ser usados apenas uma vez. Alguns filtros podem precisar de um formato de pixel específico.

Para outras causas, veja a pequena nota na parte inferior do wiki :

Parallel encoding

Outputting and re encoding multiple times in the same FFmpeg process will typically slow down to the "slowest encoder" in your list. Some encoders (like libx264) perform their encoding "threaded and in the background" so they will effectively allow for parallel encodings, however audio encoding may be serial and become the bottleneck, etc. It seems that if you do have any encodings that are serial, it will be treated as "real serial" by FFmpeg and thus your FFmpeg may not use all available cores.

    
por 03.08.2017 / 11:56
0

Eu mesmo notei isso com um tamanho de buffer de vídeo baixo / padrão.

Tente aumentar seu bufsize para algo como 50 M ou metade do seu tamanho de arquivo, o que for menor.

Observe também que o parâmetro bufsize é denotado em unidades de k, então seria algo como -bufsize 50000k

    
por 13.06.2017 / 22:15
0

Não consigo reproduzir seu problema. Configuração:

  • Última geração de estática do Zeranoe
  • Win10 pro
  • CPU Intel i5-4210U (4 núcleos, sem HT)
  • RAM DDR3 de 8 GB
  • R / W para reator interno de 1TB Mushkin SSD
  • Vídeo para reprodução: link ( -ss 00:01:00.000 -to 00:01:25.000 porque renderizar a coisa toda obviamente levaria para sempre)

Meu código no Powershell:

# Measure time of FFMPEG process
$time = Measure-Command{
    ffmpeg -ss 00:01:00.000 -i .\ToS-4k-1920.mov '
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_1.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_2.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_3.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_4.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_5.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_6.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_7.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_8.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_9.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_10.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_11.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_12.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:0" -c:v libx264 -b:v 5M -y .\out_13.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_14.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_15.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_16.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_17.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_18.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_19.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_20.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_21.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_22.mp4 '
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_23.mp4 '
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_24.mp4
}

Write-Host "Time spent: $time"

Resultado:

  • $time : 00: 05: 52.7747482
  • velocidade do ffmpeg: speed=0.0711x

Ambos os valores parecem razoáveis para mim.

Até mesmo 24 saídas paralelas não mostram nenhum problema aqui - a CPU permanece em torno de > 95% para todo o processo, quase nenhum uso do SSD (< 5%) e ~ 75% da RAM são usados ocioso, ~ 30% são usados). (Valores verificados manualmente via Task-Manager)

Portanto, existem algumas possibilidades aqui:

  • Você está usando uma versão antiga do FFmpeg
  • Algo mais (HDD, RAM) está causando gargalos
  • Algo está errado com o seu arquivo - é improvável, acho
  • Algo está errado com a sua CPU - assim como é improvável, pois você afirma que funciona com capacidade total ao usar várias instâncias do ffmpeg)
  • experimente -threads -values diferentes no seu código e veja se isso faz alguma diferença.
por 14.06.2017 / 15:12