Como dividir arquivos de vídeo em uma mudança detectada na resolução? (ou seja, fluxos gravados contendo várias larguras)

2

Tenho muitos arquivos de vídeo (flv / mp4) que alteram a resolução no meio do fluxo (720p / 1080p / 640).

Eu gostaria de usar algo como ffmpeg para detectar automaticamente a alteração na resolução e dividir os vídeos em suas cenas individuais, mantendo a qualidade de codificação existente: segmento sem recodificação (Video1-scene1.flv, Video1-scene2.flv , etc).

Eu encontrei vários métodos para dividir o silêncio, a mudança de cena, em cenas negras, mas nada tão simples quanto uma mudança na largura da resolução.

Esses arquivos geralmente fazem com que editores / aparadores de vídeo falhem, e a identificação e remoção manual de cenas de baixa resolução consome muito tempo se eu simplesmente converter o vídeo inteiro em 1080p.

O algoritmo é provavelmente tão simples quanto comparar o quadro atual ao quadro anterior e, se tiverem resoluções diferentes, dividir o vídeo e iniciar um novo segmento.

Alguém pode ajudar por favor?

EXEMPLO DO FICHEIRO (temporarily available) : Example.flv

Abaixo estão algumas respostas relacionadas:

Cortar peça de arquivo de vídeo da posição inicial para a posição final com o FFmpeg

link

Divida automaticamente grandes arquivos de vídeo .mov em arquivos menores em quadros pretos (mudanças de cena)?

Dividir um vídeo usando o FFMPEG através da detecção de cena

Recursos adicionais:
Usando a solução de Lord Neckbeard, estou anexando o processo (infelizmente muito manual) que eventualmente trabalhei no Windows10. Talvez possa gerar outras ideias em torno do ffmpeg.
(Eu postei uma pergunta separada para quem é GURU o suficiente para: Automatize esse processo ... )

arraste o vídeo para um arquivo de lote que contenha:

ffprobe -v error -show_entries frame=pkt_pts_time,width,height -select_streams v -of csv=p=0 %1 > allkeyframes.txt

(amostra allkeyframes.txt ...)

13.652000,640,480
13.755000,640,480
13.597000,480,360
13.652000,480,360

cole este texto em POWERSHELL:

$o=""
$n=0
foreach($line in (Get-Content allkeyframes.txt)){
  $nline = $line.Split(",")
  $nline2=($nline[1]+$nline[2])
  if ($nline2 -ne $preventry) {
    $n0=$nline[0]
    $o="$o,$n0"
    $n=$n0
}
  $preventry = $nline2
}
if ($o.length -gt 1){
echo $o.Remove(0,1) > resolutionchanges.txt
} else {
Write-Host "No resolution changes found" -ForegroundColor Red
}

(resolutionchanges.txt:)

13.597000,25.618000,33.628000,45.598000

digite o seguinte na janela de comando, depois de colar o conteúdo de resolutionchanges.txt e alterar "input.flv" para o nome do vídeo (o Win10 recusou minhas tentativas de agrupar isso):

ffmpeg -i input.flv -map 0 -c copy -segment_times 13.597000,25.618000,33.628000,45.598000 -reset_timestamps 1 -f segment output_%03d.flv

    
por EverT 27.02.2018 / 22:51

1 resposta

0

A solução Lazyman é usar o filtro de escala para ajustar cada entrada a uma largura x altura desejada .

Para a sua solução proposta, você pode usar ffprobe para determinar quando as alterações de tamanho ocorrem.

ffprobe -v error -show_entries frame=pkt_pts_time,width,height -select_streams v -of csv=p=0 input.flv

Exemplo de trecho de saída durante a alteração de largura e altura (key_frame, pkt_pts_time, width, height):

0,89.081000,480,640
0,89.281000,480,640
0,89.481000,480,640
1,89.568000,640,480
0,89.592000,640,480
0,89.632000,640,480
1,97.749000,480,640

As alterações de tamanho provavelmente ocorrerão nos quadros principais, onde você poderá fazer os cortes se a cópia de fluxo for um requisito. Se você quiser apenas os quadros principais, adicione a opção -skip_frame nokey .

Em seguida, use o muxer de segmento :

ffmpeg -i input.flv -map 0 -c copy -segment_times 89.568,97.749 -reset_timestamps 1 -f segment output_%03d.flv
    
por 28.02.2018 / 01:26