96 votes

Comment faire pivoter une vidéo de 180° avec FFmpeg?

J'ai une vidéo qui a été tournée à 180° lors de l'enregistrement. Est-il possible de corriger cela avec FFmpeg?

133voto

llogan Points 50040

originalrotated


tl;dr

ffmpeg va automatiquement faire pivoter la vidéo sauf si :

  • votre entrée ne contient pas de métadonnées de rotation
  • votre ffmpeg est trop ancien

Métadonnées de rotation

Certaines vidéos, telles que celles des iPhones, ne sont pas physiquement retournées, mais contiennent des données côté vidéo ou des métadonnées de rotation. Certains lecteurs ignorent ces métadonnées et d'autres non. Consultez la sortie de la console ffmpeg pour voir si votre entrée contient de telles métadonnées :

$ ffmpeg -i input.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Duration: 00:00:05.00, start: 0.000000, bitrate: 43 kb/s
    Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 39 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      rotate          : 180
    Side data:
      displaymatrix: rotation of -180.00 degrees

Rotation automatique

ffmpeg fera automatiquement pivoter physiquement la vidéo en fonction des métadonnées de rotation de flux vidéo existantes.

Vous avez besoin d'une version qui inclut le commit 1630224, du 2 mai 2015, pour pouvoir utiliser la fonction d'autorotation.

Exemple

ffmpeg -i input.mp4 -c:a copy output.mp4

Pour désactiver ce comportement, utilisez l'option -noautorotate.


Si l'entrée ne contient pas de métadonnées ou si votre ffmpeg est ancien

Vous devrez utiliser un filtre pour faire pivoter la vidéo, et s'il existe des métadonnées de rotation, elles devront être supprimées comme indiqué dans les exemples ci-dessous :

Exemples

En utilisant ffmpeg, vous avez le choix entre trois méthodes d'utilisation de filtres vidéo pour faire pivoter de 180°.

hflip et vflip

ffmpeg -i input.mp4 -vf "hflip,vflip,format=yuv420p" -metadata:s:v rotate=0 \
-codec:v libx264 -codec:a copy output.mkv

transpose

ffmpeg -i input.mp4 -vf "transpose=2,transpose=2,format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

rotate

Ce filtre peut faire pivoter vers n'importe quel angle arbitraire et utilise des radians comme unité au lieu de degrés. Cet exemple fera pivoter /1 radians, soit 180° :

ffmpeg -i input.mp4 -vf "rotate=PI:bilinear=0,format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

Vous pouvez utiliser les degrés à la place. Un degré est égal à /180 radians. Donc si vous voulez faire pivoter de 45° :

ffmpeg -i input.mp4 -vf "rotate=45*(PI/180),format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 -codec:a copy output.mp4

Lors de l'utilisation du filtre rotate, l'interpolation bilinéaire doit être désactivée (en utilisant bilinear=0) pour des angles divisibles par 90, sinon cela peut sembler flou.


