web-dev-qa-db-fra.com

Changer le framerate dans ffmpeg sans reencodage

J'ai une vidéo mkv (h264) de 23,976 i/s (24000/1001) mais je souhaite la convertir à 25 i/s sans réencodage ni perte de qualité. Je sais que mkvmerge peut le faire (avec l'option --default-duration '0: 25fps') mais j'aimerais le faire directement depuis ffmpeg si possible. Selon la documentation, cela devrait fonctionner:

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

mais quand je l'exécute, je ne reçois que les mêmes images par seconde. Quelle est la bonne méthode pour le faire (s'il existe) dans ffmpeg?

12
phate89

Voici la méthode utilisant les versions actuelles de FFmpeg. Il repose sur le démultiplexeur concat ne pas redimensionner le PTS des entrées après le premier fichier, mais simplement appliquer un décalage fixe. Supposons que vous ayez un flux de 30 images par seconde avec une échelle de temps de 15360 (typique de la sortie FFmpeg). Cela signifie que frame 0 a PTS 0 et frame 30 a PTS 15360. Cela deviendrait un flux de 45 ips si nous pouvions changer l’échelle de temps en 23040 sans affecter les valeurs PTS.

C'est essentiellement ce que fait la méthode ci-dessous.

1 . Identifiez les propriétés de la source.

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

Vous souhaitez noter les propriétés source, en particulier résolution et tbnname__.


2a . (Facultatif) Modifiez l’échelle de temps en fonction de vos besoins afin de simplifier les calculs.

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

Cela nous obtient

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

Si vous faites cette étape, la nouvelle échelle de temps doit être égale ou un multiple entier de la fréquence d'images d'origine.

2b . Calculez l'échelle de temps nécessaire pour que, pour le framerate cible xname__, le PTS de l'image # xdans la source ait la même valeur que le nouveau tbnname__. Si vous avez effectué l'étape 2a, c'est très simple et il ne s'agit que du nouveau framerate. Ainsi, pour les images cibles 45, new tbndevrait être 45.


3 . Générer une vidéo factice.

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

Toutes les propriétés doivent être identiques (résolution, profil H.264, format de pixel, nombre de références, etc.) pour obtenir les meilleurs résultats.


4 Concattez les vidéos.

Commencez par créer un fichier texte

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

Ensuite, le concat

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

La deuxième vidéo sera lue à 45 ips dans le fichier de sortie.

5 . Maintenant, cliver le preroll factice

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

et tu as

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

J'ai dit que c'était compliqué!

13
Gyan