Cambia framerate in ffmpeg senza ricodifica


14

Ho un video mkv (h264) che è 23.976 fps (24000/1001) ma voglio convertirlo in 25fps senza ricodificare e perdere qualità. So che mkvmerge può farlo (con l'opzione --default-duration '0: 25fps') ma mi piacerebbe farlo direttamente da ffmpeg se possibile Secondo i documenti questo dovrebbe funzionare:

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

ma quando lo eseguo ottengo solo gli stessi video fps. Qual è il metodo corretto per farlo (se esiste) in ffmpeg?


1
Credo che al momento non sia possibile con FFmpeg. -rnon è compatibile con la copia stream e non ci sono filtri bitstream per modificare il framerate.
Ely,

1
peccato. Dovrò usare mkvmerge ogni volta. grazie
phate89,

1
C'è un modo contorto per farlo con ffmpeg normale e un modo diretto per farlo con una vecchia versione modificata di ffmpeg. Se sei interessato, lo scrivo come una risposta.
Gyan,

1
Sì grazie..Vorrei farlo senza strumenti extra (ho già bisogno di ffmpeg)
phate89

1
@Mulvya stai parlando di questo giusto? Ho esitato a collegarlo, ma ora è vecchio .. Interessato al modo contorto di farlo con FFmpeg normale però.
Ely,

Risposte:


15

Ecco il metodo che utilizza le versioni correnti di FFmpeg. Si basa sul demuxer concat non riscalando il PTS degli input dopo il primo file, ma semplicemente applicando un offset fisso. Supponiamo che tu abbia un flusso di 30 fps con una scala temporale 15360(tipica dell'output di FFmpeg). Ciò significa che frame 0ha PTS 0e frame 30ha PTS 15360. Questo diventerebbe un flusso a 45 fps se potessimo cambiare la scala temporale 23040senza influenzare i valori PTS.

In sostanza, questo è quello che fa il metodo seguente.

1 . Identificare le proprietà di origine.

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

Si desidera annotare le proprietà della sorgente, in particolare la risoluzione e tbn.


2a . (Facoltativo) Cambia la scala temporale in qualcosa di conveniente, per semplificare i calcoli.

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

Questo ci prende

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

Se esegui questo passaggio, la nuova scala cronologica dovrebbe essere uguale o un multiplo integrale del framerate originale.

2b . Calcola la scala temporale necessaria, in modo che per il framerate di destinazione x, il PTS del frame # xnella sorgente abbia lo stesso valore del nuovo tbn. Se hai eseguito il passaggio 2a, questo è molto semplice ed è semplicemente il nuovo framerate. Quindi, per i target fps 45, tbndovrebbe essere nuovo 45.


3 . Genera video fittizi.

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

Tutte le proprietà dovrebbero essere uguali a risoluzione, profilo H.264, formato pixel, conteggio ref .. ecc per i migliori risultati.


4 Concat i video.

Per prima cosa crea un file di testo

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

Quindi, il concat

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

Il file di output avrà il secondo video riprodotto a 45 fps.

5 . Ora, togli il preroll fittizio

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

e tu hai

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

Ho detto che questo era contorto!


1
molto intelligente, buona risposta.
Rowe Morehouse,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.