Używanie ffmpeg do cięcia wideo


333

Używam ffmpeg, aby wyciąć fragment dużego pliku, takiego jak ten:

ffmpeg -i input.wmv -ss 60 -t 60 -acodec copy -vcodec copy output.wmv

-ssCzęść działa w porządku, ale -tjest ignorowany. Prawidłowo usuwa początkowe określone sekundy określone za pomocą, -ssale następnie przechodzi do końca danych wejściowych z kopią.

Czy istnieje sposób użycia ffmpeg do odcięcia końca filmu bez jego ponownego kodowania?


1
ta składnia jest poprawna.
jiggunjer,

Odpowiedzi:


393

Możesz użyć tej -ssopcji, aby określić znacznik czasu rozpoczęcia, oraz -topcji, aby określić czas trwania kodowania. Znaczniki czasu muszą być w HH:MM:SS.xxxformacie lub w sekundach ( s.msec).

Poniższe spowoduje wycięcie pierwszych 30 sekund, a następnie wycięcie wszystkiego, co nastąpi po 10 sekundach:

ffmpeg -ss 00:00:30.0 -i input.wmv -c copy -t 00:00:10.0 output.wmv
ffmpeg -ss 30 -i input.wmv -c copy -t 10 output.wmv

Zauważ, że -tjest to opcja wyjściowa i zawsze musi być określona po -i .

Kilka porad:

  • W przypadku starszych wersji ffmpeg, jeśli używasz -sspóźniej -i, możesz uzyskać dokładniejsze wyszukiwanie kosztem wolniejszego działania. Zobacz także: Szukanie z FFmpeg
  • Można użyć -tozamiast -tokreślić znacznik czasu, na który chcesz wyciąć. Zamiast tego -i <input> -ss 30 -t 10możesz zrobić -i <input> -ss 30 -to 40to samo.

  • Jeśli twój ffmpeg nie obsługuje -club -tojest prawdopodobnie bardzo nieaktualny. Skompiluj nową wersję samodzielnie lub pobierz wersję statyczną ze strony głównej. To naprawdę nie jest skomplikowane.


1
@Mainain Właściwie, możesz uzyskać większą dokładność, ustawiając -ss za. I slhck wspomina o tym tutaj blog.superuser.com/2012/02/24/... również w dokumentacji ffmpeg dla -ss mówi o różnicy między umieszczeniem go przed lub po.
barlop

5
+1 Przyszedłem tutaj, aby dowiedzieć się, jak zignorować wszystko po pierwszych 35 sekundach, dzięki:ffmpeg -i input.wmv -c copy -t 35 output.wmv
karlphillip

2
To nie działa dla mnie (MP4). Po prostu produkuje 5 sekundowy czarny ekran:frame= 150 fps=0.0 q=-1.0 Lsize= 264kB time=00:00:09.97 bitrate= 216.6kbits/s
kowal

2
Spowodowało to powstanie czarnego ekranu o wielkości 3-4 s na początku mojego klipu wideo. Modyfikacja Chrisa z pominięciem -c copyusunęła początkowy czarny ekran, szczegóły patrz jego odpowiedź.
joelostblom 16.04.16

4
Piszesz: „Poniższe wycinałoby pierwsze 30 sekund, a następnie wszystko, co następuje po 10 sekundach:” <- Co to znaczy? Przez klip rozumiesz? ponieważ klip może oznaczać wycięcie. Zakładając, że masz na myśli to. Czy masz na myśli Rozpocznij za 30 sekund, a stamtąd tylko 10 sekund? Jeśli tak, to proponuję napisać, że byłoby o wiele jaśniej.
barlop

94

Jak wspomnieli inni, stawianie -ssprzed (znacznie szybciej) lub po (dokładniejszym) -irobi dużą różnicę. Sekcja „Szybkie i dokładne wyszukiwanie” na stronie wyszukiwania ffmpeg zawiera informacje na temat tego, jak je zdobyć, a ja skorzystałem z niego i to robi dużą różnicę. Zasadniczo stawiasz -ssprzed I po -i, po prostu upewnij się, że masz wystarczająco dużo czasu przed tym, gdzie chcesz rozpocząć cięcie, aby mieć kolejną klatkę kluczową. Przykład: jeśli chcesz zrobić 1-minutowy klip, od 9min0sek do 10min 0sek w Video.mp4, możesz to zrobić zarówno szybko, jak i dokładnie, używając:

ffmpeg -ss 00:08:00 -i Video.mp4 -ss 00:01:00 -t 00:01:00 -c copy VideoClip.mp4

Pierwszy -ssszuka szybkiego do (w przybliżeniu) 8 minut 0 sekund, a następnie drugi -ssszuka dokładnie do 9 minut 0 sekund, a następnie -t 00:01:00pobiera klip 1 minuta.

Zwróć też uwagę na ten ważny punkt z tej strony: „Jeśli użyjesz -ssz -c:v copy, wynikowy strumień bitów może skończyć się nierównym, niemożliwym do odtworzenia lub niezsynchronizowanym ze strumieniem audio, ponieważ ffmpeg jest zmuszony używać / dzielenia tylko na i-ramkach. „

