Rotation de vidéos avec FFmpeg

417

J'ai essayé de comprendre comment faire pivoter des vidéos avec FFmpeg. Je travaille avec des vidéos iPhone prises en mode portrait. Je sais comment déterminer les degrés de rotation actuels en utilisant MediaInfo (excellente bibliothèque, btw) mais je suis bloqué sur FFmpeg maintenant.

D'après ce que j'ai lu, ce que vous devez utiliser est une option vfilter . Selon ce que je vois, cela devrait ressembler à ceci:

ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4

Cependant, je ne peux pas faire fonctionner cela. D'abord, -vfilters n'existe plus, c'est maintenant juste -vf . Deuxièmement, je reçois cette erreur:

No such filter: 'rotate'
Error opening filters!

Pour autant que je sache, j'ai une version toutes options sur FFmpeg. L'exécution de ffmpeg -filters montre ceci:

Filters:
anull            Pass the source unchanged to the output.
aspect           Set the frame aspect ratio.
crop             Crop the input video to x:y:width:height.
fifo             Buffer input images and send them when they are requested.
format           Convert the input video to one of the specified pixel formats.
hflip            Horizontally flip the input video.
noformat         Force libavfilter not to use any of the specified pixel formats
 for the input to the next filter.
null             Pass the source unchanged to the output.
pad              Pad input image to width:height[:x:y[:color]] (default x and y:
 0, default color: black).
pixdesctest      Test pixel format definitions.
pixelaspect      Set the pixel aspect ratio.
scale            Scale the input video to width:height size and/or convert the i
mage format.
slicify          Pass the images of input video on to next video filter as multi
ple slices.
unsharp          Sharpen or blur the input video.
vflip            Flip the input video vertically.
buffer           Buffer video frames, and make them accessible to the filterchai
n.
color            Provide an uniformly colored input, syntax is: [color[:size[:ra
te]]]
nullsrc          Null video source, never return images.
nullsink         Do absolutely nothing with the input video.

Avoir les options pour vflip et hflip est génial et tout, mais ils ne me mèneront tout simplement pas là où je dois aller. J'ai besoin au moins de faire pivoter les vidéos de 90 degrés. 270 degrés serait également une excellente option. Où sont passées les options de rotation?

