İki MP4 dosyasını FFmpeg kullanarak nasıl birleştirebilirim?


443

Ben ffmpeg kullanarak iki mp4 dosyaları bitiştirmeye çalışıyorum. Bunun otomatik bir işlem olması gerekiyor, bu yüzden neden ffmpeg'i seçtim. İki dosyayı .ts dosyalarına dönüştürüyorum ve sonra bunları birleştiriyorum ve sonra da bu .ts dosyasını kodlamaya çalışıyorum. Dosyalar h264 ve aac kodludur ve kaliteyi olabildiğince aynı veya orijinaline yakın tutmayı umuyorum.

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

Ne yazık ki kodlama sırasında ffmpeg geri gelen aşağıdaki hata mesajı alıyorum:

[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

Bu, iki .ts dosyasını birbirine yapıştıramayacağınızı ve çalıştıramayacağınızı düşündüren kodlamanın yaklaşık yarısı kadar olur.

Yanıtlar:


787

FFmpeg'in üç birleştirme yöntemi vardır:

1. concat video filtresi

Girişleriniz aynı parametrelere (genişlik, yükseklik vb.) Sahip değilse veya aynı biçimler / kodekler değilse veya herhangi bir filtreleme yapmak istiyorsanız bu yöntemi kullanın. (Yalnızca aynı codec bileşenini ve diğer parametreleri paylaşmaları için eşleşmeyen girdileri yeniden kodlayabilir, ardından diğer girişleri yeniden kodlamaktan kaçınmak için concat demuxer'ı kullanabilirsiniz).

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

Bu yöntemin bir yeniden kodlama gerçekleştirdiğini unutmayın.

2. concat demuxer

Yeniden kodlamadan kaçınmak istediğinizde ve biçiminiz dosya düzeyinde birleştirmeyi desteklemiyorsa (genel kullanıcılar tarafından kullanılan çoğu dosya dosya düzeyinde birleştirmeyi desteklemez) bu yöntemi kullanın.

$ 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

Windows için :

(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. concat protokolü

Bu yöntemi dosya düzeyi birleştirmesini destekleyen biçimlerle kullanın (MPEG-1, MPEG-2 PS, DV). Do not MP4 ile kullanın.

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

Bu yöntem, bu biçimlerin doğası ve bu yöntemle gerçekleştirilen basit birleştirme nedeniyle MP4 dahil olmak üzere birçok biçim için çalışmaz.


Hangi yöntemin kullanılacağı konusunda şüpheniz varsa concat demuxer'ı deneyin.

Ayrıca bakınız


3
Windows komut istemi çıkış karakteri ^; Ben de tırnak işaretleri ile ilgili sorunlar koştu bu yüzden oldu: ffmpeg -i concat: input1 ^ | input2 -koduk kopya çıktı
user423430

1
Yararlı cevap. Ve bu varyasyonu okuduğumda daha da anlamlı oldu: superuser.com/a/607384/74576
Ryan

3
concat demuxer video için çalışıyor, ancak ses kaybediyorum
Loïc

24
Bir oneliner kullanımı için: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv, mp4'ten daha fazla kodek kabul eder, ancak mp4 ile de deneyebilirsiniz). -safe 0Şikayet son ffmpeg sürümleri içindir Güvensiz dosya adı ve -type fdosyaları listeleme içindir. | sortDosyaları alfabetik olarak sıralamak için ekledim ; çünkü findbunları dosya sistemine kaydedildiği gibi okur. Beyaz boşluklu dosyalar için de çalışır.
erik

1
Benim için, Windows, çift tırnak işareti (yerine örnekte tek bir) çalıştı: ffmpeg -i "concat:input1|input2" -codec copy output. Boru karakterinden kaçmaya gerek yoktur.
13'te Shovalt

84

MP4 DOSYALARI İÇİN

For .mp4 dosyaları: Aşağıdaki için etkili çözüm oldu (ı DailyMotion.com elde edilen 50 dakikalık tv bölüm, sadece üç bölümden itibaren üç .mp4 video dosyalarını indirilebilir) Windows 7 ve does DEĞİL yeniden kodlamayı içerir Dosyalar.

Dosyaları yeniden adlandırdım ( dosya1.mp4 , dosya2.mp4 , dosya3.mp4 olarak gibi) parçaları, tüm tv bölümünü görüntülemek için doğru sırada olacak şekilde .

Sonra aşağıdaki içeriklerle basit bir toplu iş dosyası (concat.bat) oluşturdum :

:: 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

Toplu iş dosyası ve FFMPEG.exe olarak, zorunluluk ikisi de aynı klasörüne yerleştirilir .mp4 dosyaları birleştirilecek. Sonra toplu iş dosyasını çalıştırın. Çalıştırılması genellikle on saniyeden az sürer.
.

Zeyilname (2018/10/21) -

Ne aradığınız çok fazla yeniden yazma olmadan geçerli klasördeki tüm mp4 dosyalarını belirtmek için bir yöntem ise, bunun yerine Windows toplu iş dosyasında deneyin ( -safe 0 seçeneği dahil GEREKİR ):

:: 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

Bu, toplu iş dosyasında Windows 7'de çalışır. Etmeyin sadece bir toplu iş dosyasında çalıştığı için, komut satırında bunu kullanmayı deneyin!


5
Şimdiye kadarki en kolay çözüm.
1934286

Bu en iyi ve en kolay cevap olmalıdır. Aferin, kardeşim. Günümü kurtardın.
DysaniazzZ

Bu iyi bir çözümdür, ancak bir toplu iş dosyası hakkında konuşmak bu sesi ilkel hale getirir (toplu olarak yapıldığı gibi) ve olduğundan daha karmaşıktır (çünkü bir toplu iş dosyası tamamen gereksizdir). Sadece gösterirseniz çok daha açıktır C:\blah>type mylist.txt<ENTER>(Bu dosyanın içeriğini görüyorlar) O zaman ffmpeg -f concat -i mylist.txt -c copy output.mp4<ENTER> ayrıca bir referans trac.ffmpeg.org/wiki/Concatenate (bu referans bile aynı dosya adını, mylist.txt kullanıyor)
barlop

Bu çok iyi bir çözümdür, çünkü -iparametre için uzun dosya listeleri yazmanızı önler . Linux'ta bunu yaptım: ls -1 P1041*.mp4 | sed s/"P"/" file P"/g > mylist.txtbu, toplu bir komut dosyasını kodlamaktan bile daha havalı. Her neyse, -c copyçok hızlı bir şekilde (farkında olmadığım) bir performans sergiliyor ve bu cevabın asıl büyüsü bu.
Würgspaß

1
Mp4 dosyalarımla, ffmpeg v3.2.2'yi kullanarak Mac'te concat kodunuzu çalıştırdıktan sonra çıktı dosyasında hiç ses yok.
kakyo

60

İşte ara dosyalara gerek kalmadan bunu yapmanın hızlı (1 dakikadan az sürer) ve kayıpsız bir yolu:

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

"Ls" birleştirilecek dosyaları içerir "perl" anında bir boru içine birleştirme dosyası oluşturur "-i -" bölümü ffmpeg borudan okumak için söyler

(not - dosyalarımda boşluk veya garip şeyler yoktu - bu fikri "sabit" dosyalarla yapmak istiyorsanız uygun kabuk çıkışına ihtiyacınız olacak).


2
OSX üzerinde bunu yaptı ve harika çalıştı! Az gereksinimleri olan harika, hızlı kayıpsız çözüm.
GM Lucid

1
Boşluk içeren dosyalar için uygun bir kaçışla: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
Ayrıca, sadece yapabilirsiniz ls * | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4dosyalarınızı iyi adlandırılmış ve sırayla eğer. OS X'de tam olarak istediğim gibi çalıştı.
natebeaty

3
Linux'ta bu oneliner'ı kullandım: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv, mp4'ten daha fazla kodek kabul eder, ancak mp4 ile de deneyebilirsiniz). -safe 0Şikayet son ffmpeg sürümleri içindir Güvensiz dosya adı ve -type fdosyaları listeleme içindir. | sortDosyaları alfabetik olarak sıralamak için ekledim ; çünkü findbunları dosya sistemine kaydedildiği gibi okur. Beyaz boşluklu dosyalar için de çalışır.
erik

13
ffmpegÇalışması için bu parametreyi eklemek zorunda kaldım :-protocol_whitelist file,tcp,http,pipe
Bensge

44

MP4 dosyaları için:

Tam olarak aynı değilse (% 100 aynı kodek, aynı çözünürlük, aynı tür) MP4 dosyaları, önce onları ara akışlara dönüştürmeniz gerekir:

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

NOT! : Çıktı ilk dosya gibi olacak (ikinci dosya değil)


2
Cevabımda gösterildiği gibi, dosyaları dönüştürmek gerekli değildir. FFmpeg birden fazla mp4 dosyasını tek bir mp4 dosyasına birleştirebilir - herhangi bir ara adım olmadan ve yeniden kodlama yapmadan. Herhangi bir yeniden kodlamanın gerekli olacağı tek durum, orijinal dosyalar mp4 dosyaları değilse ancak amaç çıktı dosyası olarak bir mp4 dosyası oluşturmaktır.
Ed999

@ T. Todua: İki mp4 kaynak dosyanız arasındaki farkların tam olarak ne olduğunu öğrenmek isterim. Farklı örnekleme hızları kullanıyorlar mı (örn. 44,100 Hz ve 48,000 Hz)? Yoksa farklı bit hızları mı kullanıyorlar (örneğin 128 kbps ve 64 kbps)? Her iki durumda da, -c kopyasının (bir akış-kopyalama talimatı) kaynak dosyalarını uyumlu hale getirmek için nasıl değiştireceğini tam olarak anlamıyorum.
Ed999

4
@ T.Todua Merhaba, videolar ses parçası olmadığında komut iyi çalışıyor. Ancak, myfile1.mp4 ses olmadan ve myfile2.mp4 ses ile birlikte, sonuç output.mp4 ses olmadan. Beklenen output.mp4 ses içermelidir. Bunu nasıl çözebilirim?
AnswerZhao

2
@ T.Todua er .... Çok kötü. Dosya1 | dosya2, dosya2 | dosya1 ile farklı bir video oluşturur. sipariş önemlidir.
AnswerZhao

1
Komutunuzu concat 2 mp4 dosyalarında denedim. İşe yarıyor. Ancak, ikinci dosyanın sesi üretilen yeni birleşme sırasında Ah-oh-Ee sesleri gibi kesik kesik geliyor. buna bir çözümün var mı?
superlinux

35

Üç .mp3ses dosyasını bir .m4adosyaya birleştirmeye çalışıyordum ve bu ffmpeg komutu çalışıyor.

Giriş komutu:

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

"-Filter_complex" teriminin anlamları :

concat , medya birleştirme (birleştirme) işlevini kullanmak anlamına gelir.
n , toplam girdi dosyası sayısını onaylamak anlamına gelir.
v video var demek ? 0 kullan = video yok, 1 = video içeriyor.
bir araç sese sahip ? 0 = ses yok, 1 = ses içerir.
-f zorla set dosya formatı anlamına gelir (desteklenen tüm formatları görmek için, kullanın ffmpeg -formats)
-vn videoyu devre dışı bırakır (ve istenmediyse-an sesi devre dışı bırakır)
-y çıktı dosyalarının üzerine yazılır (çıktı dosyası zaten mevcutsa).

Daha fazla bilgi için: ffmpeg -h full tüm seçenekleri yazdır seçeneğini kullanın (tüm biçime ve codec'e özgü seçenekler dahil, çok uzun)


1
fi kullanın bu -f concat -safe 0 -i "file.txt" -c copy -y "OutPut.mp4"concat ama bazı videolar ses ile ve bazıları ses olmadan olduğunda bu nasıl sıralayabilirim çalışmıyor. Teşekkürler -
Ahmad

1
Bu çalışıyor. Cevabınızdaki ayrıntılı açıklama için teşekkürler. Çok faydalı.
Joe T. Boka

31

Ara format olarak mpg kullanarak sona erdi ve işe yaradı (NOT bu tehlikeli bir örnek, -qscale 0 videoyu yeniden kodlayacaktır ...)

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
Bu yorumdan itibaren -sameqkaldırıldı. -qscale 0Bunun yerine kullanın .
Xavier Ho

6
-sameq"aynı kalite" anlamına gelmez ve @XavierHo tarafından belirtildiği gibi ffmpeg'den kaldırılmıştır.
llogan

3
Sadece iki dosyayı birleştirmek için videoyu ara bir formatta dönüştürmek utanç verici görünüyor. Nesil kaybı yaşarsınız. Kapsayıcı biçiminden daha derine concatinmemek ve yukarıda @rogerdpack'in yaptığı gibi ffmpeg'deki komutu kullanmak daha iyidir .
Randall Cook

8
Bu nasıl kabul edilmiş bir cevap? Bu çok kötü bir yöntem.
Görünen Ad

4
@SargeBorsch Çünkü işe yarıyor. Sayfadaki diğer her şeyi denedim. Hiçbiri çalışmıyor.

14

Ffmpeg'de çeşitli birleştirme yolları hakkında ayrıntılı belgeler burada bulunabilir .

Hızlı birleştirme için 'Concat filtresi'ni kullanabilirsiniz .

Yeniden kodlama yapar. Bu seçenek, girişlerin farklı video / ses formatlarına sahip olması durumunda en iyisidir.

2 dosyayı birleştirmek için:

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

3 dosyayı birleştirmek için:

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

Bu, birden çok giriş dosyası türüyle aynı şekilde çalışır.


bu örnekteki seçeneklerle ilgili daha fazla ayrıntı belirtebilir misiniz?
Geliştirici

@Developer: Seçeneklerin açıklaması için -> Concat filtre wiki
SJ00

4
3 dosyayı birleştirirken concat = n = 3: v = 1: a = 1 değil n = 2
Cynapsis

1
kayıpsız birleşme alamıyorum benim ouput.mp4video bit hızı giriş video video bitrate önemli ölçüde daha düşük
jasan

İşaret ettiğiniz için teşekkürler Cynapsis ve komutu güncellemek için georgiecasey
SJ00

10

Kabul edilen cevapta Mac'te birkaç MP4'ü birleştirmek için 3. seçeneği kullanırken boru operatörünün benim için çalışmadığını gördüm.

Aşağıdaki tek astar, mp4'leri birleştirmek için Mac'te (High Sierra) çalışır ve aracı dosya oluşturma gerekmez.

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


2
Bu basit cevap benim için gerçekten işe yarayan tek cevaptı. Sayfalar burada ve başka yerlerde dokümantasyon sayfalarında yer alırken, bu basit tek astar gereken tek şeydir - ve aslında çalışır. Teşekkür ederim.
blujay

10

Burada sadece kullanan ffmpegve kullanmayan 2 saf bash çözümü

  • bir ara dosya
  • perl, python veya javascript

Kullanarak tek astarlı çözüm 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

0 veya 2+ bağımsız değişken alan işlev

#######################################
# 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
}

Not: Bu konuda bazı çözümler denemişti ve hiçbiri beni tatmin etmedi


9

rogerdpack ve Ed999'un yanıtlarına dayanarak, .sh sürümümü oluşturdum

#!/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

*.mp4geçerli klasördeki tüm dosyalarıjoined-out.mp4

mac üzerinde test edilmiştir.

sonuçta elde edilen dosya boyutu test edilen 60 dosyamın toplamıdır. Herhangi bir kayıp olmamalıdır. Tam ihtiyacım olan şey


9

bu benim için çalıştı (pencerelerde)

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

Bir örnek...

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

piton

Bir klasörde çok sayıda mp4 ile yapmak için bazı python kodlarını kullanma (python.org'dan python yükleyin, kopyalayıp yapıştırın ve mp4.py adlı bir dosyaya kaydedin ve python ile klasörde açılan cmd'den çalıştırın mp4.py ve klasördeki tüm mp4 birleştirilecek)

import glob
import os

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

Python ile Sürüm 2

Blogumdaki yazımdan alındığında, bunu python'da yapıyorum:

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
Concat protokolü MP4 ile kullanılmamalıdır ve kabul edilen cevapta belirtildiği gibi çalışmaz .
llogan

@LordNeckbeard Çıkış bit hızını belirlerken 2 MP4 videoyu birleştirmekle ilgili bu ffmpeg sorusunun cevabını biliyor musunuz acaba? video.stackexchange.com/q/24569/5657 Teşekkürler.
Ryan

@ LordNeckbeard Tahminimce, cevabınız en iyisi olacaktır, yine de buna hazırsanız! Kendimden özellikle memnun değilim.
Ryan

Sadece (Lord Neckbeard'ın işaret ettiği gibi), birleştirme işleminin başarılı olması için bir .mp4 dosyasını ara .TS formatına dönüştürmek gerekli değildir, ancak belki de daha da kötüsü, bu cevap giriş ihtiyacını gidermeye bile başlamaz eşleşen bit hızı, kare hızı, örnekleme hızı, zaman tabanı ve süreye sahip video dosyaları. Ortak noktası bu faktörlerin hepsini 5 olmadan, dosyalar olamaz (yani kullanarak katıldı birleştirilmelidir stream copy ), ancak yeniden kodlanmış yerine olmalıdır.
Ed999

7

İçin .mp4dosyalar, ben opensource komut satırı aracı kullanmak daha iyi ve daha hızlı çalışır bulundu: mp4box. O zaman bu şekilde kullanabilirsiniz:

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

Çoğu platform için buradan indirin: https://gpac.wp.imt.fr/mp4box/


2
Bu biri için yararlı olabilir, ancak gereksinimi: " Ben ffmpeg kullanarak iki mp4 dosyaları bitiştirmeye çalışıyorum. Bu otomatik bir işlem olması gerekir ". Lütfen tüm soruyu okuyun ve konuyla ilgili bir cevap sağlamaya çalışın.
thvs86

5
Bu cevap tamamen yerinde. Aynı işi yapan bir FOSS aracı. Tıpkı FFmpeg gibi bir komut dosyasında kullanılabilir. İşi FFmpeg cevaplarından daha basit bir şekilde yapar. Ne kadar karmaşık olduklarına bakın! Bunlardan biri FFmpeg'i aramak için Node.js kullanıyor! Delilik. Lütfen wonkism ile durun ve StackOverflow'u tekrar kullanışlı hale getirmeyi deneyin. Bu site senin gibi göz kırpmalar sayesinde eski benliğinin gölgesi. Ayrıca, bu soru sizin gibi bir sakatın aşina olması gereken "XY Sorunu" nun bir örneğidir.
blujay

Mp4box'ın bir FOSS aracı olması önemli değil. Soru, mp4box yerine ffmpeg kullanarak cevaplar istedi.
jramos775

@ thvs86 Bunun bir örneğiyim. Medya için gerçek bir İsviçre bıçağı olduğu için ffmpeg kullanıyorum. Ayrıca, tartışmaların yapısı oldukça karmaşık olabileceğinden (buradaki çeşitli yanıtlarla gösterilmiştir), özel kullanım durumlarım için yardım arıyorum. Bu mp4box hakkında ilk duydum ve bu cevap olmasaydı bulamazdım. Yani benden + 1'leyin ve lütfen, anlamsız İnternet noktaları ve katı kurallar yerine cevap arayan insanlar hakkında daha fazla düşünün.
Pavel

4

İşte birkaç GoPro mp4'leri 720p mp4'e birleştirmek için yaptığım bir komut dosyası. Umarım yardımcı olur.

#!/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}

Bu birleştirme DEĞİLDİR. Bu kod, girdileri birleştirmez, yeniden kodlar. Bu, rastgele video dosyalarını alır ve bunları ortak bir ses ve video bit hızına değiştirir (kaynak dosyaların orijinal bit hızına veya orijinal kare boyutuna bakılmaksızın). O / p, iki dosyayı akış kopyasını kullanarak birleştirmek istedi, onları yeniden kodlamıyordu, bu nedenle sorulan soruya değinmiyor.
Ed999

4

Buradaki belgelerden: https://trac.ffmpeg.org/wiki/Concatenate

MP4 dosyalarınız varsa, bunlar önce MPEG-2 aktarım akışlarına dönüştürülerek kayıpsız bir şekilde birleştirilebilir. H.264 video ve AAC ses ile aşağıdakiler kullanılabilir:

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

Bu yaklaşım tüm platformlarda işe yarar.

Bunu çapraz platform komut dosyasında kapsülleme yeteneğine ihtiyacım vardı, bu yüzden kullandım fluent-ffmpegve aşağıdaki çözümü buldum :

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
Sadece bir yanıt göndermekle kalmaz, aynı zamanda OP ve gelecekteki okuyuculara da çözümü daha iyi anlayan küçük bir açıklama ekleyebilirsiniz.
Balagurunathan Marimuthu

1
Bu, her iki girişin yan yana aynı anda oynatıldığı yeni bir sessiz video oluşturdu. Birleştirme işleminin input_1.mp4'ün oynatıldığı ve daha sonra input_2.mp4
Alexx Roche

3
Bu tamamen yanlış cevaptı. Bu, videoları birleştirmedi, onları @AlexxRoche'nin belirttiği gibi sessizce yan yana oynatıyor.
Kalob Taulien

1

Geçerli dizindeki tüm mp4 dosyalarını birleştirme

Daha sonra silmek zorunda olduğum harici dosya oluşturmayı sevmiyorum, bu yüzden çözümüm dosya numaralandırma listesini içeren takip ediyordu ( 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

Bu kodu Not Defteri'ne kopyaladım ve hiçbir şey olmadı.
7vujy0f0hy

1
@ 7vujy0f0hy bu bir bash kabuklu bir linux üzerinde çalışıyor belki de cygwin ile çalışabilir
Pipo

1

Komut dosyası altındaki çeşitli denemelerden sonra Windows 10 Powershell'de benim için çalıştı.

    $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

Burada ilk iki satır aşağıdaki içeriğe sahip bir temp.txt metin dosyası oluşturur

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

3., 4. satır ffmpeg'in yolda olup olmadığını kontrol eder ve "join.mp4"

Diğer cevaplardan temel farklar aşağıdaki gibidir

usage  of -bsf:v hevc_mp4toannexb -an

yukarıdaki mp4 dosyam çalıştıysa, video kodlamanıza bağlı olarak aşağıdaki gibi diğer alternatifleri kullanmanız gerekebilir.

h264_mp4toannexb

Bu tür olası tüm Bitstream filtreleri https://ffmpeg.org/ffmpeg-bitstream-filters.html adresinde bulunabilir.


Benimki bir CCTV kameradan gelen MP4 idi. Bu komut olmadan konuşma çıktı dosyası oluşturamaz.Web sitesinden en son ffmpeg kullanıyorum.
rahul maindargi

0

Komut ikamesi ve concat video filtresini kullanarak MP4 dosyalarıyla dolu bir dizine katılma yöntemim (bu yeniden kodlayacak) - başka birinin bu tek astardan biraz faydalanacağını düşündüm, özellikle de çok fazla dosyanız varsa tek bir dosyada 17 dosyaya katıldı):

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

Not: Bu komut dosyalarınızı adlandırıldıkları sırayla birleştirir (yani, çalıştırdığınızda sunuldukları sırayla ls *.mp4) - benim durumumda her birinin bir parça numarası vardı, bu yüzden harika çalıştı.


0

Burada açıklanan concat protokolü; https://trac.ffmpeg.org/wiki/Concatenate#protocol

Ara dosyaları önlemek için adlandırılmış kanallar kullanılarak uygulandığında

Çok hızlı (okuma: anlık), hiçbir kare düştü ve iyi çalışıyor.

Adlandırılmış kanal dosyalarını silmeyi ve videonun sadece yapabileceğiniz H264 ve AAC olup olmadığını kontrol etmeyi unutmayın ffmpeg -i filename.mp4(h264 ve aac sözlerini kontrol edin)


-1

Yeniden kullanılabilir PowerShell betiği biçiminde kabul edilen yanıt

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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.