FFmpeg dzieli wideo i łączy ponownie

8

Staram się korzystać z FFmpeg, aby podzielić wideo w oparciu o pewne start_timei end_timewejść i zastąpić te z innych plików wideo. Na przykład, dla wprowadzenia 10 15będę musiał zamienić DOKŁADNE sekundy 10 to 15innym wideo.

OK. Co przychodzi mi na myśl, to:

  1. Najpierw podziel wideo (w tym przypadku 0-10, 10-15 i 15-koniec)
  2. Zamień 10-15 na inne wideo
  3. Scal wszystkie pod-filmy z powrotem

Pierwsze pytanie: czy to najlepsze i najszybsze rozwiązanie? Czy mamy łatwiejsze polecenie lub inne narzędzia do zastąpienia określonego czasu w filmie innym filmem?

Drugie pytanie: Zakładając, że FFmpeg jest realnym rozwiązaniem, kiedy po prostu używam polecenia ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, mój kod przetwarzania wideo nie może odczytać i przetworzyć pliku. Użyłem mediainfonarzędzia do porównania dwóch plików i zauważyłem różnice w rozmiarach nagłówka, podczas gdy wszystkie rzeczy związane z kodekiem wideo były takie same. Zauważyłem, że ROZMIAR NAGŁÓWKA jest inny, co najwyraźniej powoduje problem. Czy istnieją sposoby na wymuszenie, aby rozmiar nagłówka (oprócz kodeków) był taki sam?

AKTUALIZACJA: Oto oryginalny .mp4plik, który działa dobrze w emulatorze.

Ariana
źródło
Najpierw musielibyśmy poradzić sobie z problemem, o którym wspomniałeś w drugim pytaniu. Pokaż dokładną komendę, której używasz, oraz pełne, niecięte wyjście wiersza komend, które otrzymujesz z ffmpeg. Pokaż także wszelkie rzeczywiste błędy, które wystąpią podczas odczytywania pliku - dobrze byłoby dokładnie wiedzieć, jaki jest Twój „kod przetwarzania”.
slhck
@slhck kod przetwarzania wideo jest ogromną bazą kodu. Nie mogę tego udostępnić. Po prostu z kilku powodów oryginalny plik jest odczytywany, ale nie jest ponownie generowany. W .mp4razie potrzeby mogę jednak udostępnić oryginalny plik.
Ariana
Użyłem narzędzia mediainfo do porównania dwóch plików i zauważenia różnic w rozmiarach nagłówków i innych rzeczach
Ariana
Posiadanie oryginału pomogłoby, ale nie będziemy w stanie rozwiązać problemu, dlaczego nie można go odczytać, obawiam się, że jest to jakiś wewnętrzny kod.
slhck 14.07.17
@slhck Przesłałem plik. Moje pytanie jest aktualizowana
Ariana

Odpowiedzi:

9

Używanie trimi concat- plików źródłowych z różnymi kodekami

W tym celu należy upewnić się, że poszczególne pliki mają tę samą rozdzielczość, a najlepiej takie same próbkowanie klatek i chroma itp. Zapobiegnie to błędom lub usterkom podczas konkatenacji.

Możesz zrobić wszystko za jednym razem, bez dzielenia pliku, używając filtrów trimi concat:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

Tutaj trimsłuży do określania poszczególnych części wejściowych strumieni wideo ( 0:v, 1:v), które później chcesz połączyć. Te części są nazwane v0poprzez v2. ( setptsFiltr resetuje znaczniki czasu tych poszczególnych części na 0, co jest wymagane do konkatenacji). Później łączymy trzy części.

Jeśli chcesz przyciąć od określonego znacznika czasu do końca, użyj trim=start=15zamiast określać zakres.

Jeśli Twoje pliki zawierają dźwięk, musisz przyciąć te strumienie osobno:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

Pamiętaj, że w tym przypadku wideo i audio zostaną ponownie zakodowane - upewnij się, że określono odpowiednie docelowe parametry wyjściowej jakości (np. -crfDla x264, x265 lub libvpx-vp9). Możesz przeczytać więcej na ten temat na Wiki FFmpeg, np. Dla VP9 lub H.264 .

Korzystanie z poszczególnych segmentów

Jeśli chcesz podzielić klipy, a następnie ponownie je złożyć:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

Jeśli pliki zawierają dźwięk, zastosuj to samo podejście jak powyżej:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

Spowoduje to ponowne kodowanie strumienia wideo. Jest to nieco prostsze, ale poza tym powinno być równoważne powyższej metodzie.

Korzystanie z concatdemuxera

Zasadniczo możesz także próbować połączyć strumienie bitów bez ich ponownego kodowania, korzystając z demuxera konkatencyjnego. Utwórz plik o nazwie concat.txti dodaj następujące wpisy (odpowiadające klipom wideo utworzonym powyżej):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

Następnie połącz te pojedyncze pliki:

ffmpeg -f concat -i concat.txt -c copy output.avi

Wymaga to jednak, aby twoje klipy miały ten sam kodek, rozdzielczość, szybkość klatek itp. - więc nie działa z wszystkimi rodzajami źródeł heterogenicznych.

Za pomocą concatprotokołu

Powyższy rodzaj konkatenacji na poziomie pliku można również osiągnąć przy użyciu concatprotokołu, z takimi samymi ograniczeniami jak powyżej (ten sam kodek, rozdzielczość itp.):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

Aby uzyskać więcej informacji na temat konkatenacji, przeczytaj odpowiednią stronę Wiki FFmpeg .

slhck
źródło
To wygląda bardzo kompletnie! Dzięki. Spróbuję ich!
Ariana,
Nie wiem, dlaczego użycie tej concatmetody powoduje błąd:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana,
W przypadku „używania poszczególnych segmentów” widzę zatrzymanie i małe wycięcie wyniku. Czy są jakieś sposoby, aby to naprawić?
Ariana,
Metoda 1 działa idealnie. Jedno: jak możemy określić „do końca” bez podawania konkretnej liczby (zamiast 30 s)
Ariana
1
Przepraszamy, popełniłem błąd. W przypadku concatdemuxera składnia była inna. Naprawiono teraz. Aby przejść do końca, skorzystaj trim=start=15z dokumentacji filtru przycinania: ffmpeg.org/ffmpeg-filters.html#trim - jeśli chodzi o problemy z timingiem, to naprawdę zależy od materiału źródłowego. Nie miałem problemów z połączeniem przesłanego klipu.
slhck 17.07.17