jocull
la source
77
Pour tous ceux qui recherchent une rotation à 180 degrés:-vf "vflip,hflip"
OrangeDog
4
Je me demande si cela peut être réalisé sans décodage puis recodage de la vidéo - la façon dont jpegtran peut faire tourner sans perte des images JPEG ...
Mikhail T.
2
Voir ici pour l'indicateur de rotation: stackoverflow.com/questions/15335073/…
Davor Josipovic
1
Voir également la réponse détaillée à Comment retourner une vidéo à 180 ° (vertical / à l'envers) avec FFmpeg? N'oubliez pas de réinitialiser toutes les métadonnées de rotation existantes (voir le lien).
llogan
1
Je viens de télécharger une vidéo tournée à 180 ° avec "transpose = 1, transpose = 1" sur vimeo. Même si je peux lire la vidéo pivotée, elle a été rejetée par vimeo. @ L'approche d'OrangeDog -vf "vflip,hflip"fonctionne comme un charme.
Besi

Réponses:

683

Faire pivoter de 90 dans le sens des aiguilles d'une montre:

ffmpeg -i in.mov -vf "transpose=1" out.mov

Pour le paramètre de transposition, vous pouvez passer:

0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

Utilisez -vf "transpose=2,transpose=2"pour 180 degrés.

Assurez-vous d'utiliser une version récente de ffmpeg à partir d'ici (une construction statique fonctionnera correctement).

Notez que cela ré-encodera les parties audio et vidéo. Vous pouvez généralement copier l'audio sans le toucher, en utilisant -c:a copy. Pour modifier la qualité vidéo, définissez le débit binaire (par exemple avec -b:v 1M) ou consultez le guide d'encodage H.264 si vous souhaitez des options VBR.

Une solution consiste également à utiliser ce script de commodité .

Alexy
la source
8
La vidéo aura toujours les informations d'orientation alors maintenant la vidéo sera corrigée sur l'iphone.
srcspider
26
Lorsque j'utilise cette commande, je reçois une sortie vidéo de faible qualité , à moins que - comme je viens de découvrir - j'utiliser ce paramètre ainsi: -vcodec libx264. Mais ce serait bien si je n'avais pas besoin de chercher quel encodage utiliser car ffmpeg devrait déjà le savoir. Aucune suggestion?
Sadi
8
Dans le même esprit que Sadi, existe-t-il un moyen de "copier" la qualité de la vidéo originale?
Alec Jacobson
58
Pour 180, vous pouvez utiliser-vf "transpose=2,transpose=2"
Alex Pliutau
23
Les documents actuels notent que "les valeurs numériques sont obsolètes et devraient être supprimées au profit des constantes symboliques." ffmpeg.org/ffmpeg-filters.html#transpose Ainsi cclock_flip, clock, cclockou au clock_fliplieu de 0, 1, 2ou 3.
l --marc l
149

Si vous ne voulez pas recoder votre vidéo ET que votre lecteur peut gérer les métadonnées de rotation, vous pouvez simplement changer la rotation dans les métadonnées à l'aide de ffmpeg:

ffmpeg -i input.m4v -metadata:s:v rotate="90" -codec copy output.m4v
Polo Rodrigo
la source
11
que diriez-vous de vérifier les métadonnées de rotation d'abord avecffmpeg -i input.m4v 2>&1 | grep rotate
lidaobing
60
C'est de loin la meilleure réponse. Mais il y a une petite amélioration à faire. Pour éviter de perdre les métadonnées restantes (telles que la date, la caméra) sur la vidéo ffmpeg -i input.m4v -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.m4v. De cette façon, toutes les métadonnées globales du fichier d'entrée seront copiées en tant que métadonnées globales dans le fichier de sortie et seules les métadonnées de rotation sont modifiées.
migle
11
Si vous avez une vidéo en mode portrait et que vous souhaitez simplement la "dé-tourner" pour avoir une résolution 1920 x 1080 standard, vous le voudrez probablement rotate=0.
mivk
1
Essayé -metadata:s:v rotate="180", n'a pas fonctionné. Est-ce censé fonctionner?
Ondra Žižka
7
IMHO meilleure solution car aucun réencodage n'est nécessaire et la plupart des lecteurs vidéo prennent en charge la rotation des métadonnées. Également des services cloud comme Google Photos. Cependant, rappelez-vous que ffmpeg ne copie pas nécessairement toutes les métadonnées du fichier d'origine! Par conséquent, je recommanderais de spécifier explicitement de copier toutes les autres métadonnées du fichier d'origine:ffmpeg -i input.mp4 -codec copy -map_metadata 0 -metadata:s:v:0 rotate=0 output.mp4
Andreas
83

Avez-vous déjà essayé transpose? Comme (de l'autre réponse)

 ffmpeg -i input -vf transpose=2 output

Si vous utilisez une ancienne version, vous devez mettre à jour ffmpeg si vous souhaitez utiliser la fonction de transposition, comme elle a été ajoutée en octobre 2011.

La page de téléchargement FFmpeg propose des versions statiques que vous pouvez exécuter directement sans avoir à les compiler.

rwilliams
la source
1
Non je n'ai pas. Je ne savais pas que ça existait. Je vais essayer ça.
jocull
Le filtre de transposition ne semble exister dans aucune de mes versions FFmpeg. Comment suis-je censé l'ajouter?
jocull du
Dans la version des documents à partir du 2011-05-15, le lien correct est maintenant ffmpeg.org/ffmpeg-doc.html#SEC93
Peter Hansen
7
J'ai l'impression d'avoir été puni pour avoir offert une réponse utile 1,5 an avant la réponse acceptée.
rwilliams
1
@JonasB Séparez les filtres par des virgules. Voir stackoverflow.com/questions/6195872/…
rwilliams
19

Je suis tombé sur cette page en cherchant la même réponse. Cela fait maintenant six mois que cela a été demandé à l'origine et les versions ont été mises à jour plusieurs fois depuis. Cependant, je voulais ajouter une réponse pour toute autre personne qui vient ici à la recherche de ces informations.

J'utilise la version Debian Squeeze et FFmpeg de ces dépôts.

La page MAN pour ffmpeg indique l'utilisation suivante

ffmpeg -i inputfile.mpg -vf "transpose=1" outputfile.mpg

La clé étant que vous ne devez pas utiliser une variable de degré, mais une variable de réglage prédéfinie à partir de la page MAN.

0=90CounterCLockwise and Vertical Flip  (default) 
1=90Clockwise 
2=90CounterClockwise 
3=90Clockwise and Vertical Flip
Zonjai
la source
Merci pour l'info! Je n'ai jamais réussi à faire fonctionner cela, car j'ai généralement du mal à construire à partir de la source. Je peux voir si je peux le faire fonctionner à nouveau maintenant.
jocull
transposer = 3 fait refléter l'image
Daniel Kobe
transpose = 2 a fonctionné sans mise en miroir pour ma vidéo pivotée 270
Daniel Kobe
17

Pour faire pivoter l'image dans le sens horaire, vous pouvez utiliser le filtre de rotation, indiquant un angle positif en radians. Avec 90 degrés équivalant à PI / 2, vous pouvez le faire comme suit:

ffmpeg -i in.mp4 -vf "rotate=PI/2" out.mp4

dans le sens antihoraire, l'angle doit être négatif

ffmpeg -i in.mp4 -vf "rotate=-PI/2" out.mp4

Le filtre de transposition fonctionnera également bien à 90 degrés, mais pour d'autres angles, c'est un choix plus rapide ou unique.

Bijou Trouvaille
la source
2
c'est bien. J'ai trouvé qu'il est possible d'obtenir une résolution plus fine des radians, car *se comporte comme une multiplication: ffmpeg -i in.avi -vf "rotate=-8*PI/40" -q 1 out.avi (rotation légèrement inférieure à -PI / 4 = -10 * PI / 40)
eqzx
12
ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4 

ne fonctionnera pas, même avec la dernière source ...

doit changer la commande:

ffmpeg -i input.mp4 -vf vflip output.mp4

fonctionne bien

nano
la source
c'est parce que vous appliquez le filtre au mauvais fichier ... essayez ffmpeg -i input.mp4 -vf "tourner = 90" output.mp4, alors ça marchera
patrick
2
"Faites pivoter la vidéo selon un angle arbitraire exprimé en radians ." Documentation: ffmpeg.org/ffmpeg-filters.html#rotate Donc, radians rotate=PI/2ou rotate=90*PI/180est nécessaire
l --marc l
C'est fantastique
Tessaracter
7

Si vous obtenez une erreur "Le codec est expérimental mais les codecs expérimentaux ne sont pas activés", utilisez ceci:

ffmpeg -i inputFile -vf "transpose=1" -c:a copy outputFile

Est arrivé avec moi pour un fichier .mov avec audio aac.

sabujp
la source
C'était le seul exemple qui a fonctionné pour moi, mais la qualité était terrible et très inégale. En outre, il a réduit une vidéo 1080x1920 à 352x640. Je suppose qu'il me manque un interrupteur ou deux. Aucune suggestion?
LOlliffe
1
@LOlliffe add-sameq
Andrew Schleifer
2
@AndrewSchleifer Merci. J'ai essayé cela, mais ffmpeg m'a Option 'sameq' was removed. If you are looking for an option to preserve the quality (which is not what -sameq was for), use -qscale 0 or an equivalent quality factor option. Failed to set value '1' for option 'sameq': Invalid argument renvoyé - qscale donne également une erreur. Please use -q:a or -q:v, -qscale is ambiguous, mais fonctionne toujours.
LOlliffe
3

Ce script qui affichera les fichiers avec la structure de répertoires sous "fixedFiles". Pour le moment est fixé sur des fichiers MOV et exécutera un certain nombre de transformations en fonction de la "rotation" originale de la vidéo. Fonctionne avec les vidéos capturées iOS sur un Mac exécutant Mavericks, mais devrait être facilement exportable. Dépend d'avoir installé à la fois exiftool et ffmpeg .

#!/bin/bash

# rotation of 90 degrees. Will have to concatenate.
#ffmpeg -i <originalfile> -metadata:s:v:0 rotate=0 -vf "transpose=1" <destinationfile>
#/VLC -I dummy -vvv <originalfile> --sout='#transcode{width=1280,vcodec=mp4v,vb=16384,vfilter={canvas{width=1280,height=1280}:rotate{angle=-90}}}:std{access=file,mux=mp4,dst=<outputfile>}\' vlc://quit

#Allowing blanks in file names
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

#Bit Rate
BR=16384

#where to store fixed files
FIXED_FILES_DIR="fixedFiles"
#rm -rf $FIXED_FILES_DIR
mkdir $FIXED_FILES_DIR

# VLC
VLC_START="/Applications/VLC.app/Contents/MacOS/VLC -I dummy -vvv"
VLC_END="vlc://quit"


#############################################
# Processing of MOV in the wrong orientation
for f in `find . -regex '\./.*\.MOV'` 
do
  ROTATION=`exiftool "$f" |grep Rotation|cut -c 35-38`
  SHORT_DIMENSION=`exiftool "$f" |grep "Image Size"|cut -c 39-43|sed 's/x//'`
  BITRATE_INT=`exiftool "$f" |grep "Avg Bitrate"|cut -c 35-38|sed 's/\..*//'`
  echo Short dimension [$SHORT_DIMENSION] $BITRATE_INT

  if test "$ROTATION" != ""; then
    DEST=$(dirname ${f})
    echo "Processing $f with rotation $ROTATION in directory $DEST"
    mkdir -p $FIXED_FILES_DIR/"$DEST"

    if test "$ROTATION" == "0"; then
      cp "$f" "$FIXED_FILES_DIR/$f"

    elif test "$ROTATION" == "180"; then
#      $(eval $VLC_START \"$f\" "--sout="\'"#transcode{vfilter={rotate{angle=-"$ROTATION"}},vcodec=mp4v,vb=$BR}:std{access=file,mux=mp4,dst=\""$FIXED_FILES_DIR/$f"\"}'" $VLC_END )
      $(eval ffmpeg -i \"$f\" -vf hflip,vflip -r 30 -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\")

    elif test "$ROTATION" == "270"; then
      $(eval ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=2,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\" )

    else
#      $(eval $VLC_START \"$f\" "--sout="\'"#transcode{scale=1,width=$SHORT_DIMENSION,vcodec=mp4v,vb=$BR,vfilter={canvas{width=$SHORT_DIMENSION,height=$SHORT_DIMENSION}:rotate{angle=-"$ROTATION"}}}:std{access=file,mux=mp4,dst=\""$FIXED_FILES_DIR/$f"\"}'" $VLC_END )
      echo ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=1,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\" 
      $(eval ffmpeg -i \"$f\" -vf "scale=$SHORT_DIMENSION:-1,transpose=1,pad=$SHORT_DIMENSION:$SHORT_DIMENSION:\(ow-iw\)/2:0" -r 30 -s "$SHORT_DIMENSION"x"$SHORT_DIMENSION" -metadata:s:v:0 rotate=0 -b:v "$BITRATE_INT"M -vcodec libx264 -acodec copy \"$FIXED_FILES_DIR/$f\" )

    fi

  fi

echo 
echo ==================================================================
sleep 1
done

#############################################
# Processing of AVI files for my Panasonic TV
# Use ffmpegX + QuickBatch. Bitrate at 16384. Camera res 640x424
for f in `find . -regex '\./.*\.AVI'` 
do
  DEST=$(dirname ${f})
  DEST_FILE=`echo "$f" | sed 's/.AVI/.MOV/'`
  mkdir -p $FIXED_FILES_DIR/"$DEST"
  echo "Processing $f in directory $DEST"
  $(eval ffmpeg -i \"$f\" -r 20 -acodec libvo_aacenc -b:a 128k -vcodec mpeg4 -b:v 8M -flags +aic+mv4 \"$FIXED_FILES_DIR/$DEST_FILE\" )
echo 
echo ==================================================================

done

IFS=$SAVEIFS
David Costa Faidella
la source
2
Aïe ... Cela peut fonctionner, mais c'est parfaitement hideux. Tout d'abord, la règle générale de la programmation shell: vous n'avez jamais besoin de plus d'un grep, cut, awk ou sed dans un pipe. Tout grep | cut | sed est réalisable avec sed ou awk seul. Ensuite, plus spécifiquement, exiftool peut être invité à sortir uniquement les balises que vous voulez - donc au lieu de filtrer la rotation, juste "exiftool -Rotation". Troisièmement, vous n'avez pas besoin d'autant de "preuves" et votre "si test ..." devrait être remplacé par le cas $ ROTATION in - pour la lisibilité et l'efficacité. Bonne chance!
Mikhail T.
Pas de dés: [Parsed_pad_2 @ 0x7f8b15c3a580] Input area -420:0:1500:1080 not within the padded area 0:0:1080:1080 or zero-sized\ n ` [Parsed_pad_2 @ 0x7f8b15c3a580] Failed to configure input pad on Parsed_pad_2\ n Error reinitializing filters!\ n Failed to inject frame into filter network: Invalid argument\ n Error while processing the decoded data for stream #0:0\ nConversion failed!
Slipp D. Thompson
2

La réponse d'Alexy a presque fonctionné pour moi, sauf que je recevais cette erreur:

base de temps 1/90000 non prise en charge par la norme MPEG 4, la valeur maximale admise pour le dénominateur de base de temps est 65535

J'ai juste dû ajouter un paramètre (-r 65535/2733) à la commande et cela a fonctionné. La commande complète était donc:

ffmpeg -i in.mp4 -vf "transpose=1" -r 65535/2733 out.mp4
smoyth
la source
Si vous recherchez une fréquence d'images "NTSC-film", ce 24000/1001serait plus précis.
Reino
2

Une solution supplémentaire avec une approche différente des dernières solutions mentionnées, consiste à vérifier si votre pilote de caméra prend en charge les commandes de la caméra v4l2 (ce qui est très courant).
Dans le terminal, tapez simplement:

v4l2-ctl -L

Si votre pilote de caméra prend en charge les commandes de la caméra v4l2, vous devriez obtenir quelque chose comme ceci (la liste ci-dessous dépend des commandes prises en charge par votre pilote de caméra):

               contrast (int)    : min=0 max=255 step=1 default=0 value=0 flags=slider
             saturation (int)    : min=0 max=255 step=1 default=64 value=64 flags=slider
                    hue (int)    : min=0 max=359 step=1 default=0 value=0 flags=slider
white_balance_automatic (bool)   : default=1 value=1 flags=update
            red_balance (int)    : min=0 max=4095 step=1 default=0 value=128 flags=inactive, slider
           blue_balance (int)    : min=0 max=4095 step=1 default=0 value=128 flags=inactive, slider
               exposure (int)    : min=0 max=65535 step=1 default=0 value=885 flags=inactive, volatile
         gain_automatic (bool)   : default=1 value=1 flags=update
                   gain (int)    : min=0 max=1023 step=1 default=0 value=32 flags=inactive, volatile
        horizontal_flip (bool)   : default=0 value=0
          vertical_flip (bool)   : default=0 value=0

Et si vous êtes chanceux, il prend en charge horizontal_flip et vertical_flip .
Ensuite, tout ce que vous devez faire est de définir le horizontal_flip en:

v4l2-ctl --set-ctrl horizontal_flip=1

ou le vertical_flip par:

v4l2-ctl --set-ctrl vertical_flip=1

puis vous pouvez appeler votre appareil vidéo pour capturer une nouvelle vidéo (voir l'exemple ci-dessous), et la vidéo sera tournée / retournée.

ffmpeg -f v4l2 -video_size 640x480 -i /dev/video0 -vcodec libx264 -f mpegts input.mp4

Bien sûr, si vous devez traiter une vidéo déjà existante, cette méthode n'est pas la solution que vous recherchez.

L'avantage de cette approche est que nous inversons l'image au niveau du capteur, de sorte que le capteur du pilote nous donne déjà l'image retournée, ce qui évite à l'application (comme FFmpeg) tout traitement supplémentaire et inutile.

JM
la source
Excellentes informations sur v4l2 ici. Il est évidemment préférable de tourner dans la bonne orientation au moment de l'enregistrement :) Cette question de près de 10 ans (wow!) A été initialement posée sur les vidéos téléchargées à partir d'appareils iOS si cela aide à fournir un contexte :)
jocull
Je suis un peu nouveau dans cette communauté et cette question est beaucoup plus ancienne que mon ancienneté ici ... Je pense vraiment que c'est une bonne (et commune) question, donc je pense que cette vieille question continuera d'aider de nombreux utilisateurs de FFmpeg.
JM
1

Malheureusement, la version Ubuntu de ffmpeg prend en charge les filtres vidéo.

Vous devez utiliser avidemux ou un autre éditeur pour obtenir le même effet.

De manière programmatique, mencoder a été recommandé.

ldig
la source
1
Vouliez-vous dire "La version Ubuntu de ffmpeg ne prend pas en charge les filtres vidéo"?
user1438038
2
Pour info: "FFmpeg est de retour dans Ubuntu 15.04 Vivid Vervet." ou peut être compilé pour Ubuntu. -> trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
l --marc l
avconv le fait (en 14.04), et semble fonctionner exactement de la même manière. (Mais pour les versions ultérieures, utilisez certainement FFmpeg.)
SilverWolf - Réinstallez Monica le
1

Smartphone: récupération d'une vidéo au format vertical

Vous voulez l'envoyer à un site Web, il était de 90 ° vers la gauche (anti-horaire, format paysage) hmm.

ffmpeg -i input.mp4 -vf "rotate=0" output.mp4

le fait. J'ai retrouvé le format vertical

debian buster: ffmpeg --version ffmpeg version 4.1.4-1 ~ deb10u1 Copyright (c) 2000-2019 les développeurs FFmpeg

fb
la source