Bagaimana cara menggabungkan dua file MP4 menggunakan FFmpeg?


444

Saya mencoba untuk menggabungkan dua file mp4 menggunakan ffmpeg. Saya ingin ini menjadi proses otomatis, mengapa saya memilih ffmpeg. Saya mengubah dua file menjadi file .ts dan kemudian menyatukannya dan kemudian mencoba untuk menyandikan file .ts. File-file tersebut h264 dan aac dikodekan dan saya berharap untuk menjaga kualitasnya tetap sama atau sedekat mungkin dengan aslinya.

ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

Sayangnya saya mendapatkan pesan kesalahan berikut yang kembali dari ffmpeg selama penyandian:

[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s    
av_interleaved_write_frame(): Error while opening file

Ini terjadi sekitar setengah jalan melalui pengkodean yang membuat saya berpikir bahwa Anda tidak dapat menggabungkan dua file .t bersama dan membuatnya bekerja.

Jawaban:


788

FFmpeg memiliki tiga metode gabungan:

1. filter video concat

Gunakan metode ini jika input Anda tidak memiliki parameter yang sama (lebar, tinggi, dll), atau bukan format / codec yang sama, atau jika Anda ingin melakukan penyaringan. (Anda bisa menyandikan ulang hanya input yang tidak cocok sehingga mereka berbagi codec dan parameter lain yang sama, lalu gunakan penghemat concat untuk menghindari pengkodean ulang input lain).

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
       -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] 
                        concat=n=3:v=1:a=1 [v] [a]" \
       -map "[v]" -map "[a]" output.mkv

Perhatikan bahwa metode ini melakukan penyandian ulang.

2. demuxer concat

Gunakan metode ini ketika Anda ingin menghindari penyandian ulang dan format Anda tidak mendukung penggabungan level file (kebanyakan file yang digunakan oleh pengguna umum tidak mendukung penggabungan level file).

$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Untuk Windows :

(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

3. protokol concat

Gunakan metode ini dengan format yang mendukung penggabungan level file (MPEG-1, MPEG-2 PS, DV). Jangan tidak digunakan dengan MP4.

ffmpeg -i "concat:input1|input2" -codec copy output.mkv

Metode ini tidak berfungsi untuk banyak format, termasuk MP4, karena sifat format ini dan penggabungan sederhana yang dilakukan oleh metode ini.


Jika ragu tentang metode yang digunakan, coba demuxer concat.

Lihat juga


3
Karakter command prompt Windows adalah ^; Saya juga mengalami masalah dengan tanda kutip sehingga menjadi: ffmpeg -i concat: input1 ^ | input2 -codec copy output
user423430

1
Jawaban yang membantu. Dan bahkan lebih masuk akal bagi saya ketika saya membaca variasi ini: superuser.com/a/607384/74576
Ryan

3
concat demuxer berfungsi untuk video, tapi saya kehilangan audio
Loïc

24
Untuk penggunaan oneliner: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv menerima lebih banyak codec daripada mp4, tetapi Anda juga bisa mencobanya dengan mp4). Ini -safe 0untuk versi ffmpeg terbaru yang mengeluhkan nama file yang tidak aman , dan -type fhanya untuk daftar file. Saya menambahkan | sortuntuk mengurutkan file berdasarkan abjad; karena findmembacanya agar disimpan di sistem file. Juga berfungsi untuk file dengan spasi putih.
erik

1
Bagi saya, di Windows, tanda ganda kutip bekerja (bukan tunggal dalam contoh Anda): ffmpeg -i "concat:input1|input2" -codec copy output. Tidak perlu keluar dari karakter pipa.
Shovalt

85

UNTUK FILES MP4

Untuk file .mp4 (yang saya peroleh dari DailyMotion.com: episode tv 50 menit, hanya dapat diunduh dalam tiga bagian, seperti tiga file video .mp4) berikut ini adalah solusi yang efektif untuk Windows 7 , dan TIDAK melibatkan penyandian ulang file.

Saya mengganti nama file (sebagai file1.mp4 , file2.mp4 , file3.mp4 ) sedemikian rupa sehingga bagian-bagiannya dalam urutan yang benar untuk melihat episode tv lengkap.

Kemudian saya membuat file batch sederhana (concat.bat), dengan konten berikut:

