Mam film, który został obrócony o 180 ° podczas nagrywania. Czy można to naprawić za pomocą FFmpeg?
Mam film, który został obrócony o 180 ° podczas nagrywania. Czy można to naprawić za pomocą FFmpeg?
Odpowiedzi:
ffmpeg
automatycznie obróci wideo, chyba że:
ffmpeg
jest za staryNiektóre filmy, na przykład z iPhone'ów, nie są fizycznie odwracane, ale zawierają dane poboczne strumienia danych wideo lub obracają metadane. Niektórzy gracze ignorują te metadane, a inni nie. Sprawdź ffmpeg
dane wyjściowe konsoli, aby sprawdzić, czy dane wejściowe zawierają takie metadane:
$ 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
ffmpeg
automatycznie fizycznie obróci wideo zgodnie z istniejącymi metadanymi obrotu strumienia wideo.
Aby móc korzystać z funkcji autorotacji, potrzebujesz kompilacji zawierającej zatwierdzenie 1630224 od 2 maja 2015 r.
ffmpeg -i input.mp4 -c:a copy output.mp4
Aby wyłączyć to zachowanie, użyj -noautorotate
opcji.
ffmpeg
są stareBędziesz musiał użyć filtra, aby obrócić wideo, a jeśli istnieją jakiekolwiek obracające metadane, trzeba je usunąć, jak pokazano w poniższych przykładach:
Używając ffmpeg
masz do wyboru trzy metody używania filtrów wideo do obracania o 180 °.
hflip
i 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
Ten filtr może obracać się pod dowolnym dowolnym kątem i używa radianów jako jednostki zamiast stopni. Ten przykład obróci radian π / 1 lub o 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
Zamiast tego możesz użyć stopni. Jeden stopień jest równy π / 180 radianom. Więc jeśli chcesz obrócić o 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
Podczas korzystania z rotate
filtra interpolacja dwuliniowa powinna być wyłączona (przy użyciu bilinear=0
) dla kątów podzielnych przez 90, w przeciwnym razie może wyglądać na rozmazany.
Filtrowanie wymaga kodowania. Te przykłady tworzą wyjścia wideo H.264. Zobacz Przewodnik po kodowaniu wideo FFmpeg H.264, aby uzyskać wskazówki, jak uzyskać żądaną jakość.
Podpróbkowanie barwy. Włączyłem, format=yuv420p
ponieważ ffmpeg
spróbuję zminimalizować lub uniknąć podpróbkowania barwy (w zależności od kodera, wejścia, ffmpeg
wersji itp.). Jest to dobre zachowanie w czysto technicznym sensie, ale większość graczy jest niezgodna z bardziej „zaawansowanymi” schematami podpróbkowania barwy. Jest to to samo, co używanie -pix_fmt yuv420
, ale jest dogodnie zlokalizowany w łańcuchu filtrów .
Skopiuj audio. -codec:a copy
Opcja stream copy (re-MUX) zamiast kodowania. Nie ma powodu, aby ponownie kodować dźwięk, jeśli chcesz manipulować tylko wideo (chyba że chcesz przekonwertować na inny format audio). Pozwoli to zaoszczędzić czas, ponieważ kodowanie jest czasochłonne i pozwoli zachować jakość dźwięku.
Alternatywnie możesz obracać podczas odtwarzania i unikać ponownego kodowania. ffplay
automatycznie obróci się:
ffplay input.mp4
Jeśli nie ma żadnych danych pobocznych ani rotacji metadanych, możesz użyć filtrów:
ffplay -vf "hflip,vflip" -i input.mp4
... lub skorzystaj ze swojego ulubionego odtwarzacza. Większość graczy, których warto używać, takich jak VLC, ma taką możliwość.
ffmpeg
Starsze wersje ffmpeg nie zawierają możliwości filtrowania. Zobacz stronę pobierania FFmpeg , aby zapoznać się z kilkoma opcjami, w tym wygodnymi kompilacjami dla systemów Linux, OS X i Windows, lub zapoznaj się z Wiki FFmpeg, aby uzyskać szczegółowe instrukcje kompilacji ffmpeg .
-vf vflip
i zadziałało to jak urok. Ale to było ponowne kodowanie. Nie jestem pewien, czy dobrze cię czytam. Czy mówisz, że -vf hflip,vflip
nie będzie ponownie kodować?
ffmpeg
wymaga ponownego kodowania podczas korzystania z filtrów wideo i audio. Jednak ffplay
może również korzystać z wielu filtrów podczas odtwarzania, jak pokazano w moim drugim przykładzie.
-codec:v libx264
? Czy można ffmpeg
po prostu użyć tego samego kodowania bez konieczności próbowania tego przez użytkownika?
FFMPEG zmieniło domyślne zachowanie na automatyczne obracanie wejściowych źródeł wideo za pomocą metadanych „rotate” w wersji v2.7 w 2015 roku .
Jeśli wiesz, że twój skrypt lub polecenie nigdy nie będzie działać w wersjach ffmpeg starszych niż 2.7, najprostszym rozwiązaniem jest usunięcie dowolnej rotacji niestandardowej na podstawie metadanych.
W innych przypadkach możesz zabezpieczyć się na przyszłość, zachowując swój niestandardowy kod obrotu i dodając -noautorotate
flagę (jest to obsługiwane w starszych wersjach, które nadal były w tym czasie obsługiwane).
Odtwarzacze multimedialne, które używają ffmpeg jako zaplecza dekodującego, mogą również wykorzystywać wszystkie jego filtry. Zobacz ten zrzut ekranu z filtrem „Przesunięcie i odwrócenie”.
Alternatywnie, jeśli chcesz ponownie zakodować wideo, sprawdź Obracanie filmów za pomocą FFmpeg na Stackoverflow.
transpose
filtr wymieniony w Obracanie filmów z FFmpeg nie obróci się o 180 °, o ile wiem.
transpose
połączyć dwa filtry razem, aby osiągnąć efekt.
Poniżej znajduje się skrypt bash, który wyświetli pliki ze strukturą katalogów pod „fixedFiles”. Przekształca i obraca filmy na iOS oraz transkoduje AVI. Skrypt 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
Zostałem poproszony o edycję tego, przedmowę tekstu, wskazując, że rozwiązanie, które ostatecznie znalazłem, znajdowało się na końcu tekstu. Na koniec znajdziesz dwa kolejne polecenia ffmpeg, które pomyślnie obróciły moje wideo do właściwej orientacji. Tekst poprzedzający miał dać jak najwięcej informacji, jak mogłem, ponieważ widziałem inne wiadomości, które zostały odrzucone z powodu braku informacji. W każdym razie mam nadzieję, że pomoże to innym użytkownikom ffmpeg. Wydaje mi się, że hflip i vflip w ffmpeg są co najmniej mylące i sprzeczne z oczekiwaniami.
Plik merlin.mov jest kopią wideo, które nagrałem na iPhonie, najpierw przesłałem do Dropbox, a następnie pobrałem na laptopa z systemem 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
Wiem, że powinienem móc podłączyć iPhone'a przez USB i bezpośrednio skopiować pliki, ale to nie działało; mój laptop rozpoznałby, że iPhone jest podłączony, ale nie zamontowałby systemu plików, a na moim iPhonie nie pojawił się monit o „zaufanie” laptopowi.
Polecenie, którego użyłem do skopiowania z Dropbox na mój laptop to:
cp ~/Dropbox/Camera\ Uploads/Video\ Nov\ 02\,\ 9\ 41\ 55\ AM.mov \
merlin.mov
Oryginalny plik to wideo 1920 x 1080 Codec HEVC / H.265 Framerate 30 / sec, Bitrate 8140 kbps, Audio Codec MPEG-4 AAC Audio Channels Stereo, Częstotliwość próbkowania 44100 Hz, Bitrate 85 kbps. Kiedy gram na iPhonie, jest odpowiednio zorientowany, a dźwięk jest zsynchronizowany. Kiedy odtwarzam go w filmach na moim laptopie, jest on odwrócony do góry nogami i odwrócony w poziomie, a dźwięk nie jest zsynchronizowany. Oto częściowe dane wyjściowe z „ffmpeg -i merlin.mov”:
Metadata:
rotate : 180
creation_time : 2017-11-02T14:41:55.000000Z
handler_name : Core Media Data Handler
encoder : HEVC
Oto pierwszy wiersz wyniku z „ffmpeg -version”:
ffmpeg wersja 3.3.3 Copyright (c) 2000-2017 deweloperzy FFmpeg
Następujące polecenie pozostawiło odtwarzanie odwrócone zarówno w pionie, jak iw poziomie, chociaż zostało ono przekonwertowane na wideo MPEG-4 (wideo / mp4) i zsynchronizowało dźwięk:
ffmpeg -i merlin.mov -vf 'hflip,vflip' merlinhflipvflip.mp4
Następujące elementy są odwrócone w pionie, aby odtwarzanie odbywało się w pozycji pionowej, zsynchronizowało dźwięk i zostało przekonwertowane do formatu MPEG-4, ale pozostawiło niepoprawnie odwrócony koniec dla końca (nie jest to literówka, określiłem „hflip”):
ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
Poniższe odwróciło poziomą pozycję do prawidłowej orientacji, ale pozostawiło odtwarzanie do góry nogami:
ffmpeg -i merlin.mov -vf 'vflip' merlinvflip.mp4
Wydaje się, że następujące działania nie mają żadnego wpływu:
ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
ffmpeg -i merlinhflip.mp4 -vf 'vflip' merlin2stepA.mp4
Próbowałem również tego, na podstawie polecenia znalezionego w superuser.com. Pomyślnie zsynchronizował dźwięk i przekonwertował go na MPEG-4, ale orientacja pozioma i pionowa pozostała niepoprawna:
ffmpeg -i merlin.mov \
-vf "rotate=PI:bilinear=0,format=yuv420p" \
-metadata:s:v rotate=0 -codec:v libx264 \
-codec:a copy merlinrotate.mp4
Próbowałem też tego, co również nie działało w zakresie korekty orientacji:
ffmpeg -noautorotate -i merlin.mov merlinnoautorotate.mp4
Następujący 2-etapowy proces w końcu uzyskał to, czego chciałem; pionowy i poziomy zarówno odwrócony, zsynchronizowany z dźwiękiem, jak i format przekonwertowany na MPEG-4 (Ponownie, to nie jest literówka; w obu poleceniach użyłem hflip):
ffmpeg -i merlin.mov -vf 'hflip' merlinhflip.mp4
ffmpeg -i merlinhflip.mp4 -vf 'hflip' merlin2stepB.mp4
Oto kroki:
Najpierw otwórz plik wideo w QuickTime. Możesz najpierw uruchomić QuickTime, przejść do „Plik”, a następnie do „Otwórz plik”. Możesz też kliknąć plik prawym przyciskiem myszy, wybrać „Otwórz za pomocą”, a następnie QuickTime.
Po otwarciu filmu kliknij „Edytuj”, a poniżej znajdziesz opcje obracania i odwracania
Po zablokowaniu pożądanej orientacji musisz wyeksportować wideo z nowymi dodanymi zmianami. Opcja „Eksportuj” znajduje się w menu „Plik” w QuickTime.
Wybierz ustawienia pliku, które chcesz wyeksportować, i kliknij „OK”, aby rozpocząć eksport.
Po zakończeniu operacji eksportowania znajdziesz nowy plik w dowolnym miejscu, w którym chcesz go zapisać w odpowiedniej orientacji!
Cała ta poprawka zajęła mi mniej niż 5 minut, ale w zależności od długości filmu może to potrwać znacznie dłużej (lub krócej, znowu się różni).
ffmpeg -i input.mp4 -filter:v "transpose=1,transpose=1" output.mp4
Wykonał dla mnie lewę. Nie jestem pewien, dlaczego filtr transpozycji nie zapewnia możliwości obrotu o 180 stopni na raz, ale cokolwiek. Sprawdź Dokumenty, aby uzyskać więcej informacji.