Oznacza to, że musisz ponownie zakodować film, nawet jeśli chcesz go po prostu skopiować, lub ryzykować, że będzie on przerywany i nie będzie zsynchronizowany. Możesz spróbować -c copynajpierw, ale jeśli film jest do bani, musisz to zrobić ponownie.


to samo ostrzeżenie dotyczy -c:a copytego sposobu poszukiwania.
jiggunjer

1
Najlepsza odpowiedź, ten sposób działał dla mnie najlepiej.
Ondra Žižka

3
Wygląda na to, że „-ss” jest teraz szybki i dokładny w ffmpeg 2.1+ bez konieczności dwukrotnego określania. trac.ffmpeg.org/wiki/Seeking
Conrad Meyer

25

Przekonałem się, że w -sspołączeniu z -c copypoczątkiem przyniosło pół sekundy.

Aby tego uniknąć, musisz usunąć -c copy(co wprawdzie wykona transkodowanie).


4
Istnieje inna odpowiedź, która dotyczy dokładności. Ponowne kodowanie z opcją domyślną często NIE jest tym, co chcesz zrobić!
Tomasz Gandor

Dobry punkt @TomaszGandor
Chris

1
W ogóle nie rozumiem odpowiedzi @ TomaszGandor, ale usunięcie -c copygo naprawiło.
Iulian Onofrei

14

RĘCZNIE

Otwórz plik w odtwarzaczu multimediów, który będzie klatka po klatce, i odtwórz plik AVISynth z danymi, takimi jak:

DirectShowSource(("C:\Downloads\Video\Do you want him.flv"), Pixel_Type="yuy2").Crop(0,0,-0,-0)
Subtitle("C:\Downloads\Video\Do you want him.flv", font="Arial", size=24, text_color=$ff0000, align=3)
ShowFrameNumber(scroll=true, x=336, y=27, font="Arial", size=24, text_color=$ff0000)
ShowTime(x=398, y=44, font="Arial", size=24, text_color=$ff0000)

Następnie wycinaj w formacie EXACT time:

ffmpeg -i "Path\do you want him.flv"        \
       -ss 00:00:05.240 -to 00:00:08.360    \
       -vcodec libx264 -acodec libvo_aacenc \
       "Path\Do you want him1.flv"

i

ffmpeg -i "Path\do you want him.flv"        \
       -ss 00:00:10.240 -to 00:00:14.360    \
       -vcodec libx264 -acodec libvo_aacenc \
       "Path\Do you want him2.flv"

Teraz utwórz plik txt z plikami wideo o treści takiej jak:

file 'C:\Downloads\Video\Do you want him1.flv'
file 'C:\Downloads\Video\Do you want him2.flv'

Uruchom ffmpeg:

ffmpeg -f concat -i FileList.txt -c copy "Path\NewName_joined.flv"

9

Dla mnie -topcja nie działała, ale -vframesdziałała. Wolę używać #frames, ponieważ wolę wycinać w I-Frames i odkryłem GOP do używania wideo ffprobe.

Linia poleceń, która działała dla mnie to:

ffmpeg -ss 60s -i input.wmv -vframes 1800 -acodec copy -vcodec copy output.wmv

Nawiasem mówiąc, umieszczenie -ssz przodu -ima dużą różnicę w czasie wykonania.


1
Właściwie -vframes(lub -frames:v) powinno przyjść później, -iponieważ jest to opcja wyjściowa.
slhck,

5

Podobnie jak w przypadku user225366, opcja -t nie działa w przypadku krótkich filmów, ale działa w przypadku dłuższych filmów. W przypadku krótkich filmów wydaje się, że -frames: v jest lepszy. To działało dla mnie.

ffmpeg -ss 4 -i input.mp4 -frames:v 200 -vcodec copy output.mp4

-Akodec kopia musi zostać dodana, jeśli wideo ma dźwięk, jak pokazują inne odpowiedzi.


0

Nie widzę o tym wielu wspominających (nie jestem ekspertem, więc może jest jakiś haczyk), ale jeśli twój plik ma inne strumienie, takie jak napisy i inne metadane, takie jak rozdziały i tak dalej, można wycinać / przycinać i zachować wszystkie strumienie za pomocą następujące polecenie

ffmpeg -to 60 -i input.mkv -map 0 -c copy output.mkv

Z -map 0wami podjąć wszelkie strumienie w pliku, a przy -c copykopiowaniu wszystkie je takimi jakie są.
Użycie -topominięcia startu przez -ssspowoduje obcięcie wejściowego wideo od początku do drugiego 60.

Fiddling mapprzydaje się również wtedy, gdy chcesz zachować tylko określone strumienie w wycięciu (być może nie potrzebujesz wszystkich źródeł audio w pliku lub tylko niektórych napisów).

Używam tego, gdy muszę podzielić duże pliki MKV, których nie można zapisać w pamięci FAT32.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.