:: Create File List
echo file file1.mp4 >  mylist.txt 
echo file file2.mp4 >> mylist.txt
echo file file3.mp4 >> mylist.txt

:: Concatenate Files
ffmpeg -f concat -i mylist.txt -c copy output.mp4

File batch , dan ffmpeg.exe , keduanya harus diletakkan di folder yang sama dengan file .mp4 yang akan digabung. Kemudian jalankan file batch. Biasanya diperlukan waktu kurang dari sepuluh detik untuk berjalan.
.

Addendum (2018/10/21) -

Jika yang Anda cari adalah metode untuk menentukan semua file mp4 di folder saat ini tanpa banyak mengetik ulang, coba ini di file batch Windows Anda ( HARUS sertakan opsi- aman 0 ):

:: Create File List
for %%i in (*.mp4) do echo file '%%i'>> mylist.txt

:: Concatenate Files
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Ini berfungsi pada Windows 7, dalam file batch. Jangan coba menggunakannya di baris perintah, karena hanya berfungsi di file batch!


5
Solusi termudah sejauh ini.
1934286

Ini harus menjadi jawaban terbaik dan termudah. Kerja bagus, teman saya. Kamu menyelamatkan hariku.
DysaniazzZ

Ini adalah solusi yang baik tetapi berbicara tentang file batch membuat suara ini primitif (seperti yang dilakukan dalam batch), dan lebih kompleks daripada itu (karena file batch sama sekali tidak diperlukan). Jauh lebih jelas jika Anda hanya menampilkan C:\blah>type mylist.txt<ENTER>(Jadi mereka melihat isi file itu) Kemudian ffmpeg -f concat -i mylist.txt -c copy output.mp4<ENTER> Juga Anda harus menyertakan referensi trac.ffmpeg.org/wiki/Concatenate (referensi itu bahkan menggunakan nama file yang sama, mylist.txt)
barlop

Ini adalah solusi yang sangat bagus karena ini menyelamatkan Anda dari mengetikkan daftar panjang file untuk -iparameter. Di Linux saya melakukan ini: ls -1 P1041*.mp4 | sed s/"P"/" file P"/g > mylist.txtyang bahkan lebih keren daripada pengkodean skrip batch. Lagi pula, -c copyberkinerja sangat cepat (yang saya tidak sadari) dan ini adalah keajaiban nyata dari jawaban ini.
Würgspaß

1
Dengan file mp4 saya, tidak ada audio sama sekali dalam file output setelah menjalankan kode concat Anda pada Mac, menggunakan ffmpeg v3.2.2.
kakyo

60

Inilah cara cepat (kurang dari 1 menit) dan tanpa kehilangan untuk melakukan ini tanpa memerlukan file perantara:

ls Movie_Part_1.mp4 Movie_Part_2.mp4 | \
perl -ne 'print "file $_"' | \
ffmpeg -f concat -i - -c copy Movie_Joined.mp4

"Ls" berisi file-file yang akan digabungkan. "Perl" membuat file concatenation on-the-fly ke dalam pipa. Bagian "-i -" memberi tahu ffmpeg untuk membaca dari pipa.

(catatan - file saya tidak memiliki spasi atau hal-hal aneh di dalamnya - Anda perlu melarikan diri shell yang tepat jika Anda ingin melakukan ide ini dengan file "keras").


2
Apakah ini pada OSX dan itu berhasil! Luar biasa, solusi lossless cepat dengan sedikit persyaratan.
GM Lucid

1
Dengan melarikan diri yang tepat untuk file yang mengandung spasi putih:ls Movie_Part_1.mp4 Movie_Part_2.mp4 | perl -ne '$_ =~ s/\n$//; print "file '"'"'$_'"'"'\n"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4
Thomas Bachem

4
Anda juga bisa melakukannya ls * | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4jika file Anda diberi nama dengan baik dan teratur. Bekerja sangat baik untuk saya di OS X, persis apa yang saya inginkan.
natebeaty

3
Di Linux saya menggunakan oneliner ini: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv menerima lebih banyak codec daripada mp4, tetapi Anda juga bisa mencobanya dengan mp4). Ini -safe 0untuk versi ffmpeg terbaru yang mengeluhkan nama file yang tidak aman , dan -type fhanya untuk daftar file. Saya menambahkan | sortuntuk mengurutkan file berdasarkan abjad; karena findmembacanya agar disimpan di sistem file. Juga berfungsi untuk file dengan spasi putih.
erik