Notes

  • Le filtrage nécessite un encodage. Ces exemples créent des sorties vidéo H.264. Consultez le Guide d'encodage vidéo H.264 de FFmpeg pour obtenir des conseils sur la qualité que vous souhaitez.

  • Sous-échantillonnage chromatique. J'ai inclus format=yuv420p car ffmpeg tentera de minimiser ou d'éviter le sous-échantillonnage chromatique (selon le codeur, l'entrée, la version de ffmpeg, etc.). C'est un bon comportement d'un point de vue purement technique, mais la plupart des lecteurs sont incompatibles avec des schémas de sous-échantillonnage chromatique plus "avancés". C'est la même chose que d'utiliser -pix_fmt yuv420, mais est commodément situé dans le chaîne de filtres.

  • Conserver l'audio. L'option -codec:a copy effectuera une copie de flux (re-mux) au lieu d'encoder. Il n'y a aucune raison de réencoder l'audio si vous voulez uniquement manipuler la vidéo (à moins que vous ne vouliez convertir vers un format audio différent). Cela économisera du temps car l'encodage est long et cela préservera la qualité de l'audio.


Pivoter lors de la lecture

Alternativement, vous pouvez faire pivoter lors de la lecture et éviter le réencodage. ffplay fera pivoter automatiquement :

ffplay input.mp4

S'il n'y a pas de données côté displaymatrix ou de métadonnées de rotation, vous pouvez utiliser les filtres :

ffplay -vf "hflip,vflip" -i input.mp4

... ou consultez votre lecteur préféré. La plupart des lecteurs de qualité, comme VLC, ont cette fonctionnalité.


Obtenir ffmpeg

Les anciennes versions de ffmpeg ne comprennent pas les capacités de filtrage. Consultez la page de téléchargement de FFmpeg pour plusieurs options, y compris des versions pratiques pour Linux, OS X et Windows, ou consultez le Wiki de FFmpeg pour des guides de compilation ffmpeg étape par étape.

8voto

Albin Points 180

FFMPEG a modifié le comportement par défaut pour tourner automatiquement les sources vidéo d'entrée avec des métadonnées "rotate" dans la version 2.7 en 2015.

Si vous savez que votre script ou commande ne s'exécutera jamais sur des versions de ffmpeg antérieures à 2.7, la solution la plus simple est de supprimer toute rotation personnalisée basée sur les métadonnées.

Pour les autres cas, vous pouvez assurer la compatibilité future en conservant votre code de rotation personnalisé et en ajoutant le drapeau -noautorotate (cela est pris en charge dans les anciennes versions qui étaient encore maintenues à l'époque).

2voto

Mxx Points 2763

Les lecteurs multimédias qui utilisent ffmpeg comme backend de décodage peuvent également utiliser tous ses filtres. Voir cette capture d'écran avec le filtre "Décalage & retournement". entrer la description de l'image ici

Alternativement, si vous souhaitez ré-encoder votre vidéo, consultez Rotation des vidéos avec FFmpeg sur Stackoverflow.

1voto

Suivant est un script bash qui affichera les fichiers avec la structure du répertoire sous "fixedFiles". Il transforme et fait pivoter des vidéos iOS et transcode des AVIs. Le script repose sur l'installation à la fois de exiftool et de ffmpeg.

#!/bin/bash

# rotation de 90 degrés. Devra être concaténé.
#ffmpeg -i  -metadata:s:v:0 rotate=0 -vf "transpose=1" 
#/VLC -I dummy -vvv  --sout='#transcode{width=1280,vcodec=mp4v,vb=16384,vfilter={canvas{width=1280,height=1280}:rotate{angle=-90}}}:std{access=file,mux=mp4,dst=}\' vlc://quit

#Permettre les espaces dans les noms de fichiers
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

#Débit binaire
BR=16384

#où stocker les fichiers fixés
REP_FICHIERS_FIXES="fixedFiles"
#rm -rf $REP_FICHIERS_FIXES
mkdir $REP_FICHIERS_FIXES

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

#############################################
# Traitement des MOV dans la mauvaise orientation
for f in `find . -regex '\./.*\.MOV'` 
do
  ROTATION=`exiftool "$f" |grep Rotation|cut -c 35-38`
  DIMENSION_COURTE=`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 Dimension courte [$DIMENSION_COURTE] $BITRATE_INT

  if test "$ROTATION" != ""; then
    DEST=$(dirname ${f})
    echo "Traitement de $f avec rotation $ROTATION dans le répertoire $DEST"
    mkdir -p $REP_FICHIERS_FIXES/"$DEST"

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

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

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

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

    fi

  fi

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

#############################################
# Traitement des fichiers AVI pour ma TV Panasonic
# Utiliser ffmpegX + QuickBatch. Débit binaire à 16384. Rés. caméra 640x424
for f in `find . -regex '\./.*\.AVI'` 
do
  DEST=$(dirname ${f})
  FICHIER_DEST=`echo "$f" | sed 's/.AVI/.MOV/'`
  mkdir -p $REP_FICHIERS_FIXES/"$DEST"
  echo "Traitement de $f dans le répertoire $DEST"
  $(eval ffmpeg -i \"$f\" -r 20 -acodec libvo_aacenc -b:a 128k -vcodec mpeg4 -b:v 8M -flags +aic+mv4 \"$REP_FICHIERS_FIXES/$FICHIER_DEST\" )
echo 
echo ==================================================================

done

IFS=$SAVEIFS

1voto

Thomas Smith Points 21

J'ai été invité à éditer ceci, pour introduire le texte, indiquant que la solution que j'ai finalement trouvée était à la fin du texte. Donc, à la fin, vous trouverez les deux commandes ffmpeg consécutives qui ont correctement pivoté ma vidéo dans la bonne orientation. Le texte précédant cela était censé donner autant d'informations que possible, car j'avais vu d'autres messages rejetés en raison du manque d'informations. De toute façon, j'espère que cela aidera d'autres utilisateurs de ffmpeg. Il me semble que le but de hflip et vflip dans ffmpeg est, au minimum, déroutant, et contraire à ce à quoi je m'attendais.

Le fichier merlin.mov est une copie d'une vidéo que j'ai prise avec mon iPhone, d'abord téléchargée sur Dropbox, puis téléchargée sur mon ordinateur portable, sous Ubuntu:

    $ uname -a
    Linux gazelle 3.13.0-135-generic #184-Ubuntu SMP
    Wed Oct 18 11:55:51 UTC 2017 x86_64 x86_64 x86_64
    GNU/Linux

Je sais que j'aurais dû pouvoir monter mon iPhone via USB et copier les fichiers directement, mais cela n'a pas fonctionné; mon ordinateur portable reconnaissait que l'iPhone était connecté, mais ne montait pas son système de fichiers, et je n'ai eu aucune invite sur mon iPhone pour "faire confiance" à l'ordinateur portable.

La commande que j'ai utilisée pour copier de Dropbox vers mon ordinateur portable était la suivante:

    cp ~/Dropbox/Camera\ Uploads/Video\ Nov\ 02\,\ 9\ 41\ 55\ AM.mov \
            merlin.mov

Le fichier d'origine est une vidéo 1920 x 1080 Codec HEVC/H.265 Fréquence d'images 30/sec, Débit binaire 8140 kbps, Codec audio MPEG-4 AAC audio, Canaux stéréo, Taux d'échantillonnage 44100 Hz, Débit binaire 85 kbps. Lorsque je le lis sur mon iPhone, il est correctement orienté et le son est synchronisé. Lorsque je le lis sur mon ordinateur portable, il est à l'envers et inversé horizontalement, et le son n'est pas synchronisé. Voici une partie de la sortie de "ffmpeg -i merlin.mov":

    Metadata:
    rotate          : 180
    creation_time   : 2017-11-02T14:41:55.000000Z
    handler_name    : Core Media Data Handler
    encoder         : HEVC

Voici la première ligne de la sortie de "ffmpeg -version":

ffmpeg version 3.3.3 Copyright (c) 2000-2017 les développeurs de FFmpeg

Les commandes suivantes laissent la lecture inversée verticalement et horizontalement, bien qu'elles convertissent en vidéo MPEG-4 (video/mp4) et synchronisent le son:

    ffmpeg -i merlin.mov -vf 'hflip,vflip' merlinhflipvflip.mp4

La commande suivante inverse verticalement donc la lecture est droite, synchronise le son et convertit en MPEG-4, mais laisse l'orientation horizontale incorrectement inversée (ce n'est pas une faute de frappe, j'ai spécifié 'hflip'):

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4

La commande suivante a retourné l'horizontale vers la bonne orientation, mais a laissé la lecture à l'envers:

    ffmpeg -i merlin.mov -vf 'vflip' merlinvflip.mp4

La commande suivante semblait n'avoir aucun effet:

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
    ffmpeg -i merlinhflip.mp4 -vf 'vflip' merlin2stepA.mp4

J'ai également essayé ceci, basé sur une commande que j'ai trouvée sur superuser.com. Cela a synchronisé le son avec succès, et converti en MPEG-4, mais l'orientation horizontale et verticale est restée incorrecte:

    ffmpeg -i merlin.mov \
            -vf "rotate=PI:bilinear=0,format=yuv420p" \
            -metadata:s:v rotate=0 -codec:v libx264 \
            -codec:a copy merlinrotate.mp4

J'ai également essayé ceci, qui n'a pas fonctionné non plus en termes de correction de l'orientation:

    ffmpeg -noautorotate -i merlin.mov merlinnoautorotate.mp4

Le processus en 2 étapes suivant a enfin donné ce que je voulais; verticalement et horizontalement retournés, son synchronisé, et format converti en MPEG-4 (Encore une fois, ce n'est pas une faute de frappe; j'ai utilisé hflip dans les deux commandes):

    ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
    ffmpeg -i merlinhflip.mp4 -vf 'hflip' merlin2stepB.mp4

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X