Użyj kodeka kopiującego ffmpeg, aby połączyć pliki * .ts w jeden plik MP4


47

Mam kilka segmentów ts opisanych w jednym pliku index.m3u8:

index.m3u8        
segment1_0_av.ts  
segment2_0_av.ts  
segment3_0_av.ts  
segment4_0_av.ts  
segment5_0_av.ts

Wiem, że wszystkie są kodowane w ten sam sposób. ffprobe daje mi następujące informacje:

Input #0, mpegts, from 'segment1_0_av.ts':
  Duration: 00:00:10.00, start: 0.100511, bitrate: 1251 kb/s
  Program 1 
    Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 960x540 [SAR 1:1 DAR 16:9], 12.50 fps, 25 tbr, 90k tbn, 25 tbc
    Stream #0:1[0x101]: Audio: aac ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 105 kb/s
    Stream #0:2[0x102]: Unknown: none ([21][0][0][0] / 0x0015)

Chciałbym połączyć je w jeden pojemnik MP4. Ale kiedy próbuję poleceń takich jak:

ffmpeg -f concat -i filelist.txt -c copy output.mp4

gdzie generuje plik filelist.txt z pliku index.m3u8, narzeka na niemożność odczytania różnych plików. Ale sama konwersja plików ts wydaje się działać dobrze. Myślę, że nie używam ffmpeg poprawnie.

Jak użyć ffmpeg do połączenia plików ts opisanych przez index.m3u8 w jeden kontener mp4 za pomocą kodeka kopiującego?

Odpowiedzi:


58

Nie jestem pewien, dlaczego ffmpeg wyświetla błąd. Jednak ts jest jednym z niewielu formatów, które można po prostu połączyć. Następnie, gdy masz pojedynczy ts, przenieś do mp4.

Pod oknami:

copy /b segment1_0_av.ts+segment2_0_av.ts+segment3_0_av.ts all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

W systemie GNU / Linux za pomocą bash:

cat segment1_0_av.ts segment2_0_av.ts segment3_0_av.ts > all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

12
Możesz także potrzebować -bsf:a aac_adtstoasc.
Camilo Martin

1
ciekawe, że polecenie NIE jest ffmpeg copy ..., to copy ...(pod Windows)
Ron Royston

25

Używanie kopiowania lub kota do łączenia plików, takich jak aktualna najwyższa odpowiedź Szatmary, może pozostawić plik, który jest odtwarzany daleko poza limit i nie może wyszukiwać wraz z problemami z odtwarzaniem.

Zamiast tego, aby poprawnie połączyć te pliki, użyj ffmpeg, zgodnie z instrukcją https://trac.ffmpeg.org/wiki/Concatenate . (Zainstaluj ffmpeg tutaj, jeśli jeszcze go nie masz https://github.com/adaptlearning/adapt_authoring/wiki/Installing-FFmpeg .)

Jeśli jesteś zbyt leniwy, aby przeczytać mój pierwszy link, musisz w zasadzie utworzyć plik .txt zawierający listę wszystkich plików, które chcesz połączyć w podobny sposób (który mój pierwszy link zawiera instrukcje, jak łatwo to zrobić) w folderze, w którym „ ponownie wykonuję konkatenację:

file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

Oto wklej kopię z mojego pierwszego linku w jeden sposób, aby utworzyć plik tekstowy, jeśli na przykład masz Windows w linii poleceń, ale oczywiście możesz zrobić plik ręcznie lub w dowolny sposób:

(for %i in (*.ts) do @echo file '%i') > mylist.txt

Dokładnie sprawdź, czy plik .txt wygląda dobrze i jest poprawnie sformatowany!

Następnie w wierszu poleceń uruchom:

ffmpeg -f concat -i mylist.txt -c copy all.ts

gdzie „mylist.txt” to właśnie utworzony plik .txt.

Sprawdź, czy plik wynikowy odtwarza poprawnie wideo. Stąd możesz przesłać do MP4 jak zwykle, jeśli chcesz:

ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

To for %i in (*.ts) donie sortuje się poprawnie dla i> = 10. Poza tym wszystko działa, dzięki. Rzeczywiście wystąpiły problemy z połączonym plikiem, nie wspominając o tym, że plik utworzony za pomocą twojej metody okazał się być o 16% mniejszy (miałem 1400 części o 400kb).
użytkownik