13
Saya harus menambahkan parameter ini ffmpeguntuk membuatnya berfungsi:-protocol_whitelist file,tcp,http,pipe
Bensge

45

untuk file MP4:

Jika mereka tidak persis sama (100% codec yang sama, resolusi yang sama, jenis yang sama) file MP4, maka Anda harus trans-kode mereka ke aliran menengah pada awalnya:

ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts
ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts
// now join
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

CATATAN! : Output akan seperti file pertama (dan bukan yang kedua)


2
Seperti yang diilustrasikan dalam jawaban saya, di bawah ini, transcoding file tidak diperlukan. FFmpeg dapat menggabungkan beberapa file mp4 menjadi satu file mp4 - tanpa langkah perantara, dan tanpa pengodean ulang. Satu-satunya kasus di mana setiap pengkodean ulang akan diperlukan adalah jika file asli bukan file mp4 tetapi tujuannya adalah untuk membuat file mp4 sebagai file output.
Ed999

@T. Todua: Saya tertarik untuk mengetahui apa sebenarnya perbedaan antara dua file sumber mp4 Anda. Apakah mereka menggunakan tingkat sampel yang berbeda (mis. 44.100 Hz dan 48.000 Hz)? Atau apakah mereka menggunakan bit rate yang berbeda (mis. 128 kbps dan 64 kbps)? Dalam kedua kasus tersebut, saya tidak begitu mengerti bagaimana perintah -c copy (instruksi stream-copy) akan memodifikasi file sumber untuk membuatnya kompatibel.
Ed999

4
@ T.Todua Hai, perintah berfungsi dengan baik saat video tidak memiliki trek audio. Namun, ketika myfile1.mp4 tanpa audio dan myfile2.mp4 dengan audio, hasil output.mp4 tanpa audio. Output.mp4 yang diharapkan harus mengandung audio. Bagaimana saya bisa menyelesaikannya?
AnswerZhao

2
@ T.Todua er .... Sayang sekali. File1 | file2 menghasilkan video yang berbeda dengan file2 | file1. urutannya penting.
AnswerZhao

1
Saya mencoba perintah Anda pada file concat 2 mp4. Berhasil. Namun, audio file kedua menjadi berombak seperti suara Ah-oh-Ee dalam rangkaian baru yang dihasilkan. apakah Anda memiliki perbaikan untuk ini?
superlinux

35

Saya mencoba menggabungkan tiga .mp3file audio menjadi satu.m4a file dan perintah ffmpeg ini berfungsi.

Perintah input:

ffmpeg -i input1.mp3 -i input2.mp3 -i input3.mp3 \
       -filter_complex "concat=n=3:v=0:a=1" -f MOV -vn -y input.m4a

Arti dari -filter_complex "concat = n = 3: v = 0: a = 1" :

concat berarti menggunakan fungsi media concatenate (join).
n berarti mengkonfirmasi jumlah total file input.
v berarti punya video ? gunakan 0 = tidak ada video, 1 = berisi video.
a berarti memiliki audio ? gunakan 0 = tidak ada audio, 1 = mengandung audio.
-f berarti memaksa mengatur format file (untuk melihat semua format yang didukung, gunakan ffmpeg -formats)
-vn berarti menonaktifkan video (dan juga -anakan menonaktifkan audio jika tidak diinginkan)
-y berarti menimpa file output (jika file output sudah ada).

Untuk info lebih lanjut: gunakan ffmpeg -h full cetak semua opsi (termasuk semua format dan opsi spesifik codec, sangat panjang)


1
Saya menggunakan ini -f concat -safe 0 -i "file.txt" -c copy -y "OutPut.mp4"akan concat tetapi ketika beberapa video dengan audio dan beberapa tanpa audio itu tidak berfungsi bagaimana saya bisa memilah ini. Terima kasih -
Ahmad

1
Ini bekerja. Terima kasih atas penjelasan terperinci dalam jawaban Anda. Ini sangat membantu.
Joe T. Boka

31

Saya akhirnya menggunakan mpg sebagai format perantara dan berhasil (CATATAN ini adalah contoh berbahaya, -kala 0 akan mengkodekan ulang video ...)

