Como cortar vídeos em quadros exatos com ffmpeg, selecione o filtro

15

Em vez de usar os parâmetros de busca -ss e -to , que não parecem muito precisos, posso cortar vídeos para determinados números de quadros? Por exemplo:

ffmpeg -i video.webm -startingframe 80 -endingframe 560 output.webm

[80º quadro e 560º quadro incluídos. Então, como o total faz (560 - 80 + 1) quadros]

Após as respostas e um pouco de pesquisa, tentei alguns comandos. Mas até agora não consegui encontrar um meio aceitável.

Se alguém quiser cortar o fluxo de vídeo entre 250 e 750 quadros, esse é o caminho a seguir. Isso dará 501 quadros como saída:

Nota: movie.mp4 tem 25 fps, e sua taxa de amostragem de áudio 48k

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm

Como esperado, a saída tem exatamente 20 segundos de duração.

Usando o mesmo método para áudio:

ffmpeg -i movie.mp4 -vn -af "aselect=between(n\,480\,1440),setpts=PTS-STARTPTS" a_stream.webm

Inesperadamente, este tem uma precisão muito baixa. Ele deveria ter me dado 960001 (960k + 1) amostras que equivalem a 20 segundos de áudio. Mas, em vez disso, a saída foi de 20,505 segundos e tem 984240 amostras. Além disso, se eu aumentar a duração, o erro também aumenta.

Em seguida, tentei usar os parâmetros -ss para cortar o fluxo de áudio:

ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm

O antigo modo clássico funciona muito melhor. A saída foi de 20,003 segundos e tem 960144 amostras. Além disso, aumentar a duração não aumenta o erro, o erro é constante, há sempre 144 amostras excedentes com esse arquivo de entrada.

Resumindo: O filtro select funciona bem na maioria das vezes, mas um select não é. Os parâmetros clássicos -ss funcionam melhor para o áudio, mas não para a amostra. Além disso, não é possível usar os parâmetros -vf select e -ss juntos, porque -ss afetará os fluxos de áudio e vídeo, enquanto queremos que ele afete somente o áudio.

Então, para cortar precisamente um arquivo de mídia eu tenho que fazer estes 3 passos:

ffmpeg -i movie.mp4 -an -vf "select=between(n\,250\,750),setpts=PTS-STARTPTS" v_stream.webm 
ffmpeg -i movie.mp4 -vn -ss 10.000 -to 30.000 a_stream.webm 
ffmpeg -i v_stream.webm -i a_stream.webm -c:v copy -c:a copy  movie-between_10th_and 20th_seconds.webm

Isso fornece os resultados mais precisos. O vídeo tem 20.000 segundos de duração e frame-acurate O áudio tem 20,003 segundos de duração e tem 960144 de amostra. Não corresponde exatamente ao fluxo de vídeo, mas está tudo bem. Há apenas 144 amostras excedentes. A maior desvantagem é, sempre que eu quero cortar um arquivo, eu tenho que enviar 3 comandos para um trabalho simples e ele cria dois arquivos desnecessários: a_stream.webm e v_stream.webm. E o filtro select não está funcionando em alguns arquivos de entrada que tentei. Ele faz o trabalho com sucesso (?), Mas nunca interrompe o processo de codificação, então eu tenho que fechar o prompt de comando toda vez.

    
por destor 18.01.2015 / 02:36

1 resposta

2

O áudio vem de segundos, não de quadros, por isso, se você quiser cortar um vídeo, é necessário calcular os fps de vídeo × 20 segundos desta forma: 20 segundos de 23,97 fps = 479,4

O corte de quadros não é preciso porque você não pode obter fps completos no último segundo, então o áudio terá mais segundos ou apenas meio segundo ou um pouco mais ou menos! Talvez você deva usar segundos em vez de quadros para obter o corte exato e dizer ao ffmpeg para fazer isso por você. E se você obtiver 1 frame extra, o que dizer de mudar 250th e 750th frames para 250th e 749th frames ?! Use menos 1 lá para obter sempre quantos quadros você pede!

    
por 28.06.2017 / 05:52

Tags