ffmpeg połącz dwa pliki mp4 z ffmpeg w wierszu poleceń

29

Mogę z powodzeniem połączyć wiele plików za pomocą następującego polecenia:

ffmpeg -f concat -i input.txt -codec copy output.mp4

Jedynym problemem związanym z tym poleceniem jest to, że musisz odczytać ścieżki plików z pliku tekstowego o nazwie input.txt o następującej treści:

file 'C:\Users\fabio\Downloads\Super\Sharks\01.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\02.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\03.mp4'

Czy istnieje sposób na osiągnięcie tego samego celu bez konieczności odczytywania ścieżek plików z pliku? Próbowałem następujących bez powodzenia:

ffmpeg -f concat -i file "C:\a\b\01.mp4" file "C:\a\b\02.mp4" -codec copy output.mp4
ffmpeg -f concat -i "C:\a\b\01.mp4" "C:\a\b\02.mp4" -codec copy output.mp4

Czy muszę użyć innego polecenia?

Fabio Delarias
źródło
1
powiązane: stackoverflow.com/questions/7333232/…
Ciro Santilli 13 改造 中心 法轮功 六四 事件

Odpowiedzi:

37

Aktualizacja 2019:

Jak wspomniano w komentarzach, przepełnienie stosu zawiera doskonały opis dostępnych opcji konkatenacji, a także omówienie używanej metody w zależności od typów używanych plików:

Jak połączyć dwa pliki MP4 za pomocą FFmpeg?

Oryginalna odpowiedź 2016:

Powinieneś być w stanie użyć metody protokołu konkat do łączenia plików:

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

Ponadto instrukcja FFmpeg omawia metodę specjalnie dla plików MP4, aby bezstratnie połączyć je, ale wymaga utworzenia plików tymczasowych (lub nazwanych potoków):

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Carson Darling
źródło
1
Pierwsze polecenie działało dla mnie jak masło. Zajęło mi 2 do 3 sekund, aby połączyć moje pliki 6 mp4 w plik wyjściowy (około 239 MB).
Sachin
22
Pierwsze polecenie nie działało dla mnie. Właśnie skopiował pierwszy plik.
Luis A. Florit,
3
To nie działa, po prostu skopiował pierwszy plik output.mp4.
crmpicco
2
Konkatenacja na poziomie pliku nie działa dla MP4, więc protokół konkatowania nie jest zalecany dla tego formatu i na ogół nie będzie działał.
llogan
1
@brasofilo Dziękujemy za link. To już dawno spóźnione, ale zaktualizowałem odpowiedź, aby wskazać ludziom w tym kierunku.
Carson Darling
5

Możesz zamienić plik na listę, wysyłając listę do stdouti czytając listę stdinprzez ffmpeg:

(echo file 'a.mp4' & echo file 'b.mp4') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "result.mp4"
Qwertiy
źródło
W przypadku ffmpeg w wersji 2.4.3-tessus w systemie Mac OS 10.12.6 pojawia się tylko błąd: „Nierozpoznana opcja„ biała lista protokołów ””. Bez opcji Białej listy protokołów wydaje się, że po prostu tworzy kopię drugiego pliku MP4.
James
2

Nie, wydaje się, że nie ma możliwości użycia demultipera konkatacji ffmpeg w jednym wierszu poleceń bez włamania. Musisz utworzyć wejściowy plik tekstowy z listą plików. Myślałem, że to dziwne, może ktoś doda to do FFMpeg w późniejszym terminie.

Akceptowana odpowiedź na to pytanie wykorzystuje protokół konkat, a nie demuxer konkat, o co poprosił OP.

georgiecasey
źródło
1
Tak naprawdę jest. standardowe
Qwertiy
protokół concat nie powinien być używany z MP4 ani żadnym innym formatem wymagającym globalnego nagłówka.
llogan
1

Nadal możesz to zrobić w skrypcie bez zmiany polecenia. Coś jak:

echo "file fname1" >$$.tmp    #single redirect creates or truncates file
echo "file fname2" >>$$.tmp   # double redirect appends
echo "file fname3" >>$$.tmp   # do as many as you want.

ffmpeg -f concat -i $$.tmp -codec copy output.mp4

rm $$.tmp  # just to clean up the temp file. 
           # For debugging, I usually leave this out.

$$ rozwija się do pid powłoki wykonującej polecenie, więc nazwa pliku będzie inna przy każdym uruchomieniu. więc możesz użyć $$. txt, jeśli wolisz. Albo coś innego...

Możesz także użyć tutaj plików, aby dodać do pliku wiązkę danych:

cat <<EOF >$$.tmp
file fname1
file fname2
file fname3
EOF

bash Podstawianie zmiennych działa, więc możesz programowo określić zawartość pliku, nie trzeba go naprawiać. Cały czas osadzam tego rodzaju rzeczy w pętlach. Wreszcie przekierowanie działa tak samo jak powyżej, więc> $$. Tmp zostaje obcięte, a następnie zapisuje, >> $$ .tmp dodaje.

Richard Betel
źródło
2
Pytanie brzmi: „Czy istnieje sposób na osiągnięcie tego samego celu bez konieczności odczytywania ścieżek plików z pliku?” Wszystko, co zrobiłeś, to sposób na zapisanie ścieżek plików do pliku (przed odczytaniem ścieżek plików z pliku). To nie odpowiada na pytanie.
Scott