Girando vídeos com o FFmpeg

417

Eu tenho tentado descobrir como girar vídeos com FFmpeg. Estou trabalhando com vídeos do iPhone tirados no modo retrato. Eu sei como determinar os graus atuais de rotação usando o MediaInfo (excelente biblioteca, btw), mas estou preso no FFmpeg agora.

Pelo que li, o que você precisa usar é uma opção vfilter . De acordo com o que vejo, deve ficar assim:

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

No entanto, não consigo fazer isso funcionar. Primeiro, -vfilters não existe mais, agora é apenas -vf . Segundo, recebo este erro:

No such filter: 'rotate'
Error opening filters!

Até onde eu sei, tenho uma compilação do FFmpeg com todas as opções. A execução de ffmpeg -filters mostra isso:

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.

Ter as opções para vflip e hflip são ótimas e tudo, mas elas simplesmente não me levam aonde eu preciso ir. Eu preciso da capacidade de girar vídeos 90 graus, no mínimo. 270 graus seria uma excelente opção para ter também. Para onde foram as opções de rotação?

jocull
fonte
Atualizei minha resposta. Parece que esse filtro foi adicionado no mês passado à fonte.
precisa
76
Para quem procura uma rotação de 180 graus:-vf "vflip,hflip"
OrangeDog
4
Eu estou querendo saber, se isso pode ser alcançado sem decodificação e, em seguida, re-codificar o vídeo - o caminho jpegtran pode imagens sem perdas de rotação JPEG ...
Mikhail T.
2
Veja aqui o sinalizador de rotação: stackoverflow.com/questions/15335073/…
Davor Josipovic
1
Acabei de enviar um vídeo girado em 180 ° com "transpose = 1, transpose = 1" para o vimeo. Embora eu possa reproduzir o vídeo rotacionado, ele foi rejeitado pelo vimeo. A abordagem do @ OrangeDog -vf "vflip,hflip"funciona como um encanto.
Besi

Respostas:

682

Gire 90 no sentido horário:

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

Para o parâmetro transpose, você pode passar:

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

Use -vf "transpose=2,transpose=2"para 180 graus.

Certifique-se de usar uma versão ffmpeg recente daqui (uma compilação estática funcionará bem).

Observe que isso irá recodificar as partes de áudio e vídeo. Geralmente, você pode copiar o áudio sem tocá-lo usando -c:a copy. Para alterar a qualidade do vídeo, defina a taxa de bits (por exemplo, com -b:v 1M) ou consulte o guia de codificação H.264, se desejar opções de VBR.

Uma solução também é usar esse script de conveniência .

Alexy
fonte
8
O vídeo ainda terá as informações de orientação e agora o vídeo será corrigido incorretamente no iphone.
srcspider
25
Quando eu usar este comando, recebo uma saída de vídeo de baixa qualidade , a menos que - como eu acabei de descobrir - I utilizar esse parâmetro, bem como: -vcodec libx264. Mas seria ótimo se eu não precisasse procurar qual codificação usar como ffmpeg já deveria saber. Alguma sugestão?
Sadi
8
Na mesma linha de Sadi, existe uma maneira de "copiar" a qualidade do vídeo original?
Alec Jacobson
58
Para 180 você pode usar-vf "transpose=2,transpose=2"
Alex Pliutau
23
Os documentos atuais observam que "os valores numéricos foram descontinuados e devem ser descartados em favor de constantes simbólicas". ffmpeg.org/ffmpeg-filters.html#transpose Assim cclock_flip, clock, cclockou clock_flipem vez de 0, 1, 2ou 3.
l --marc l
149

Se você não deseja recodificar o vídeo e seu player pode lidar com metadados de rotação, basta alterar a rotação nos metadados usando ffmpeg:

ffmpeg -i input.m4v -metadata:s:v rotate="90" -codec copy output.m4v
Rodrigo Polo
fonte
11
como sobre verificar os metadados rodar pela primeira vez comffmpeg -i input.m4v 2>&1 | grep rotate
lidaobing
60
Esta é a melhor resposta de longe. Mas há uma pequena melhoria a ser feita. Para evitar perder os meta-dados restantes (como data, câmera) no vídeo, faça ffmpeg -i input.m4v -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.m4v. Dessa forma, todos os metadados globais no arquivo de entrada serão copiados como metadados globais para o arquivo de saída e apenas os metadados de rotação serão alterados.
Migle
11
Se você possui um vídeo em modo retrato e deseja apenas "girar UN" para ter um padrão de 1920x1080, provavelmente deseja rotate=0.
mivk
1
Tentei -metadata:s:v rotate="180", não funcionou. Isso deveria funcionar?
Ondra Žižka
7
IMHO melhor solução, porque nenhuma reencodificação é necessária e a maioria dos players de vídeo suporta a rotação de metadados. Também serviços em nuvem, como o Google Fotos. No entanto, lembre-se de que o ffmpeg não copia necessariamente todos os metadados do arquivo original! Portanto, eu recomendaria para especificar explicitamente para copiar todos os outros metadados do arquivo original:ffmpeg -i input.mp4 -codec copy -map_metadata 0 -metadata:s:v:0 rotate=0 output.mp4
Andreas
83