ffmpeg -i 1.mp4 -qscale 0 1.mpg
ffmpeg -i 2.mp4 -qscale 0 2.mpg
cat 1.mpg 2.mpg | ffmpeg -f mpeg -i - -qscale 0 -vcodec mpeg4 output.mp4

8
Pada komentar ini, -sameqtelah dihapus. Gunakan -qscale 0sebagai gantinya.
Xavier Ho

6
-sameqtidak berarti "kualitas yang sama" dan telah dihapus dari ffmpeg seperti yang disebutkan oleh @XavierHo.
llogan

3
Tampaknya memalukan harus transcode video melalui format perantara hanya untuk menyatukan dua file. Anda akan kehilangan generasi. Lebih baik tidak masuk lebih dalam daripada format wadah dan gunakan concatperintah di ffmpeg, seperti yang dilakukan @rogerdpack di atas.
Randall Cook

8
Kenapa ini jawaban yang diterima? Ini metode yang sangat buruk.
Nama Tampilan

4
@SargeBorsch Karena berfungsi. Saya sudah mencoba semua yang lain di halaman - Tidak ada yang bekerja.

14

Dokumentasi terperinci tentang berbagai cara penggabungan dalam ffmpeg dapat ditemukan di sini .

Anda dapat menggunakan 'Filter perhatian' untuk penggabungan cepat.

Ia melakukan pengkodean ulang. Opsi ini paling baik bila input memiliki format video / audio yang berbeda.

Untuk Concatenating 2 file:

ffmpeg -i input1.mp4 -i input2.webm \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Untuk Concatenating 3 file:

ffmpeg -i input1.mp4 -i input2.webm -i input3.mp4 \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Ini berfungsi untuk jenis file input yang sama maupun multi.


dapatkah Anda menentukan lebih detail tentang opsi yang Anda miliki dalam contoh ini?
Pengembang

@Developer: Untuk penjelasan tentang opsi -> Concat filter wiki
SJ00

4
Ketika menggabungkan 3 file, Anda harus menggunakan concat = n = 3: v = 1: a = 1 bukan n = 2
Cynapsis

1
Saya tidak mendapatkan penggabungan lossless ouput.mp4bitrate video saya secara signifikan lebih rendah daripada bitrate video input video
jasan

Terima kasih Cynapsis untuk menunjukkannya dan georgiecasey untuk memperbarui perintah
SJ00

10

Saya menemukan operator pipa tidak bekerja untuk saya ketika menggunakan opsi 3 untuk menyelesaikan beberapa MP4 pada Mac dalam jawaban yang diterima.

One-liner berikut berfungsi pada Mac (High Sierra) untuk menggabungkan mp4s, tanpa diperlukan pembuatan file perantara.

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4


2
Jawaban sederhana ini adalah satu-satunya yang benar-benar bekerja untuk saya. Halaman demi halaman dokumentasi di sini dan di tempat lain, sementara ini satu-liner sederhana adalah semua yang diperlukan - dan benar-benar berfungsi. Terima kasih.
blujay

10

Di sini 2 solusi bash murni hanya menggunakan ffmpegdan tidak menggunakan

  • file perantara
  • perl, python atau javascript

Solusi satu-liner menggunakan ls

ls video1.mp4 video2.mp4 | while read line; do echo file \'$line\'; done | ffmpeg -protocol_whitelist file,pipe -f concat -i - -c copy output.mp4

Fungsi yang membutuhkan 0 atau 2+ argumen

