Nós desenvolvemos um aplicativo para transcodificar arquivos .mov de origem para saída .ogg, .mp4 e .webm. Atualmente, ele está sendo executado na instância g2.8xlarge do AWS EC2. Está funcionando (yay!).

Minha pergunta: Embora eu esteja passando -threads 0 para o comando ffmpeg (na verdade, definindo ffmpeg.threads configuração em php-ffmpeg ), o processo em execução às vezes só está sendo executado em um único núcleo. Por que isso está acontecendo? Veja abaixo a saída do comando htop:

saída htop

Como você pode ver , O Core # 21 está no limite. Em alguns segundos, ele vai mudar para outro, ao invés de maximizar todos eles como eu gostaria e acelerar muito meu processo de codificação. A situação é transitória; durante algumas execuções, todos os processadores são atingiu o limite máximo, mas durante outros não e nós apenas usamos um processador. Um colega mencionou que talvez o codec que estamos usando para alguns dos formatos não suporte a execução multi-thread durante a codificação, embora eu ainda não possa verificar se é o comportamento que estou observando.

É esse o caso? Em caso afirmativo, quais codecs para os formatos acima nos permitirão transcodificar para esses formatos de destino enquanto aproveitamos todo o nosso hardware disponível? Os codecs padrão definidos para php-ffmpeg estão abaixo;

 Video Audio Ogg libtheora libvorbis WebM libvpx libvorbis X264 libx264 libfaac 

Atualização

Olhando para os processos em execução, abaixo está o que acaba sendo o comando ffmpeg executado para um MP4 (atualmente saturando todos os 32 núcleos):

Na verdade, não estou construindo este comando diretamente, php-ffmpeg está, embora acredite ter pelo menos um controle modesto sobre o que acontece nele (por exemplo, não tenho ideia de por que há várias -metadata:s:v:0 entradas no início)

Comentários

  • Há ‘ muito fator eca nessa linha de comando, além das opções duplicadas (-s três vezes , o último com um tamanho diferente). Definindo explicitamente vários argumentos para seus valores padrão atuais (por exemplo, -i_qfactor, -subq, -qcomp) é estranho e pode dar resultados ruins com a futura libx264. (Provavelmente não, mas apenas porque a libx264 está praticamente pronta, e estável, não em desenvolvimento pesado. Se fizesse algo assim para x265, seria ruim.) De qualquer forma, 1200k em 2 passagens é bom, mas você pode preferir alvo -quality crf. Ele não ‘ t especifica um -preset. 🙁
  • libfaac isn ‘ t tão bom quanto libfdk_aac . Se você ‘ estiver usando isso em um serviço pago, ‘ precisaria verificar o licenciamento de libfdk_aac. Além disso, este cmdline está faltando -movflags +faststart
  • É ‘ também possível fazer com que o ffmpeg produza vários resultados do mesmo entrada. Basta ter várias sequências de opções de saída nome de arquivo de saída na linha de comando. Resumindo, eu ‘ não estou impressionado com php-ffmpeg, se ‘ é o tipo de cmdline que ele oferece. Talvez você pudesse usá-lo de forma diferente para fazer com que gerasse várias saídas de uma vez, então não haveria ‘ t ser uma etapa de teora de thread único. De qualquer forma, se funcionar, ótimo, mas cuidado com as alterações nos padrões do codificador e com o significado de x264 subme níveis mudando, de maneiras que eu e seu cmdline prejudica a qualidade.
  • @Peter muito obrigado. Acho que a resposta aqui realmente é que preciso depurar como esse cmd está sendo construído. Se eu realmente puder colocar várias saídas nesse comando, acho que provavelmente teria a melhor chance de maximizar a carga no hardware
  • trac.ffmpeg .org / wiki / Criando% 20multiple% 20outputs . E sim, concordo que ‘ é provavelmente o melhor. Caso contrário, você tem tarefas que ‘ s com thread único por algum tempo e carregando todos os seus núcleos em outra parte do tempo. É difícil agendar tarefas que se comportam dessa maneira.

Resposta

A propósito, esta pergunta pode ser melhor no stackoverflow, ou talvez unix.stackexchange, ou talvez serverfault. Acho que este site é menos focado em questões que não envolvem decisões baseadas no mérito criativo ou pelo menos na qualidade perceptual de vídeo / áudio. No entanto, eu sou tudo sobre os detalhes técnicos, então responderei.

FFmpeg usa multi-threading por padrão, então você provavelmente não precisa de -threads 0. Se sua codificação tiver gargalos em um filtro ou decodificador de thread único, você verá carga total em um núcleo e carga leve em muitos outros núcleos.

Uma coisa que você pode fazer é verificar as informações de mídia do vídeo de saída. x264 deixa suas configurações em uma string ASCII no cabeçalho h.264. Portanto, strings -n20 ou mediainfo para obter:

... Chroma subsampling : 4:2:0 Bit depth : 8 bits Scan type : Progressive Bits/(Pixel*Frame) : 0.051 Stream size : 455 MiB (89%) Writing library : x264 core 146 r2538+1 d48ec67 Encoding settings : cabac=1 / ref=6 / deblock=1:0:0 / analyse=0x3:0x133 / me=umh / subme=10 / psy=1 / psy_rd=0.70:0.10 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-3 / threads=4 / lookahead_threads=1 / sliced_threads=0 / nr=50 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=5 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=60 / rc=crf / mbtree=1 / crf=22.5 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=3:0.60 Color primaries : BT.709 Transfer characteristics : BT.709 Matrix coefficients : BT.709 

Observação o “threads = 4” ali. Acho que defini isso manualmente no meu quad core i5 2500k, em vez de deixar o x264 usar as CPUs padrão * 1.5, já que eu tinha filtros intensivos de CPU (hqdn3d e lanczos-downscale) em execução.

De qualquer forma, libx264 com um preset como slower não deve ter nenhum problemas para manter muitos núcleos ocupados. Existem algumas partes da codificação que são inerentemente seriais (por exemplo, a codificação CABAC do bitstream final), portanto, um vídeo de alta taxa de bits que não gasta muito tempo de CPU refinando referências (high subme) para vários quadros (alto ref) pode mostrar um padrão de carregamento como o seu (um thread usando 100% da CPU, outros não).

I “Não estou 100% certo de que predefinições mais rápidas sejam menos paralelas, mas sei que CABAC é serial.

Para ficar extremamente paralelo, a libx264 poderia usar uma carga de RAM para manter os quadros por perto e continuar fazendo a verificação à frente por 2 ou mais GOPs, e codifique-os independentemente. No entanto, ele não tem a opção de operar dessa maneira.

Uma maneira de usar MUITOS núcleos é executar várias codificações separadas em paralelo, em vez de apenas uma série de codificação única usando todos os núcleos. Isso só funciona se você tiver vários arquivos de entrada que deseja codificar separadamente. Você está trocando a sobrecarga de threading por mais capacidade de memória e largura de banda (com impacto no cache, a menos que seja em um sistema de vários soquetes com L3 e DRAM separados para cada cluster de CPUs, e você tem os processos fixados nos núcleos, de modo que uma codificação está usando os núcleos em um soquete e o outro no outro).

Comentários

  • Obrigado pelo insight. Eu perguntei aqui principalmente porque eu não ‘ não tenho nenhuma pergunta sobre o ” código ” e mais sobre o que está acontecendo nos bastidores e achei que seria a melhor opção. Eu ‘ sinalizarei para que a atenção do moderador migre e então ele poderá fazer a chamada.
  • No momento nós ‘ re colando uma mensagem em uma fila AWS SQS que tem um link para cada arquivo. Esta instância tem um trabalho em execução que escuta essas mensagens, baixa o arquivo, transcodifica-o e carrega os arquivos de saída assim que cada um for concluído. Se estou lendo isso corretamente, você ‘ está dizendo que provavelmente faria mais sentido para nós ir em frente e lançar alguns desses processos de trabalho e transcodificar vários arquivos em paralelo, em vez de tentar concentrar todos os núcleos em um único processo?
  • Sim, se você ‘ está tendo problemas para saturar mais núcleos, ‘ está bem para executar um encode ou 3 em paralelo. Acho que x264 deve ser capaz de saturar a maioria dos seus 32 núcleos, mas talvez apenas com uma predefinição mais lenta. Poste suas opções de cmdline do ffmpeg e saída do console em sua pergunta. IDK se você ‘ está usando algo bobo e de baixa qualidade como -preset veryfast. Nesse caso, a decodificação da entrada pode ser o gargalo de thread único. Ou, como eu disse, talvez um filtro lento.
  • Você ‘ certamente vai querer sobrepor o download / upload de um xcode com o uso da CPU de outro xcode, se você ‘ não estiver planejando transmitir de / para ffmpeg em tempo real para uso em produção. (Pode ser possível obter o equivalente a -movflags +faststart na hora, com um muxer diferente. Acho que li algo sobre isso. Caso contrário, se você ‘ reimprimindo mp4, você precisa gerar um arquivo para que o ffmpeg possa colocar o átomo moov na frente e embaralhar os dados quando a codificação estiver concluída.)
  • Oh, acabei de ler seu Q com mais detalhes. Se você ‘ reexibir todos os 3 formatos de uma vez (com a mesma linha de comando ffmpeg, então a decodificação da entrada só precisa acontecer uma vez), então se um dos 3 codificadores for single-threaded, isso causará um gargalo em todo o processo. Eu acho que libtheora não é multi-threaded. wiki.xiph.org/TheoraEncoders diz que havia uma bifurcação multi-thread, mas morreu. (talvez nunca funcionou bem ou não foi ‘ compatível com outras melhorias do codificador? Pode haver vários motivos para não ‘ ter sido mesclado.) lists.xiph.org/pipermail//theora-dev/2015-February/004374.html

Resposta

libtheora tem uma única thread. Existe uma compilação experimental multithread, mas não é mantida. Eu sugeriria executá-lo em paralelo com as outras codificações. Também, se possível, use libfdk-aac em vez de libfaac.Fidelidade de áudio muito maior com a mesma taxa de bits.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *