Video rotanti con FFmpeg


417

Ho cercato di capire come ruotare i video con FFmpeg. Sto lavorando con i video di iPhone ripresi in modalità verticale. So come determinare gli attuali gradi di rotazione usando MediaInfo (libreria eccellente, btw) ma ora sono bloccato su FFmpeg.

Da quello che ho letto, quello che devi usare è un'opzione vfilter . Secondo quello che vedo, dovrebbe apparire così:

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

Tuttavia, non riesco a farlo funzionare. Innanzitutto, -vfilters non esiste più, ora è solo -vf . Secondo, ottengo questo errore:

No such filter: 'rotate'
Error opening filters!

Per quanto ne so, ho una build all-options-on di FFmpeg. L'esecuzione di ffmpeg -filters mostra questo:

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.

Avere le opzioni per vflip e hflip è fantastico e tutto, ma non mi porterà dove devo andare. Ho bisogno della possibilità di ruotare i video di almeno 90 gradi. 270 gradi sarebbe anche un'opzione eccellente da avere. Dove sono finite le opzioni di rotazione?


77
Per chiunque cerchi una rotazione di 180 gradi:-vf "vflip,hflip"
OrangeDog,

4
Mi chiedo se questo può essere ottenuto senza decodifica e quindi ricodifica del video - il modo in cui jpegtran può ruotare senza perdita di immagini JPEG ...
Mikhail T.

2
Vedi qui per la bandiera di rotazione: stackoverflow.com/questions/15335073/…
Davor Josipovic

1
Vedi anche la risposta dettagliata in Come capovolgere un video a 180 ° (verticale / capovolto) con FFmpeg? Non dimenticare di ripristinare eventuali metadati di rotazione esistenti (vedi link).
llogan,

1
Ho appena caricato un video ruotato di 180 ° con "transpose = 1, transpose = 1" su vimeo. Anche se posso riprodurre il video ruotato, è stato rifiutato da Vimeo. L'approccio di @ OrangeDog -vf "vflip,hflip"funziona come un fascino.
Besi,

Risposte:


683

Ruota di 90 in senso orario:

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

Per il parametro transpose è possibile passare:

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

Utilizzare -vf "transpose=2,transpose=2"per 180 gradi.

Assicurati di utilizzare una versione recente di ffmpeg da qui (una build statica funzionerà correttamente ).

Si noti che ciò ricodificherà le parti audio e video. Di solito è possibile copiare l'audio senza toccarlo, utilizzando -c:a copy. Per modificare la qualità del video, imposta la velocità in bit (ad esempio con -b:v 1M) o dai un'occhiata alla guida alla codifica H.264 se desideri opzioni VBR.

Una soluzione è anche quella di utilizzare questo comodo script .


8
Il video conterrà comunque le informazioni sull'orientamento, quindi ora il video non verrà corretto su iPhone.
srcspider

26
Quando uso questo comando, ottengo un uscita bassa qualità video , a meno che - come ho appena scoperto - io uso questo parametro così: -vcodec libx264. Ma sarebbe fantastico se non avessi bisogno di cercare quale codifica usare come ffmpeg dovrebbe già conoscerla. Eventuali suggerimenti?
Sadi,

8
Sulla stessa linea di Sadi, c'è un modo per "copiare" la qualità del video originale?
Alec Jacobson,

58
Per 180 è possibile utilizzare-vf "transpose=2,transpose=2"
Alex Pliutau il

23
I documenti attuali osservano che "I valori numerici sono deprecati e dovrebbero essere eliminati a favore delle costanti simboliche". ffmpeg.org/ffmpeg-filters.html#transpose Così cclock_flip, clock, cclocko clock_flipal posto di 0, 1, 2o 3.
l

149

Se non vuoi ricodificare il tuo video E il tuo lettore è in grado di gestire i metadati di rotazione, puoi semplicemente cambiare la rotazione nei metadati usando ffmpeg:

ffmpeg -i input.m4v -metadata:s:v rotate="90" -codec copy output.m4v

11
che ne dite di controllare prima i metadati ruotati conffmpeg -i input.m4v 2>&1 | grep rotate
lidaobing

60
Questa è di gran lunga la risposta migliore. Ma c'è un piccolo miglioramento da fare. Per evitare di perdere i metadati rimanenti (come data, fotocamera) sul video, fai ffmpeg -i input.m4v -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.m4v. In questo modo tutti i metadati globali sul file di input verranno copiati come metadati globali nel file di output e verranno modificati solo i metadati di rotazione.
migle,

11
Se hai un video in modalità ritratto e vuoi solo "ruotarlo UN" per avere uno standard 1920x1080, allora probabilmente lo desideri rotate=0.
mivk

