Obracanie filmów za pomocą FFmpeg

417

Próbowałem wymyślić, jak obracać filmy za pomocą FFmpeg. Pracuję z filmami iPhone wykonanymi w trybie portretowym. Wiem, jak określić bieżące stopnie obrotu za pomocą MediaInfo (doskonała biblioteka, btw), ale teraz utknąłem na FFmpeg.

Z tego, co przeczytałem, musisz użyć opcji vfilter . Zgodnie z tym, co widzę, powinno to wyglądać tak:

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

Nie mogę tego jednak uruchomić. Po pierwsze, -vfilters już nie istnieje, teraz jest po prostu -vf . Po drugie, pojawia się ten błąd:

No such filter: 'rotate'
Error opening filters!

O ile mi wiadomo, mam FFmpeg na wszystkie opcje. Uruchomienie ffmpeg -filters pokazuje:

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.

Opcje vflip i hflip są świetne, ale po prostu nie doprowadzą mnie tam, gdzie potrzebuję. Potrzebuję możliwości obracania filmów co najmniej o 90 stopni. 270 stopni byłoby również doskonałą opcją. Gdzie się podziały opcje obracania?

żartobliwy
źródło
Zaktualizowałem moją odpowiedź. Wygląda na to, że ten filtr został właśnie dodany do źródła w zeszłym miesiącu.
rwilliams
76
Dla każdego, kto szuka obrotu o 180 stopni:-vf "vflip,hflip"
OrangeDog
4
Zastanawiam się, czy można to osiągnąć bez dekodowania, a następnie ponownego kodowania wideo - sposób, w jaki jpegtran może bezstratnie obracać obrazy JPEG ...
Mikhail T.
2
Zobacz tutaj flagę rotacji: stackoverflow.com/questions/15335073/…
Davor Josipovic
1
Właśnie przesłałem wideo obrócone o 180 ° z „transpose = 1, transpose = 1” do vimeo. Mimo że mogę odtworzyć obrócone wideo, zostało ono odrzucone przez vimeo. @ Podejście OrangeDog -vf "vflip,hflip"działa jak urok.
Besi

Odpowiedzi:

682

Obróć o 90 w prawo:

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

Dla parametru transpozycji możesz przekazać:

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

Użyj -vf "transpose=2,transpose=2"do 180 stopni.

Upewnij się, że używasz najnowszej wersji ffmpeg stąd (kompilacja statyczna będzie działać poprawnie).

Pamiętaj, że spowoduje to ponowne zakodowanie części audio i wideo. Zwykle możesz skopiować dźwięk bez dotykania go, używając -c:a copy. Aby zmienić jakość wideo, ustaw bitrate (na przykład za pomocą -b:v 1M) lub zajrzyj do przewodnika kodowania H.264, jeśli chcesz opcji VBR.

Rozwiązaniem jest również użycie tego skryptu wygody .

Alexy
źródło
8
Film nadal będzie zawierał informacje o orientacji, więc teraz film zostanie pominięty i poprawiony na iPhonie.
srcspider
25
Kiedy używać tego polecenia, mam wyjście niską jakość obrazu , chyba że - jak właśnie odkrył - używam tego parametru, a także: -vcodec libx264. Ale byłoby wspaniale, gdybym nie musiał sprawdzać, jakiego kodowania użyć, ponieważ ffmpeg powinien go już znać. Jakieś sugestie?
Sadi
8
Czy w taki sam sposób jak Sadi istnieje sposób na „skopiowanie” jakości oryginalnego wideo?
Alec Jacobson
58
Za 180 możesz użyć-vf "transpose=2,transpose=2"
Alex Pliutau,
23
Obecni doktorzy zauważają, że „Wartości liczbowe są przestarzałe i należy je porzucić na rzecz stałych symbolicznych”. ffmpeg.org/ffmpeg-filters.html#transpose Zatem cclock_flip, clock, cclocklub clock_flipzamiast 0, 1, 2i 3.
l --marc l
149

Jeśli nie chcesz ponownie kodować wideo ORAZ odtwarzacz obsługuje metadane rotacji, możesz po prostu zmienić rotację metadanych za pomocą ffmpeg:

ffmpeg -i input.m4v -metadata:s:v rotate="90" -codec copy output.m4v
Rodrigo Polo
źródło
11
co powiesz na sprawdzenie najpierw rotacyjnych metadanych za pomocąffmpeg -i input.m4v 2>&1 | grep rotate
lidaobing
60
Jak dotąd najlepsza odpowiedź. Ale jest niewielka poprawa do zrobienia. Aby uniknąć utraty pozostałych metadanych (takich jak data, kamera) na wideo, wykonaj ffmpeg -i input.m4v -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.m4v. W ten sposób wszystkie globalne metadane z pliku wejściowego zostaną skopiowane jako globalne metadane do pliku wyjściowego i zmieniane będą tylko metadane rotacyjne.
migle
11
Jeśli masz wideo w trybie portretowym i po prostu chcesz je „obrócić w UN”, aby mieć standardową rozdzielczość 1920 x 1080, prawdopodobnie chcesz rotate=0.
mivk
1
Próbowałem -metadata:s:v rotate="180", nie działało. Czy to powinno działać?
Ondra Žižka
7
Najlepsze rozwiązanie IMHO, ponieważ nie jest konieczne ponowne kodowanie, a większość odtwarzaczy wideo obsługuje rotację metadanych. Również usługi w chmurze, takie jak Zdjęcia Google. Pamiętaj jednak, że ffmpeg niekoniecznie kopiuje wszystkie metadane z oryginalnego pliku! Dlatego zaleciłbym jawne określenie kopiowania wszystkich innych metadanych z oryginalnego pliku:ffmpeg -i input.mp4 -codec copy -map_metadata 0 -metadata:s:v:0 rotate=0 output.mp4
Andreas
83

Próbowałeś już transpose? Jak (z drugiej odpowiedzi)

 ffmpeg -i input -vf transpose=2 output

Jeśli używasz starej wersji, musisz zaktualizować ffmpeg, jeśli chcesz skorzystać z funkcji transpozycji, ponieważ została dodana w październiku 2011 r.

Strona pobierania FFmpeg oferuje kompilacje statyczne, które można wykonać bezpośrednio bez konieczności ich kompilacji.

rwilliams
źródło
1
Nie, nie mam. Nie wiedziałem, że istnieje. Dam temu szansę.
żartuje
Wygląda na to, że filtr transpozycji nie istnieje w żadnej z moich kompilacji FFmpeg. Jak mam to dodać?
żartuje
W wersji dokumentów z 15.05.2011 r.
Peter Hansen
6
Mam wrażenie, że zostałem ukarany za zaoferowanie użytecznej odpowiedzi 1,5 roku przed zaakceptowaną odpowiedzią.
rwilliams
1
@JonasB Rozdziel filtry przecinkami. Zobacz stackoverflow.com/questions/6195872/…
rwilliams
19

Natknąłem się na tę stronę, szukając tej samej odpowiedzi. Minęło sześć miesięcy, odkąd pierwotnie o to pytano, a od tego czasu kompilacje były wielokrotnie aktualizowane. Chciałem jednak dodać odpowiedź dla wszystkich osób, które tu przychodzą i szukają tych informacji.

Używam wersji Debian Squeeze i FFmpeg z tych repozytoriów.

Strona MAN ffmpeg zawiera następujące zastosowanie

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

Kluczowe jest to, że nie należy używać zmiennej stopnia, ale predefiniowaną zmienną ustawienia ze strony MAN.

0=90CounterCLockwise and Vertical Flip  (default) 
1=90Clockwise 
2=90CounterClockwise 
3=90Clockwise and Vertical Flip
Zonjai
źródło
Dzięki za informację! Nigdy nie byłem w stanie uruchomić tego, ponieważ generalnie mam problemy z budowaniem ze źródła. Mogę zobaczyć, czy uda mi się znów uruchomić.
żartuje
transpozycja = 3 powoduje odbicie obrazu
Daniel Kobe
transpose = 2 działało bez kopii lustrzanej dla mojego 270 obróconego wideo
Daniel Kobe
17

Aby obrócić obraz zgodnie z ruchem wskazówek zegara, możesz użyć filtra obrotu wskazującego dodatni kąt w radianach. Dzięki 90 stopniom równym PI / 2 możesz to zrobić w następujący sposób:

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

dla przeciwnie do ruchu wskazówek zegara kąt musi być ujemny

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

Filtr transpozycji będzie działał równie dobrze dla 90 stopni, ale dla innych kątów jest to szybszy lub jedyny wybór.

Bijou Trouvaille
źródło
2
to jest świetne. Odkryłem, że możliwe jest uzyskanie dokładniejszej rozdzielczości radianów, ponieważ *zachowuje się jak mnożenie: ffmpeg -i in.avi -vf "rotate=-8*PI/40" -q 1 out.avi (nieco mniejszy obrót niż -PI / 4 = -10 * PI / 40)
eqzx
12
ffmpeg -vfilters "rotate=90" -i input.mp4 output.mp4 

nie będzie działać, nawet z najnowszym źródłem ...

musi zmienić kolejność:

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

działa w porządku

nano
źródło
czyli becuase starasz filtr do niewłaściwego pliku ... spróbuj ffmpeg -i input.mp4 -vf „rotate = 90” output.mp4 Pokochasz to działa
Patrick
2
„Obróć wideo o dowolny kąt wyrażony w radianach ”. Dokumentacja: ffmpeg.org/ffmpeg-filters.html#rotate Tak więc, radiany rotate=PI/2lub rotate=90*PI/180jest potrzebne
l --marc l
To fantastyczne
Tessaracter
7

Jeśli pojawia się komunikat „Kodek jest eksperymentalny, ale eksperymentalne kodeki nie są włączone”, użyj tego błędu:

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

Stało się ze mną dla jakiegoś pliku .mov z dźwiękiem AAC.

sabujp
źródło
To był jedyny przykład, który działał dla mnie, ale jakość była okropna i bardzo blokująca. Ponadto zmniejszył rozmiar wideo 1080x1920 do 352x640. Chyba brakuje mi jednego lub dwóch przełączników. Jakieś sugestie?
LOlliffe,
1
@LOlliffe dodaj-sameq
Andrew Schleifer
2
@AndrewSchleifer Thanks. Próbowałem tego, ale ffmpeg zwrócił się do mnie - 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 również daje błąd. Please use -q:a or -q:v, -qscale is ambiguous, ale nadal działa.
LOlliffe,
3

