Alterar taxa de quadros em ffmpeg sem reencodificar

14

Eu tenho um vídeo mkv (h264) que é 23.976 fps (24000/1001), mas quero convertê-lo para 25 fps sem reencodificar e perder qualidade. Eu sei que o mkvmerge pode fazer isso (com a opção --default-duration '0: 25fps'), mas eu gostaria de fazê-lo diretamente do ffmpeg, se possível De acordo com os documentos, isso deve funcionar:

ffmpeg -i input.mkv -r 25 -vcodec copy output.mkv

mas quando o executo, recebo apenas o mesmo vídeo fps. Qual é o método correto para fazê-lo (se existir) no ffmpeg?

phate89
fonte
1
Eu acredito que não é possível com o FFmpeg no momento. -rnão é compatível com a cópia de fluxo e não há filtros de fluxo de bits para alterar a taxa de quadros.
Ely
1
que pena. Vou ter que usar mkvmerge toda vez. graças
phate89
1
Existe uma maneira complicada de fazer isso com o ffmpeg regular e uma maneira direta de fazer isso com uma versão modificada antiga do ffmpeg. Se você estiver interessado, escreverei como resposta.
Gyan
1
Sim thanks..I'd como fazê-lo sem ferramentas extras (eu já precisa ffmpeg)
phate89
1
@Mulvya você está falando sobre isso certo? Hesitei em vinculá-lo, mas agora é antigo. Interessado na maneira complicada de fazê-lo com o FFmpeg regular.
Ely

Respostas:

15

Aqui está o método usando as versões atuais do FFmpeg. Ele conta com o desmuxer concat não redimensionando o PTS das entradas após o primeiro arquivo, mas simplesmente aplicando um deslocamento fixo. Digamos que você tenha um fluxo de 30 qps com uma escala de tempo 15360(típica da saída FFmpeg). Isso significa que o quadro 0possui PTS 0e o quadro 30possui PTS 15360. Isso se tornaria um fluxo de 45 fps se pudéssemos alterar a escala de tempo para 23040sem afetar os valores do PTS.

Essencialmente, é isso que o método abaixo faz.

1 . Identifique as propriedades de origem.

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s,
       30 fps, 30 tbr, 15360 tbn (default)

Você deseja anotar as propriedades de origem, especialmente resolução e tbn.


2a . (Opcional) Altere a escala de tempo para algo conveniente, para simplificar os cálculos.

ffmpeg -i in.mp4 -c copy -an -video_track_timescale 30 in-v30.mp4

Isso nos leva

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s, \
       30 fps, 30 tbr, 30 tbn (default

Se você executar esta etapa, a nova escala de tempo deverá ser igual ou um múltiplo integral da taxa de quadros original.

2b . Calcule a escala de tempo necessária para que, para a taxa de quadros de destino x, o PTS do quadro # xna origem tenha o mesmo valor que o novo tbn. Se você executou a etapa 2a, isso é muito fácil e é simplesmente a nova taxa de quadros. Portanto, para o alvo fps 45, novo tbndeve ser 45.


3 . Gere vídeo fictício.

ffmpeg -f lavfi -i color=s=1280x720:r=45:d=1 -profile:v main -video_track_timescale 45 0.mp4

Todas as propriedades devem ser iguais, como resolução, perfil H.264, formato de pixel, refs count ... etc para obter melhores resultados.


4 Concat os vídeos.

Primeiro crie um arquivo de texto

file '0.mp4'
file 'in-v30.mp4'

Então, o concat

ffmpeg -f concat -i list.txt -c copy -video_track_timescale 45 45fps.mp4

O arquivo de saída terá o segundo vídeo sendo reproduzido a 45 fps.

5 . Agora, retire o pré-jogo fictício

ffmpeg -ss 1.1 -i 45fps.mp4 -c copy -avoid_negative_ts make_zero in45.mp4

e você tem

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1757 kb/s, \
       45 fps, 45 tbr, 11520 tbn (default)

Eu disse que isso foi complicado!

Gyan
fonte
1
muito inteligente, boa resposta.
Rowe Morehouse