Połącz dwa pliki mp4 z ffmpeg bez utraty jakości

16

Chcę połączyć 2 filmy za pomocą ffmpeg. Ja używam:

ffmpeg -i output1.mp4 -scodec copy -vbsf h264_mp4toannexb i0.ts

Ale plik MP4, który dostaję wygląda znacznie gorzej niż plik źródłowy.

Oto informacje o obu plikach

   Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output1.mp4':
   Metadata:
   major_brand     : isom
   minor_version   : 1
   compatible_brands: isom
   creation_time   : 2013-06-13 15:40:36
   Duration: 00:00:15.72, start: 0.000000, bitrate: 2053 kb/s
   Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720, 1931 kb/s, 25 fps, 25 tbr,   12800 tbn, 50 tbc
   Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 128 kb/s

  Input #0, mpegts, from 'i0.ts':
  Duration: 00:00:15.64, start: 1.400000, bitrate: 1382 kb/s
  Program 1 
  Metadata:
  service_name    : Service01
  service_provider: Libav
  Stream #0.0[0x100]: Video: mpeg2video (Main), yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 104857 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
  Stream #0.1[0x101](und): Audio: mp2, 44100 Hz, stereo, s16, 128 kb/s

Jak mogę rozwiązać ten problem?

Eric Leschinski
źródło
Co dokładnie próbujesz zrobić? Określenie „concat” oznacza dołączyć kilka plików, ale odnosimy się tylko do jednego wejścia, output1.mp4i jednym wyjściowym i0.ts. Kodowanie do kontenera wyjściowego ts mpeg2videodomyślnie użyje kodera (przynajmniej z twoją kompilacją), a ostatnim razem sprawdziłem, że domyślne ustawienie szybkości transmisji lub jakości dla tego kodera -b:v 200kjest zbyt niskie w większości przypadków.
llogan
Przepraszam. Następnie konkatuję je za pomocą ffmpeg -i "concat: i0.ts | i1.ts" output1111.mp4. Problem polega jednak na tym, że jakość jest już
Może nie być konieczne ponowne kodowanie do wideo MPEG-2. Czy wszystkie twoje oryginalne dane wejściowe ( output1.mp4itp.) Mają te same formaty, liczbę klatek i rozmiar ramki?
llogan
tak, dokładnie. Wszyscy są równi
1
Zobacz także stackoverflow.com/questions/7333232/…
rogerdpack,

Odpowiedzi:

36

Zastanów się nad użyciem concatdemuxera . W ten sposób można uniknąć tworzenia tymczasowych, stratnych plików pośrednich i pominąć dodatkowy etap ponownego kodowania.

Uwaga: Wszystkie dane wejściowe muszą mieć te same typy strumieni (te same formaty, ta sama podstawa czasu itp.).

  1. Utwórz plik tekstowy i dołącz ścieżki i nazwy każdego pliku do połączenia (lub „dołączenia”). Przykładowy plik input.txt:

    file '/home/jenia/input1.mp4'
    file '/home/jenia/input2.mp4'
    file '/home/jenia/input3.mp4'
    
  2. Teraz możesz użyć concatdemuxera:

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

Jeśli nie masz tej funkcji, oznacza to, że albo twoja ffmpeg jest za stara, albo używasz „fałszywego” ffmpeg z libav fork.

Łatwe w użyciu kompilacje statyczne są dostępne dla systemów Linux, OS X i Windows za pośrednictwem strony pobierania FFmpeg , lub możesz postępować zgodnie ze szczegółowymi instrukcjami kompilacji ffmpeg .

Zobacz także:

Llogan
źródło
Właśnie tego chciałem i pomógł mi scalić 2 pliki .mov z mojego iPhone'a 6. Dzięki.
Ryan
7

Najszybszy 1-liniowy będzie:

ls Movie\ Part\ * | while read line; do echo file \'$line\'; done | ffmpeg -f concat -i - -c copy output.mp4
Hackeron
źródło
Czy jest jakaś szansa na uzyskanie takiego 1-onliner dla wiersza poleceń systemu Windows?
PeterCo
2
W systemie Linux użyłem tego narzędzia oneliner: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv akceptuje więcej kodeków niż mp4, ale możesz także wypróbować go z mp4). -safe 0Jest dla ostatnich ffmpeg wersjach narzekających uznanych za niebezpieczne nazwy pliku , a -type fjest jedynie wymieniając pliki. Dodałem, | sortaby posortować pliki alfabetycznie; ponieważ findodczytuje je w kolejności zapisanej w systemie plików. Działa również w przypadku plików z białymi spacjami.
erik