Como criar eficientemente um gif de melhor paleta a partir de uma parte de vídeo diretamente da web

1

Eu tenho usado por algum tempo esse par de comandos para converter um segmento de vídeo em um gif animado, tendo ffmpeg calculando a melhor paleta para ele:

ffmpeg -ss $START -i $IN_FILE -t $LENGTH -vf "fps=$FPS,scale=$WIDTH:-1:flags=lanczos,palettegen" palette.png
ffmpeg -ss $START -i $IN_FILE -i palette.png -t $LENGTH -filter_complex "fps=$FPS,scale=$WIDTH:-1:flags=lanczos [x]; [x] [1:v] paletteuse" output.gif

Isso funciona muito bem para arquivos locais, mas se eu começar a usar URLs remotas para $IN_FILE , ele baixará a parte necessária duas vezes - uma para a geração de paleta, uma vez para a conversão real.

Fazer o download completo do arquivo com antecedência geralmente está fora de questão - geralmente estou interessado em uma seqüência muito pequena no meio de um vídeo mais longo.

Tentei fazer o download apenas da pequena parte usando -ss e -t e salvá-lo - sem reencodificar - em um arquivo temporário:

ffmpeg -ss $START -i $IN_URL -t $LENGTH -vc copy -ac none temp.mkv

Nesse caso, evito o desperdício de largura de banda (somente a parte relevante do arquivo é baixada e apenas uma vez), mas a busca não é mais precisa, como -ss on input possui apenas a granularidade de quadros-chave para procurar ao fazer uma cópia de fluxo .

Ao converter para gif, em teoria, seria possível fazer uma busca extra precisa e corrigir isso, mas não parece haver uma maneira de obter o timestamp original do início do arquivo temporário gerado acima, portanto, Não é possível calcular para onde devo -ss quando transcodifico para gif. Eu tentei jogar com -copy_ts , mas não deu nada de bom.

A solução trivial é reencodificar nesta primeira etapa (possivelmente aplicando a escala / resample no processo, para evitar fazer isso duas vezes mais tarde), mas eu gostaria de evitar a perda de custo / qualidade de uma codificação extra inútil.

Então: como posso realizar o vídeo com a melhor paleta para a conversão de uma pequena porção de um grande arquivo em rede, obtendo-o eficientemente (= baixar uma vez, apenas a parte relevante), com busca precisa e sem extra codificações?

    
por Matteo Italia 17.05.2018 / 08:16

1 resposta

1

O problema pode ser facilmente resolvido usando um filtro gráfico com várias redes , o que nos permite realizar a pesquisa / download / filter apenas uma vez e processá-lo de várias maneiras. O fluxo de procura / filtrado é alimentado para o gerador de paleta e para o filtro de aplicativo de paleta, que o utiliza junto com a paleta gerada. Graficamente:

                                       .--> palettegen [pal]---.
 input                                /                        |
 [0:v] -> fps -> scale -> split=2 [a][b]                       V
 with                                 '-> [b] fifo [b] -> [b] [pal] paletteuse -> out.gif
precise
 seek

que se traduz em:

ffmpeg -ss $START -I $IN_URL -t $LENGTH -filter_complex "fps=$FPS,scale=$WIDTH:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" out.gif

Observe que para usar o mesmo fluxo como entrada para duas ramificações de pipeline separadas, é necessário usar o filtro split .

Editar : fifo foi adicionado graças ao comentário do @Gyan ; é necessário porque palettegen precisa esperar até o final do fluxo antes de gerar a paleta, e paletteuse não pode começar a consumir [b] antes de ter a paleta, portanto, se o vídeo for grande o suficiente, os buffers padrão serão [b] não será suficiente e ffmpeg começará a descartar quadros. A solução é adicionar um fifo no meio para manipular o buffer de tamanho arbitrário (é preciso tomar cuidado para não exceder o comprimento do vídeo, já que armazenar em buffer todo o fluxo na memória pode estar sobrecarregando a RAM disponível).

(plug sem vergonha: este é o comando Estou usando agora no meu tube2gif_bot bot de telegrama

Mais importante ainda, este é um conto sobre entender os comandos que você está usando ; o segundo comando citado na questão já usou um filtro-gráfico complexo, mas como copiei-o cegamente da web eu realmente não tentei entender a sintaxe opaca do filtro de grafos, então não me ocorreu que apenas ajustando um pouco teria sido a melhor solução.

    
por 17.05.2018 / 08:17