Ten skrypt, który wyświetli pliki o strukturze katalogów w „fixedFiles”. W tej chwili jest ustalony na pliki MOV i wykona szereg transformacji w zależności od pierwotnego „obrotu” wideo. Działa z przechwyconymi filmami z iOS na Macu z systemem Mavericks, ale powinien być łatwo eksportowany. Polega na zainstalowaniu zarówno exiftool, jak i 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
źródło
2
Ojej ... To może zadziałać, ale jest całkowicie ohydne. Przede wszystkim ogólna zasada programowania powłoki: nigdy nie potrzebujesz więcej niż grep, cut, awk lub sed w rurze. Każdy grep | cut | sed jest możliwy do wykonania za pomocą samego sed lub awk. Następnie, bardziej konkretnie, exiftool może zostać poproszony o wydrukowanie tylko żądanego znacznika (tagów) - więc zamiast odfiltrowywać Rotation, po prostu „exiftool -Rotation”. Po trzecie, nie potrzebujesz tak wielu „ewaluacji”, a twój „jeśli test ...” powinien zostać zastąpiony skrzynką $ ROTATION in - zarówno dla czytelności jak i wydajności. Powodzenia!
Mikhail T.
Bez kości: [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

Odpowiedź Alexy prawie dla mnie zadziałała, z wyjątkiem tego, że otrzymywałem ten błąd:

podstawa czasu 1/90000 nieobsługiwana przez standard MPEG 4, maksymalna dopuszczalna wartość dla mianownika podstawy czasu wynosi 65535

Po prostu musiałem dodać parametr (-r 65535/2733) do polecenia i zadziałało. Pełne polecenie brzmiało zatem:

ffmpeg -i in.mp4 -vf "transpose=1" -r 65535/2733 out.mp4
smoyth
źródło
Jeśli szukasz klatek „NTSC-film”, 24000/1001byłoby bardziej dokładne.
Reino
2

Dodatkowym rozwiązaniem z innym podejściem niż ostatnie wspomniane rozwiązania jest sprawdzenie, czy sterownik aparatu obsługuje sterowanie kamerą v4l2 (co jest bardzo częste).
W terminalu wpisz:

v4l2-ctl -L

Jeśli sterownik aparatu obsługuje sterowanie kamerą v4l2, powinieneś otrzymać coś takiego (poniższa lista zależy od sterowania obsługiwanego przez sterownik aparatu):

               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

A jeśli masz szczęście, obsługuje poziomo i pionowo .
Następnie wszystko, co musisz zrobić, to ustawić horizontal_flip przez:

v4l2-ctl --set-ctrl horizontal_flip=1

lub vertical_flip przez:

v4l2-ctl --set-ctrl vertical_flip=1

a następnie możesz zadzwonić do urządzenia wideo, aby przechwycić nowe wideo (patrz przykład poniżej), a wideo zostanie obrócone / odwrócone.

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

Oczywiście, jeśli potrzebujesz przetworzyć już istniejące wideo, ta metoda nie jest rozwiązaniem, którego szukasz.

Zaletą tego podejścia jest to, że odwracamy obraz na poziomie czujnika, więc czujnik sterownika już daje nam odwrócony obraz, co oszczędza aplikacji (jak FFmpeg) dalsze i niepotrzebne przetwarzanie.

JM
źródło
Świetne informacje o v4l2 tutaj. Obracanie do właściwej orientacji w czasie nagrywania jest oczywiście lepsze :) To prawie 10-letnie pytanie (wow!) Zostało pierwotnie zadane na temat przesyłania filmów z urządzeń z systemem iOS, jeśli to pomaga zapewnić jakiś kontekst :)
jocull
Jestem trochę nowa w tej społeczności i to pytanie jest znacznie starsze niż moje starszeństwo tutaj ... Naprawdę uważam, że jest to dobre (i wspólne) pytanie, więc wierzę, że to stare pytanie będzie nadal pomagać wielu użytkownikom FFmpeg.
JM
1

Niestety, wersja ffmpeg Ubuntu obsługuje filmy wideo.

Aby uzyskać ten sam efekt, musisz użyć avidemux lub innego edytora.

W sposób programowy zalecany jest mencoder.

ldig
źródło
1
Czy miałeś na myśli „Ubuntu wersja ffmpeg nie obsługuje filtrów wideo”?
user1438038,
2
FYI: „FFmpeg powrócił w Ubuntu 15.04 Vivid Vervet.” lub może być skompilowany dla Ubuntu. -> trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
l --marc l
avconv działa (w 14.04) i wydaje się działać dokładnie tak samo. (Ale w przypadku późniejszych wersji zdecydowanie użyj FFmpeg.)
SilverWolf - Przywróć Monikę
1

Smartfon: Zapisano film w formacie pionowym

Chcesz wysłać go na stronę internetową, to było 90 ° w lewo (przeciwnie do ruchu wskazówek zegara, format poziomy) hmm.

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

czy to. Znowu dostałem format pionowy

debian buster: ffmpeg - wersja ffmpeg wersja 4.1.4-1 ~ deb10u1 Copyright (c) 2000-2019 deweloperzy FFmpeg

pełne wyżywienie
źródło