#######################################
# Merge mp4 files into one output mp4 file
# usage:
#   mergemp4 #merges all mp4 in current directory
#   mergemp4 video1.mp4 video2.mp4
#   mergemp4 video1.mp4 video2.mp4 [ video3.mp4 ...] output.mp4 
#######################################
function mergemp4() {
  if [ $# = 1 ]; then return; fi

  outputfile="output.mp4"

  #if no arguments we take all mp4 in current directory as array
  if [ $# = 0 ]; then inputfiles=($(ls -1v *.mp4)); fi
  if [ $# = 2 ]; then inputfiles=($1 $2); fi  
  if [ $# -ge 3 ]; then
    outputfile=${@: -1} # Get the last argument
    inputfiles=(${@:1:$# - 1}) # Get all arguments besides last one as array
  fi

  # -y: automatically overwrite output file if exists
  # -loglevel quiet: disable ffmpeg logs
  ffmpeg -y \
  -loglevel quiet \
  -f concat \
  -safe 0 \
  -i <(for f in $inputfiles; do echo "file '$PWD/$f'"; done) \
  -c copy $outputfile

  if test -f "$outputfile"; then echo "$outputfile created"; fi
}

Catatan: telah mencoba beberapa solusi di utas ini dan tidak ada yang memuaskan saya


9

berdasarkan tanggapan rogerdpack dan Ed999, saya telah membuat versi .sh saya

#!/bin/bash

[ -e list.txt ] && rm list.txt
for f in *.mp4
do
   echo "file $f" >> list.txt
done

ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt

itu menggabungkan semua *.mp4file di folder saat ini kejoined-out.mp4

diuji pada mac.

filesize yang dihasilkan adalah jumlah pasti dari 60 file yang saya uji. Seharusnya tidak ada kerugian. Apa yang saya butuhkan


9

ini bekerja untuk saya (di windows)

ffmpeg -i "concat:input1|input2" -codec copy output

sebuah contoh...

ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4

Python

Menggunakan beberapa kode python untuk melakukannya dengan sebanyak mp4 yang ada di folder (instal python dari python.org, salin dan tempel dan simpan kode ini ke dalam file bernama mp4.py dan jalankan dari cmd yang dibuka di folder dengan python mp4.py dan semua mp4 di folder akan digabungkan)

import glob
import os

stringa = ""
for f in glob.glob("*.mp4"):
    stringa += f + "|"
os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")

Versi 2 dengan Python

Diambil dari pos saya di blog saya , ini adalah bagaimana saya melakukannya dengan python:

import os
import glob

def concatenate():
    stringa = "ffmpeg -i \"concat:"
    elenco_video = glob.glob("*.mp4")
    elenco_file_temp = []
    for f in elenco_video:
        file = "temp" + str(elenco_video.index(f) + 1) + ".ts"
        os.system("ffmpeg -i " + f + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + file)
        elenco_file_temp.append(file)
    print(elenco_file_temp)
    for f in elenco_file_temp:
        stringa += f
        if elenco_file_temp.index(f) != len(elenco_file_temp)-1:
            stringa += "|"
        else:
            stringa += "\" -c copy  -bsf:a aac_adtstoasc output.mp4"
    print(stringa)
    os.system(stringa)

concatenate()

1
Protokol concat tidak boleh digunakan dengan MP4 dan tidak akan berfungsi sebagaimana disebutkan dalam jawaban yang diterima .
Logan

@ LordNeckbeard Saya ingin tahu apakah Anda tahu jawaban untuk pertanyaan ffmpeg ini tentang menggabungkan 2 video MP4 sambil menentukan bitrate output? video.stackexchange.com/q/24569/5657 Terima kasih.
Ryan

@ LordNeckbeard Dugaan saya adalah bahwa jawaban Anda akan menjadi yang terbaik, tetap, jika Anda siap! Saya tidak terlalu puas dengan milik saya sendiri.
Ryan

Tidak hanya (seperti yang ditunjukkan oleh Lord Neckbeard), perlu untuk mengonversi file .mp4 ke format .TS menengah agar penggabungan berhasil, tetapi, mungkin bahkan lebih buruk, jawaban ini bahkan tidak mulai menjawab kebutuhan akan input. file video memiliki bitrate, frame rate, sample rate, timebase, dan durasi yang sesuai. Tanpa semua 5 faktor yang sama, file tidak dapat digabungkan (yaitu bergabung menggunakan aliran salinan ), tetapi harus disandikan ulang sebagai gantinya.
Ed999

7

Untuk .mp4file, saya menemukan itu bekerja lebih baik dan lebih cepat untuk menggunakan alat baris perintah opensource: mp4box. Maka Anda dapat menggunakannya dengan cara ini:

mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4

Unduh di sini untuk sebagian besar platform: https://gpac.wp.imt.fr/mp4box/


2
Meskipun ini mungkin berguna bagi seseorang, persyaratannya adalah: " Saya mencoba untuk menggabungkan dua file mp4 menggunakan ffmpeg. Saya ingin ini menjadi proses otomatis ". Silakan baca pertanyaan lengkap dan coba dan berikan jawaban yang tepat.
thvs86

5
Jawaban ini sepenuhnya tepat sasaran. Ini adalah alat FOSS yang melakukan pekerjaan yang sama. Itu dapat digunakan dalam skrip seperti FFmpeg. Ini membuat pekerjaan dilakukan lebih sederhana daripada jawaban FFmpeg. Lihatlah betapa rumitnya mereka! Salah satunya menggunakan Node.js untuk memanggil FFmpeg! Penyakit jiwa. Tolong berhenti dengan winkism dan coba dan buat StackOverflow berguna lagi. Situs ini adalah bayang-bayang diri sebelumnya berkat para winks seperti Anda. Selain itu, pertanyaan ini adalah contoh dari "Masalah XY," yang tidak asing lagi bagi Anda.
blujay

Tidak masalah bahwa mp4box adalah alat FOSS. Pertanyaannya menanyakan jawaban menggunakan ffmpeg, bukan mp4box.
jramos775

@ thvs86 Saya salah satu contohnya. Saya menggunakan ffmpeg karena itu pisau swiss nyata untuk media. Saya juga mencari bantuan dengan kasus penggunaan khusus saya, karena struktur argumen bisa sangat kompleks (yang ditunjukkan oleh beragam jawaban di sini). Ini adalah pertama kalinya saya mendengar tentang mp4box dan saya tidak akan menemukannya jika bukan karena jawaban ini. Jadi +1 dari saya dan tolong, tolong, pikirkan lebih banyak tentang orang yang mencari jawaban daripada tentang poin Internet yang tidak berarti dan aturan yang kaku.
Pavel

4

Berikut ini skrip yang saya buat untuk menggabungkan beberapa GoPro mp4 menjadi 720p mp4. Semoga ini bisa membantu.

#!/bin/sh
cmd="( "
for i; do
    cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}

Ini BUKAN penggabungan. Kode ini tidak menggabungkan input, tetapi mengkodekan ulang input tersebut. Ini mengambil file video sembarang dan mengubahnya menjadi bitrate audio dan video yang umum (terlepas dari bitrate asli file sumber atau bingkai asli). O / p ingin menggabungkan dua file menggunakan aliran salinan, bukan menyandikan ulang mereka, jadi ini tidak menjawab pertanyaan yang diajukan.
Ed999

4

Dari dokumentasi di sini: https://trac.ffmpeg.org/wiki/Concatenate

Jika Anda memiliki file MP4, file ini dapat digabungkan tanpa kehilangan dengan terlebih dahulu mentranskodenya ke stream transport MPEG-2. Dengan video H.264 dan audio AAC, berikut ini dapat digunakan:

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

Pendekatan ini bekerja pada semua platform.

Saya membutuhkan kemampuan untuk merangkum ini dalam skrip lintas platform, jadi saya menggunakan fluent-ffmpegdan menghasilkan solusi berikut:

const unlink = path =>
  new Promise((resolve, reject) =>
    fs.unlink(path, err => (err ? reject(err) : resolve()))
  )

const createIntermediate = file =>
  new Promise((resolve, reject) => {
    const out = `${Math.random()
      .toString(13)
      .slice(2)}.ts`

    ffmpeg(file)
      .outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
      .output(out)
      .on('end', () => resolve(out))
      .on('error', reject)
      .run()
  })

const concat = async (files, output) => {
  const names = await Promise.all(files.map(createIntermediate))
  const namesString = names.join('|')

  await new Promise((resolve, reject) =>
    ffmpeg(`concat:${namesString}`)
      .outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
      .output(output)
      .on('end', resolve)
      .on('error', reject)
      .run()
  )

  names.map(unlink)
}

concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
  console.log('done!')
)

1
ffmpeg \
  -i input_1.mp4 \
  -i input_2.mp4 \
  -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
  -map [vid] \
  -c:v libx264 \
  -crf 23 \
  -preset veryfast \
  output.mp4

1
Tidak hanya memposting jawaban, Anda dapat menambahkan sedikit penjelasan yang memahami solusinya dengan lebih baik bagi OP dan pembaca di masa mendatang.
Balagurunathan Marimuthu

1
Ini menciptakan video bisu baru dengan kedua input diputar sebagai waktu yang sama di samping satu sama lain. Saya berharap rangkaian akan membuat video di mana input_1.mp4 diputar dan kemudian input_2.mp4
Alexx Roche

3
Ini adalah jawaban yang salah sepenuhnya. Ini tidak sesuai dengan videonya, hanya diputar secara diam-diam, seperti yang @AlexxRoche sebutkan.
Kalob Taulien

1

Menggabungkan semua file mp4 dari direktori saat ini

Saya pribadi tidak suka membuat file eksternal yang harus saya hapus setelah itu, jadi solusi saya mengikuti yang mencakup daftar penomoran file (seperti file_1_name, file_2_name, file_10_name, file_20_name, file_100_name, ...)

#!/bin/bash
filesList=""
for file in $(ls -1v *.mp4);do #lists even numbered file
    filesList="${filesList}${file}|"
done
filesList=${filesList%?} # removes trailing pipe
ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4

Saya menyalin kode ini ke Notepad dan tidak ada yang terjadi.
7vujy0f0hy

1
@ 7vujy0f0mengapa ini bekerja di linux dengan bash shell mungkin bisa bekerja dengan cygwin
Pipo

1

Setelah berbagai upaya di bawah ini skrip bekerja untuk saya di windows 10 PowerShell.

    $files=Get-ChildItem -path e:\ -Filter *.mp4


    $files| ForEach-Object  {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII


    if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}

    E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4

    # Conversion Cleanup
    Remove-Item e:\temp.txt

Di sini dua baris pertama membuat file teks temp.txt yang memiliki konten berikut

file 'e:\first.mp4'
file 'e:\second.mp4'

Baris ke-3 dan ke-4 memeriksa apakah ffmpeg tersedia di path dan membuat "bergabung.mp4"

Perbedaan utama dari jawaban lain adalah sebagai berikut

usage  of -bsf:v hevc_mp4toannexb -an

untuk file mp4 saya di atas berfungsi, Anda mungkin perlu menggunakan alternatif lain seperti di bawah ini tergantung pada encoding video Anda.

h264_mp4toannexb

Semua kemungkinan filter Bitstream dapat ditemukan di https://ffmpeg.org/ffmpeg-bitstream-filters.html


Milik saya adalah MP4 yang berasal dari kamera CCTV. Tanpa perintah itu, percakapan gagal menghasilkan file keluaran. Saya menggunakan ffmpeg terbaru dari situs webnya.
rahul maindargi

0

Inilah metode saya untuk bergabung dengan direktori yang penuh dengan file MP4 menggunakan substitusi perintah dan filter video concat (ini akan menyandikan ulang) - mengira orang lain akan dapat menggunakan liner ini, terutama jika Anda memiliki banyak file (saya hanya bergabung dengan 17 file dalam sekali gerakan):

ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4

NB perintah ini menggabungkan file-file Anda dengan urutan nama mereka (yaitu urutan yang sama seperti yang disajikan jika Anda menjalankan ls *.mp4) - dalam kasus saya, mereka masing-masing memiliki nomor trek, sehingga bekerja dengan baik.


0

Protokol penting yang dijelaskan di sini; https://trac.ffmpeg.org/wiki/Concatenate#protocol

Ketika diimplementasikan menggunakan pipa bernama untuk menghindari file menengah

Sangat cepat (baca: instan), tidak ada bingkai yang terjatuh, dan berfungsi dengan baik.

Ingatlah untuk menghapus file pipa yang dinamai dan ingat untuk memeriksa apakah video tersebut H264 dan AAC yang dapat Anda lakukan dengan adil ffmpeg -i filename.mp4(periksa h264 dan aac menyebutkan)


-1

Jawaban yang diterima dalam bentuk skrip PowerShell yang dapat digunakan kembali

Param(
[string]$WildcardFilePath,
[string]$OutFilePath
)
try
{
    $tempFile = [System.IO.Path]::GetTempFileName()
    Get-ChildItem -path $wildcardFilePath | foreach  { "file '$_'" } | Out-File -FilePath $tempFile -Encoding ascii
    ffmpeg.exe -safe 0 -f concat -i $tempFile -c copy $outFilePath
}
finally
{
    Remove-Item $tempFile
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.