Comment changer le framerate d'une vidéo sans réencodage

14

J'essaye de changer le framerate d'une vidéo MP4 (c'est une vidéo GoPro 120fps, je veux la lire à 30fps pour un effet de ralenti).

J'utilise avconv pour cela:

avconv -i SourceMovie.mp4 -vf setpts=4.0*PTS -r 30 DestMovie.mp4

Cela fonctionne techniquement, mais il réencode le film. En plus d'être lent, c'est évidemment un problème de qualité. Techniquement, il devrait y avoir un moyen de simplement définir les fps dans l'en-tête de la vidéo, comment puis-je changer cela? (Tout outil autre que avconv fonctionnerait aussi.)

EboMike
la source

Réponses:

15

MP4Box peut le faire.

La commande

MP4Box -add SourceMovie.mp4#video -raw 1 -new test

crée les fichiers testet test_track1.h264. Vous pouvez maintenant créer un fichier mp4 avec la fréquence d'images prise en charge que vous souhaitez (30 dans cet exemple):

MP4Box -add test_track1.h264:fps=30 -new DestMovie.mp4

MP4Box fait partie du gpacpackage, alors assurez-vous qu'il est installé.

Mitch
la source
6
Ce n'est vraiment pas simple, mais je l'ai compris - vous devez le faire en deux étapes. Extrayez d'abord le flux vidéo séparément en tant que raw ( MP4Box -add source.mp4#video -raw 1 -new test), puis enregistrez-le à nouveau en tant que MP4 ( MP4Box -add test_track1.h264:fps=30 -new dest.mp4). Vous pouvez également y ajouter une piste audio (via #audio).
EboMike
Il est préférable d'utiliser l' -singleoption pour la première commande. MP4Box -single 1 -raw 1 SourceMovie.mp4crée un seul fichier SourceMovie_track1.h264au lieu de deux.
diversenok
6

La modification du débit d'images dans l'en-tête de la vidéo (conteneur) n'a aucun effet sur le flux vidéo (ou audio). Le réencodage est la seule option.

Les flux vidéo ont des horodatages et dans la plupart des vidéos, les images sont interdépendantes en raison de la compression inter-images. Certains joueurs peuvent accélérer et ralentir la vidéo, mais pas par des commandes intégrées ou quelque chose. Aucun joueur ne peut changer le framerate à la volée quand une commande de conteneur le demande. Le fichier vidéo se retrouvera hors spécifications (c'est-à-dire ne respectant pas les normes) et 99,9% des joueurs refuseront de s'y conformer. Il est tout à fait impossible de faire ce que vous voulez sans recodage. Bien sûr, vous pouvez attendre le recodage jusqu'à la dernière étape de votre montage.

thom
la source
1
Merci thom! Question stupide cependant - pourquoi? Chaque image a-t-elle un horodatage qui oblige le lecteur à appliquer une certaine vitesse de lecture? Je veux exactement les mêmes images, je veux juste qu'elles soient lues à un rythme différent.
EboMike
2
Salut Mike, non ta question n'est pas stupide, franchement la façon dont tu penses est assez intelligente. J'aime ta façon de penser. J'ai ajouté plus d'informations à ma réponse car il était trop long pour le mettre dans la boîte de commentaire.
thom
Merci! C'est assez instructif. Maintenant, pour le recodage - quelle est la meilleure façon de le faire avec quelque chose comme avconv? J'ai utilisé la ligne de commande ci-dessus, mais cela a résulté en une qualité horrible - je pouvais presque voir chaque macrobloc.
EboMike
1
Les horodatages des flux vidéo sont stockés dans le conteneur, pas le flux binaire h.264 brut lui-même, je pense. Tant que vous voulez juste changer le timing, mais pas l'ordre, dont la trame est affichée quand, vous ne devriez pas avoir besoin de transcoder, juste de remuxer. (Et si vous utilisez xcode, avec un matériel plus rapide, vous utiliserez -preset plus lent ou très lent pour obtenir plus de qualité au même débit binaire, au lieu de simplement lancer plus de bits au problème. Et utilisez -crf 18 ou quelque chose, pas ABR)
Peter Cordes
1
Je ne peux pas comprendre cependant comment obtenir ffmpeg pour produire un autre taux de rafraîchissement. On dirait que mkvmerge / mp4box sont nécessaires, sauf si vous pouvez obtenir ffmpeg pour sortir un flux binaire .264 brut, puis utiliser l'option fps pour le démultiplexeur h.264 (qui -h complète les documents qu'il possède, car le flux binaire n'a pas de synchronisation info, juste commande.)
Peter Cordes
3

Dans le cas où votre intention principale est de le lire au ralenti, et de ne pas conserver le fichier en MP4, vous pouvez utiliser l'outil GUI MKVmerge pour le remuxer dans un conteneur Matroska qui peut facilement changer le framerate. Le remuxage est bien meilleur que le réencodage, car il ne fait que modifier les métadonnées, et non le flux lui-même.

Vous installez d'abord le package

sudo apt-get install mkvtoolnix-gui

Ensuite, vous démarrez l'interface graphique MKVmerge. Vous serez face à une fenêtre comme celle-ci

mkvmerge gui 1

Appuyez simplement sur le bouton Ajouter et sélectionnez votre fichier ou même faites simplement glisser-déposer le fichier dans la zone "Fichiers d'entrée". À ce stade, vous devriez pouvoir sélectionner le flux vidéo dans votre vidéo. Vous pouvez également supprimer d'autres flux, car ils seront de toute façon gênants.

Après l'avoir sélectionné, vous devriez voir les onglets du bas devenir actifs:

entrez la description de l'image ici

Passer à "Formater des actions spécifiques"

entrez la description de l'image ici

Vous pouvez voir qu'il y a un champ "FPS", où vous pouvez entrer la valeur des images par seconde. Il semblait que vous prévoyiez de ralentir les choses quatre fois, donc environ 7 images par seconde serait votre objectif. Vous pouvez également utiliser l'option "Stretch by".

Après cela, vous pouvez simplement changer le nom du fichier de sortie (si vous le souhaitez) et appuyez sur "Démarrer le multiplexage".

Le programme s'exécutera et vous devriez avoir votre fichier.

v010dya
la source
2

Je voulais également ralentir sans perte mes films à 120 FPS à 30 FPS. J'ai fait un script qui le fait en changeant le tempo du son et en modifiant FPS directement dans le conteneur MP4. Les outils suivants sont requis:

  1. avconv pour convertir des flux audio
  2. sondstretch pour ralentir le tempo audio
  3. gpac pour obtenir MP4Box pour changer FPS

Le script utilisé pour la conversion est ici:

#!/bin/bash
#########################################
# Lossless slow down from 120 to 30 FPS #
#                                       #
# Use:                                  #
#                                       #
#   slow.bash <mp4_file>                #
#                                       #
#                           #-= OSi =-# #
#########################################


# Prepare basic variables
IN_FILE="$1"
NAME=$(echo "${IN_FILE}" | sed 's/\.[^.]*//')


# Clean up before start
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264" "${NAME}_slow.mp4"


# Slow down sound
avconv -i "${IN_FILE}" -vn -acodec pcm_s16le "${NAME}_.wav"
soundstretch "${NAME}_.wav" "${NAME}.wav" -tempo=-75
avconv -i "${NAME}.wav" -vn -codec:a ac3_fixed -b:a 448k "${NAME}.ac3"


# Change video frame rate and multiplex with slowed sound
MP4Box -add "${IN_FILE}#video" -raw 1 -new "${NAME}"
MP4Box -add "${NAME}_track1.h264:fps=30" -add "${NAME}.ac3" -new "${NAME}_slow.mp4"


# Clean up when we are done
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264"

Ce script crée une copie de MP4 avec le suffixe _slow.

OSi
la source