@ użytkownik dla liczb w celu iteracji po liczbach takich jakfor i in {1..10}; do echo file \'$i.ts\' >> list.txt ; done
qwr

8

Odpowiedź z 2017 r

Ale kiedy próbuję poleceń ..., narzeka, że ​​nie mogę odczytać różnych plików.

Gdy wykonuję ffmpeg -i some.ts -c copy some.mp4określone wideo, pojawia się następujący komunikat o błędzie:

Malformed AAC bitstream detected: use the audio bitstream filter 
'aac_adtstoasc' to fix it ('-bsf:a aac_adtstoasc' option with ffmpeg)

av_interleaved_write_frame(): Operation not permitted

Nic dziwnego, że wykonanie ffmpeg -i some.ts -c copy -bsf:a aac_adtstoasc some.mp4go naprawia.


3
Zdobądź wystarczająco nowy, ffmpega teraz zrobi to automatycznie.
llogan

7

Składając wszystko razem

Korzystając z odpowiedzi Juana Aquino (i poprawiając pierwsze polecenie, aby był zgodny z Bash i stosując naturalną kolejność plików), a także odpowiedź 7vujy0f0hy, prosty działający skrypt dla powłoki Linux Bash to:

#!/bin/bash
for i in `ls *.ts | sort -V`; do echo "file $i"; done >> mylist.txt
ffmpeg -f concat -i mylist.txt -c copy -bsf:a aac_adtstoasc video.mp4

4

Prawidłowy sposób na konkatowanie wielu plików wideo z listy odtwarzania m3u8 to

ffmpeg -i "index.m3u8" -codec copy output.mp4


  • lista odtwarzania m3u8 może znajdować się w Internecie lub lokalnie w katalogu
    • zawiera listę ścieżek do plików względem listy odtwarzania
  • -codec copy aby uniknąć kodowania
  • rodzaj pojemnika ma znaczenie:
    • *.mp4 jest w porządku, ale wydaje się trochę powolne w multipleksowaniu, gdy playlista jest pobierana z sieci
    • *.mkvlub *.tsdziałał najlepiej dla mnie

2

Możesz zrobić prostą konkatenację tak (z bash):

for f in ./{0..<number>}.ts; do cat $f >> out.ts; done

Zamień <number>na najwyższy numer (oczywiście). Warianty z ffmpeg nie działały poprawnie. Wyjściowy plik wideo zacinałby się dziwnie.

Korzystam z pętli for, aby zapewnić prawidłową kolejność plików. Może nie potrzebujesz tego. Być może możliwe jest nawet przesłanie danych wyjściowych do ffmpeg i konwersja do mp4 w locie.


1

Możesz użyć potoku tych plików ts do ffmpeg i wyprowadzić plik mp4.

cat *.ts | ffmpeg -i pipe: -c:a copy -c:v copy output.mp4

lub Jeśli nazwa pliku nie ma kolejności,

grep .*.ts index.m3u8 | xargs cat | ffmpeg -i pipe: -c:a copy -c:v copy output.mp4


0

Wszystkie popularne odpowiedzi na to pytanie, które wprowadzają czytelników w błąd, aby połączyć pliki TS przed uruchomieniem ffmpeg, są niepoprawne. Aby mieć pewność, że dźwięk i obraz nie będą zsynchronizowane podczas składania strumienia MP4, należy użyć słabo udokumentowanej, ale ważnej funkcji „-f concat” programu ffmpeg.

    delimiterBeforeFileNumber="-"
    ls |egrep '[.]ts$' \
        |sort "-t$delimiterBeforeFileNumber" -k2,2n \
        |sed -r "s/(.*)/file '\1'/" >ts.files.txt

    ffmpeg -f concat -i ts.files.txt -c copy tsw.014.ts.mp4

Dwa wiersze przygotowawcze kodu po prostu tworzą plik zawierający listę plików TS w tym formacie wiersza:

    file 'seg-37-a.ts'

Właściwie, kiedy tego spróbowałem, pomiędzy segmentami w ostatnim filmie było niewielkie „zacinanie się”. Więc przynajmniej w tym jednym przypadku pomogło to najpierw połączyć pliki TS.
Sphinxxx
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.