1
Ho provato -metadata:s:v rotate="180", non ha funzionato. Dovrebbe funzionare?
Ondra Žižka,

7
La migliore soluzione IMHO perché non è necessaria la ricodifica e la maggior parte dei lettori video supporta la rotazione dei metadati. Anche servizi cloud come Google Foto. Tuttavia, ricorda che ffmpeg non copia necessariamente tutti i metadati dal file originale! Pertanto, consiglierei di specificare esplicitamente di copiare tutti gli altri metadati dal file originale:ffmpeg -i input.mp4 -codec copy -map_metadata 0 -metadata:s:v:0 rotate=0 output.mp4
Andreas

83

Hai già provato transpose? Mi piace (dall'altra risposta)

 ffmpeg -i input -vf transpose=2 output

Se si utilizza una versione precedente, è necessario aggiornare ffmpeg se si desidera utilizzare la funzione di trasposizione, poiché è stata aggiunta nell'ottobre 2011.

La pagina di download di FFmpeg offre build statiche che puoi eseguire direttamente senza doverle compilare.


1
No, non ho. Non sapevo che esistesse. Ci proverò.
giocate il

Il filtro di trasposizione non sembra esistere in nessuno dei miei build FFmpeg. Come dovrei aggiungerlo?
giovedì

Nella versione dei documenti del 15/05/2011 il
Peter Hansen,

6
Mi sento punito per aver offerto una risposta utile 1,5 anni prima della risposta accettata.
rwilliams,

1
@JonasB Separare i filtri con virgole. Vedere stackoverflow.com/questions/6195872/...
rwilliams

19

Mi sono imbattuto in questa pagina mentre cercavo la stessa risposta. Sono passati ormai sei mesi da quando è stato richiesto inizialmente e le build sono state aggiornate molte volte da allora. Tuttavia, volevo aggiungere una risposta a chiunque si imbattesse qui alla ricerca di queste informazioni.

Sto usando la versione di Debian Squeeze e FFmpeg da quei repository.

La pagina MAN per ffmpeg indica il seguente uso

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

La chiave è che non devi usare una variabile di grado, ma una variabile di impostazione predefinita dalla pagina MAN.

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

Grazie per le informazioni! Non sono mai stato in grado di farlo funzionare davvero, dato che generalmente ho difficoltà a costruire dalla fonte. Potrei vedere se riesco a farlo funzionare di nuovo ora.
jocull,

transpose = 3 sta causando il mirroring dell'immagine
Daniel Kobe,

transpose = 2 ha funzionato senza mirroring per il mio video ruotato di 270
Daniel Kobe

17

Per ruotare l'immagine in senso orario è possibile utilizzare il filtro di rotazione, che indica un angolo positivo in radianti. Con 90 gradi equivalenti a PI / 2, puoi farlo in questo modo:

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

per il senso antiorario l'angolo deve essere negativo

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

Il filtro di trasposizione funzionerà ugualmente bene per 90 gradi, ma per altri angoli questa è una scelta più veloce o unica.


2
è fantastico Ho scoperto che è possibile ottenere una risoluzione più fine dei radianti, perché *si comporta come una moltiplicazione: ffmpeg -i in.avi -vf "rotate=-8*PI/40" -q 1 out.avi (rotazione leggermente inferiore rispetto a -PI / 4 = -10 * PI / 40)
eqzx

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

non funzionerà, anche con l'ultima fonte ...

deve cambiare l'ordine:

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

funziona bene


cioè perché stai applicando il filtro al file sbagliato ... prova ffmpeg -i input.mp4 -vf "rotate = 90" output.mp4, quindi funzionerà
patrick

2
"Ruota il video di un angolo arbitrario espresso in radianti ." Documentazione: ffmpeg.org/ffmpeg-filters.html#rotate Quindi, radianti rotate=PI/2o rotate=90*PI/180è necessario
l --marc l

Questo è fantastico
Tessaracter,

7

Se ricevi un errore "Il codec è sperimentale ma i codec sperimentali non sono abilitati" usa questo:

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

È successo con me per alcuni file .mov con audio aac.


Questo è stato l'unico esempio che ha funzionato per me, ma la qualità era terribile e molto bloccata. Inoltre, ha ridimensionato un video 1080x1920 a 352x640. Immagino che mi manchi un interruttore o due. Eventuali suggerimenti?
LOlliffe,

1
@LOlliffe add-sameq
Andrew Schleifer

2
@AndrewSchleifer Grazie. Ci ho provato, ma ffmpeg mi ha lanciato di nuovo, 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 anche qscale dà un errore. Please use -q:a or -q:v, -qscale is ambiguous, ma funziona ancora.
LOlliffe,

3

Questo script che genererà i file con la struttura di directory in "fixedFiles". Al momento è fisso su file MOV ed eseguirà una serie di trasformazioni a seconda della "rotazione" originale del video. Funziona con i video acquisiti iOS su un Mac con Mavericks, ma dovrebbe essere facilmente esportabile. Si affida ad aver installato sia exiftool che 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

2
Ahi ... Questo può funzionare, ma è perfettamente orribile. Prima di tutto, la regola generale della programmazione della shell: non hai mai bisogno di più di una di grep, cut, awk o sed in una pipe. Qualsiasi grep | cut | sed è realizzabile con sed o awk da solo. Quindi, più specificamente, exiftool può essere invitato a produrre solo i tag desiderati, quindi invece di filtrare la rotazione, basta "exiftool -Rotation". Terzo, non hai bisogno di così tanti "eval" e il tuo "if test ..." dovrebbe essere sostituito con il caso $ ROTATION in - sia per leggibilità che per efficienza. In bocca al lupo!
Mikhail T.

Nessun dado: [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 risposta di Alexy ha funzionato quasi per me, tranne che stavo ottenendo questo errore:

base dei tempi 1/90000 non supportata dallo standard MPEG 4, il valore massimo ammesso per il denominatore della base dei tempi è 65535

Ho dovuto solo aggiungere un parametro (-r 65535/2733) al comando e ha funzionato. Il comando completo era quindi:

ffmpeg -i in.mp4 -vf "transpose=1" -r 65535/2733 out.mp4

Se stai cercando un framerate "NTSC-film", allora 24000/1001sarebbe più preciso.
Reino

2

Un'ulteriore soluzione con un approccio diverso rispetto alle ultime soluzioni menzionate è quella di verificare se il driver della fotocamera supporta i controlli della fotocamera v4l2 (che è molto comune).
Nel terminale basta digitare:

v4l2-ctl -L

Se il driver della fotocamera supporta i controlli della fotocamera v4l2, dovresti ottenere qualcosa del genere (l'elenco che segue dipende dai controlli supportati dal driver della fotocamera):

               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

E se sei fortunato, supporta horizontal_flip e vertical_flip .
Quindi tutto ciò che devi fare è impostare il parametro orizzontale :

v4l2-ctl --set-ctrl horizontal_flip=1

oppure vertical_flip di:

v4l2-ctl --set-ctrl vertical_flip=1

quindi puoi chiamare il tuo dispositivo video per acquisire un nuovo video (vedi esempio sotto) e il video verrà ruotato / capovolto.

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

Naturalmente, se è necessario elaborare un video già esistente, questo metodo non è la soluzione che stai cercando.

Il vantaggio di questo approccio è che capovolgiamo l'immagine a livello del sensore, quindi il sensore del driver ci fornisce già l'immagine capovolta e ciò salva l'applicazione (come FFmpeg) ogni ulteriore e inutile elaborazione.


Grandi informazioni su v4l2 qui. È ovviamente preferibile ruotare con l'orientamento corretto al momento della registrazione :) Questa domanda di quasi 10 anni (wow!) È stata originariamente posta sui video caricati da dispositivi iOS se questo aiuta a fornire qualsiasi contesto :)
jocull

Sono un po 'nuovo in questa comunità e questa domanda è molto più antica della mia anzianità qui ... Penso davvero che sia una buona (e comune) domanda, quindi credo che questa vecchia domanda continuerà ad aiutare molti utenti di FFmpeg.
JM

1

Sfortunatamente, la versione Ubuntu di ffmpeg supporta i videofiltri.

È necessario utilizzare avidemux o qualche altro editor per ottenere lo stesso effetto.

In modo programmatico, è stato raccomandato mencoder.


1
Intendevi "La versione Ubuntu di ffmpeg non supporta i videofiltri"?
user1438038

2
FYI: "FFmpeg è tornato in Ubuntu 15.04 Vivid Vervet." o può essere compilato per Ubuntu. -> trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
l --marc l

avconv (nel 14.04), e sembra funzionare esattamente allo stesso modo. (Ma per le versioni successive, usa sicuramente FFmpeg.)
SilverWolf - Ripristina Monica

1

Smartphone: ha registrato un video in formato verticale

Vuoi inviarlo a un sito web era 90 ° a sinistra (antiorario, formato orizzontale) hmm.

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

lo fa. Ho di nuovo il formato verticale

debian buster: ffmpeg --version ffmpeg versione 4.1.4-1 ~ deb10u1 Copyright (c) 2000-2019 gli sviluppatori di FFmpeg

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.