Você já tentou transpose? Curtir (da outra resposta)

 ffmpeg -i input -vf transpose=2 output

Se você estiver usando uma versão antiga, precisará atualizar o ffmpeg se quiser usar o recurso de transposição, como foi adicionado em outubro de 2011.

A página de download do FFmpeg oferece compilações estáticas que você pode executar diretamente sem precisar compilá-las.

rwilliams
fonte
1
Não, eu não tenho. Eu não sabia que existia. Vou tentar.
jocull
O filtro de transposição parece não existir em nenhuma das minhas compilações FFmpeg. Como devo adicioná-lo?
Jocull
Na versão dos documentos de 15/05/2011,
Peter Hansen
6
Parece que fui punido por oferecer uma resposta útil 1,5 anos antes da resposta aceita.
Rwilliams
1
@JonasB Separe os filtros com vírgulas. Veja stackoverflow.com/questions/6195872/…
rwilliams
19

Me deparei com esta página enquanto procurava a mesma resposta. Agora faz seis meses que isso foi solicitado originalmente e as construções foram atualizadas várias vezes desde então. No entanto, eu queria adicionar uma resposta para qualquer pessoa que se deparar aqui procurando essas informações.

Estou usando a versão Debian Squeeze e FFmpeg desses repositórios.

A página MAN para ffmpeg indica o seguinte uso

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

A chave é que você não deve usar uma variável de grau, mas uma variável de configuração predefinida na página MAN.

0=90CounterCLockwise and Vertical Flip  (default) 
1=90Clockwise 
2=90CounterClockwise 
3=90Clockwise and Vertical Flip
Zonjai
fonte
Obrigado pela informação! Eu nunca consegui fazer isso funcionar, pois geralmente tenho problemas para criar a partir da fonte. Posso ver se consigo fazê-lo funcionar novamente agora.
jocull
transpose = 3 está causando o espelhamento da imagem
Daniel Kobe
transpose = 2 funcionou sem espelhar no meu vídeo girado 270
Daniel Kobe
17

Para girar a imagem no sentido horário, você pode usar o filtro de rotação, indicando um ângulo positivo em radianos. Com 90 graus igualando PI / 2, você pode fazer o seguinte:

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

no sentido anti-horário, o ângulo deve ser negativo

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

O filtro de transposição funcionará igualmente bem em 90 graus, mas para outros ângulos, essa é uma opção mais rápida ou única.

Bijou Trouvaille
fonte
2
isso é ótimo. Eu descobri que é possível obter mais refinado resolução de radianos, porque *se comporta como multiplicação: ffmpeg -i in.avi -vf "rotate=-8*PI/40" -q 1 out.avi (um pouco menos do que a rotação -PI / 4 = -10 * PI / 40)
eqzx
12
ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4 

não funcionará, mesmo com a fonte mais recente ...

deve alterar a ordem:

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

funciona bem

nano
fonte
que é becuase você está aplicando o filtro para o arquivo errado ... tente ffmpeg -i input.mp4 -vf "rotate = 90" output.mp4, então ele vai trabalhar
patrick
2
"Gire o vídeo por um ângulo arbitrário expresso em radianos ." Documentation: ffmpeg.org/ffmpeg-filters.html#rotate Então, é necessário radianos rotate=PI/2ou rotate=90*PI/180é
l --marc l
Isso é fantástico
Tessaracter 26/11/19
7

Se você receber um erro "O codec é experimental, mas os codecs experimentais não estão ativados", use este:

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

Aconteceu comigo para algum arquivo .mov com áudio aac.

sabujp
fonte
Este foi o único exemplo que funcionou para mim, mas a qualidade foi terrível e muito irregular. Além disso, reduziu o tamanho de um vídeo de 1080x1920 para 352x640. Acho que estou perdendo um interruptor ou dois. Alguma sugestão?
LOlliffe
1
@LOlliffe add-sameq
Andrew Schleifer
2
@AndrewSchleifer Thanks. Eu tentei isso, mas o ffmpeg jogou de volta para mim 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 -qscale também dá um erro. Please use -q:a or -q:v, -qscale is ambiguous, mas ainda funciona.
LOlliffe
3

