A resposta, portanto, parece ser:
- O método 1 foi verificado para funcionar, mas é
libx264
-específico e tem o custo de eliminar a opçãoscenecut
muito útil emlibx264
. - O método 3 funciona a partir da versão do FFMPEG de abril de 2015, mas você deve verificar seus resultados com o script incluído na parte inferior desta postagem, pois a documentação do FFMPEG não está clara quanto ao efeito da opção. Se funciona, é a superior das duas opções.
-
NÃO USE o Método 2,
-g
parece estar obsoleto. Ele não parece funcionar, nem está explicitamente definido na documentação, nem é encontrado na ajuda, nem parece ser usado no código. A inspeção de código mostra que a opção-g
é provavelmente destinada a fluxos MPEG-2 (existem até mesmo estrofes de código referentes a PAL e NTSC!).
Além disso:
- Arquivos gerados com o Método 3 podem ser um pouco maiores que o Método 1, como quadros I intersticiais (quadros-chave) são permitidos.
- Você deve definir explicitamente o sinalizador "-r" em ambos os casos, mesmo que o Método 3 coloque um quadro I no próximo intervalo de quadros ou após o horário especificado. A falha em definir o sinalizador "-r" coloca você à mercê do arquivo de origem, possivelmente com uma taxa de quadros variável. Podem ocorrer transições DASH incompatíveis.
- Apesar dos avisos na documentação do FFMPEG, o método 3 é NÃO menos eficiente que outros. De fato, os testes mostram que pode ser um pouco MAIS eficiente que o método 1.
Script para a opção -force_key_frames
Aqui está um pequeno programa PERL que eu usei para verificar a cadência do I-frame com base na saída da sugestão do ffprobe do slhck. Parece verificar que o método -force_key_frames
também funcionará e tem o benefício adicional de permitir scenecut
frames. Eu não tenho absolutamente nenhuma idéia de como o FFMPEG faz esse trabalho, ou se eu apenas tive sorte de alguma forma porque meus fluxos foram bem condicionados.
No meu caso, codifiquei a 30fps com um tamanho esperado de GOP de 6 segundos ou 180 quadros. Eu usei 180 como o argumento gopsize para este programa verificou um quadro I em cada múltiplo de 180, mas defini-lo para 181 (ou qualquer outro número não um múltiplo de 180) fez reclamar.
#!/usr/bin/perl
use strict;
my $gopsize = shift(@ARGV);
my $file = shift(@ARGV);
print "GOPSIZE = $gopsize\n";
my $linenum = 0;
my $expected = 0;
open my $pipe, "ffprobe -i $file -select_streams v -show_frames -of csv -show_entries frame=pict_type |"
or die "Blah";
while (<$pipe>) {
if ($linenum > $expected) {
# Won't catch all the misses. But even one is good enough to fail.
print "Missed IFrame at $expected\n";
$expected = (int($linenum/$gopsize) + 1)*$gopsize;
}
if (m/,I\s*$/) {
if ($linenum < $expected) {
# Don't care term, just an extra I frame. Snore.
#print "Free IFrame at $linenum\n";
} else {
#print "IFrame HIT at $expected\n";
$expected += $gopsize;
}
}
$linenum += 1;
}