Este script que produzirá os arquivos com a estrutura de diretórios em "FixedFiles". No momento, é fixado em arquivos MOV e executará várias transformações, dependendo da "rotação" original do vídeo. Funciona com vídeos capturados no iOS em um Mac executando o Mavericks, mas deve ser facilmente exportável. Depende da instalação do exiftool e do 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
fonte
2
Ai ... Isso pode funcionar, mas é perfeitamente hediondo. Primeiro de tudo, a regra geral da programação de shell: você nunca precisa de mais do que um grep, cut, awk ou sed em um pipe. Qualquer grep | cut | sed é factível apenas com sed ou awk. Então, mais especificamente, pode ser solicitado que o exiftool produza apenas as tags que você deseja - então, em vez de filtrar a rotação, basta "exiftool -Rotation". Terceiro, você não precisa de tantos "avaliações" e seu "teste se ..." deve ser substituído pelo caso $ ROTATION in - para facilitar a leitura e a eficiência. Boa sorte!
Mikhail T.
Nenhum 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

A resposta de Alexy quase funcionou para mim, exceto que eu estava recebendo este erro:

base de tempo 1/90000 não suportada pelo padrão MPEG 4, o valor máximo permitido para o denominador de base de tempo é 65535

Eu apenas tive que adicionar um parâmetro (-r 65535/2733) ao comando e funcionou. O comando completo foi assim:

ffmpeg -i in.mp4 -vf "transpose=1" -r 65535/2733 out.mp4
smoyth
fonte
Se você está procurando uma taxa de quadros "filme NTSC", 24000/1001seria mais preciso.
Reino
2

Uma solução adicional com uma abordagem diferente das últimas soluções mencionadas é verificar se o driver da câmera suporta os controles da câmera v4l2 (o que é muito comum).
No terminal, basta digitar:

v4l2-ctl -L

Se o driver da câmera suportar os controles da câmera v4l2, você deverá obter algo assim (a lista abaixo depende dos controles que o driver da câmera suporta):

               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 você tiver sorte, ele suporta horizontal_flip e vertical_flip .
Então, tudo o que você precisa fazer é definir o horizontal_flip :

v4l2-ctl --set-ctrl horizontal_flip=1

ou o vertical_flip por:

v4l2-ctl --set-ctrl vertical_flip=1

e então você pode ligar para o seu dispositivo de vídeo para capturar um novo vídeo (veja o exemplo abaixo) e o vídeo será girado / invertido.

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

Obviamente, se você precisar processar um vídeo já existente, esse método não será a solução que você está procurando.

A vantagem dessa abordagem é que invertemos a imagem no nível do sensor, para que o sensor do driver já nos dê a imagem invertida e isso economiza para o aplicativo (como o FFmpeg) qualquer processamento adicional e desnecessário.

JM
fonte
Ótimas informações sobre a v4l2 aqui. É obviamente preferível girar para a orientação correta no momento da gravação :) Essa pergunta de quase 10 anos (uau!) Foi originalmente feita sobre vídeos sendo enviados de dispositivos iOS, se isso ajuda a fornecer qualquer contexto :)
jocull
Sou um pouco novo nesta comunidade e essa pergunta é muito mais antiga que minha antiguidade aqui ... Eu realmente acho que é uma pergunta boa (e comum), então acredito que essa pergunta antiga continuará ajudando muitos usuários do FFmpeg.
JM
1

Infelizmente, a versão Ubuntu do ffmpeg suporta filtros de vídeo.

Você precisa usar o avidemux ou algum outro editor para obter o mesmo efeito.

De maneira programática, o mencoder foi recomendado.

ldig
fonte
1
Você quis dizer "A versão Ubuntu do ffmpeg não suporta filtros de vídeo"?
user1438038
2
FYI: "O FFmpeg retornou no Ubuntu 15.04 Vivid Vervet." ou pode ser compilado para o Ubuntu. -> trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
l --marc l
O avconv funciona (em 14.04) e parece funcionar exatamente da mesma maneira. (Mas, para versões posteriores, definitivamente use o FFmpeg.)
SilverWolf - Restabelecer Monica
1

Smartphone: gravou um vídeo no formato vertical

Deseja enviá-lo para um lado da Web, a 90 ° à esquerda (anti-horário, formato paisagem) hmm.

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

faz isso. Voltei ao formato vertical

debian buster: ffmpeg --version ffmpeg versão 4.1.4-1 ~ deb10u1 Copyright (c) 2000-2019 the FFmpeg developers

fb
fonte