Linuxでmp4ファイルに参加する


31

2つのmp4ファイルを結合して、1つのファイルを作成したいです。ビデオストリームはh264でエンコードされ、オーディオはaacでエンコードされます。計算上の理由により、ビデオを別の形式に再エンコードできません。また、GUIプログラムを使用できません。すべての処理はLinuxコマンドラインユーティリティで実行する必要があります。FFmpegはmpeg4ファイルに対してこれを行うことができないため、代わりにMP4Boxを使用しました。

MP4Box -add video1.mp4 -cat video2.mp4 newvideo.mp4

残念ながら、音声はすべて混同されます。問題はオーディオがaacにあることだと思ったので、mp3でトランスコードし、再びMP4Boxを使用しました。この場合、音声は前半newvideo.mp4(に対応video1.mp4)で問題ありませんが、音声がなく、ビデオでもナビゲートできません。

私の次の考えは、オーディオストリームとビデオストリームの長さに若干の不一致があり、修正する必要があることです。そのため、入力ビデオごとにビデオストリームとオーディオストリームを分割し、FFmpegの-shortestオプションで結合しました。

したがって、私が最初に実行したビデオの場合:

 avconv -y -i video1.mp4 -c copy -map 0:0 videostream1.mp4
 avconv -y -i video1.mp4 -c copy -map 0:1 audiostream1.m4a
 avconv -y -i videostream1.mp4 -i audiostream1.m4a  -c copy -shortest  video1_aligned.mp4

2番目のビデオについても同様に、以前と同様にMP4Boxを使用しました。残念ながら、これも機能しませんでした。私が唯一成功したのは、ビデオストリーム(videostream1.mp4とvideostream2.mp4)とオーディオストリーム(audiostream1.m4aとaudiostream2.m4a)を別々に結合し、最終ファイルのビデオとオーディオを結合したときでした。ただし、ビデオの後半の同期は失われます。具体的には、オーディオとビデオには1秒の遅延があります。どんな提案も大歓迎です。


「FFmpegはmpeg4ファイルに対してこれを行うことができないので、代わりにMP4Boxを使用しました」とは、MP4ファイルを意味しますか?オーディオビデオストリームの両方で同じエンコードパラメーター(幅、高さ、SPS、PPS、フレームレート、サンプリングレート、チャネル数を使用していますか?

ffprobeを使用すると、オーディオストリームの属性が同じであることがわかります。ビデオストリームのサイズは同じですが、レートが異なります。最初のビデオの場合ビデオ:h264、720x592、277 kb / s、PAR 18944:12915 DAR 512:287、24.97 fps、45k tbr、90k tbn、90k tbc 2番目のビデオの場合:h264、720x592、226 kb / s、 PAR 481:330 DAR 39:22、24.91 fps、45k tbr、90k tbn、90k tbc。これが私の問題の原因だと思いますか?

MP4は、異なるビデオ用の異なるトラックを使用して、異なる特性を持つビデオ/オーディオの結合をサポートしますが、プレーヤーはそれほどスマートではありません。
rajneesh


あなたの質問はffmpeg FAQですでに回答されています:ffmpeg.org/faq.html#How-can-I-join-video-files_003f
Palec

回答:


31

現在これを行う最良の方法は、concat demuxerを使用することです。まず、inputs.txtformatted というファイルを次のように作成します。

file '/path/to/input1.mp4'
file '/path/to/input2.mp4'
file '/path/to/input3.mp4'

次に、次のffmpegコマンドを実行します。

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

FAQの連結ffmpegも参照してください


ffmpegの古いバージョンを使用している人の利益のために、ここでは以下を保持しています。

ffmpegの最新バージョンではこれを行うことができます:最初にファイルをmpegトランスポートストリームにリマックスする必要があります(コンテナー形式を変更するだけなので、かなりプロセッサライトです)。

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

h264に関するエラーが発生する場合は、次を使用する必要があります。

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

入力ファイルごとに個別にこれを行う必要があります。ファイルを連結するには、次を使用します。

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy output.mp4

それがaacに関するエラーをスローする場合、使用する必要があるかもしれません

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy -absf aac_adtstoasc output.mp4

システムが名前付きパイプをサポートしている場合、中間ファイルを作成せずにこれを行うことができます。

mkfifo temp0 temp1

3つの個別の仮想端末で次のことを行う必要があります。

ffmpeg -i input0.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp0
ffmpeg -i input1.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp1
ffmpeg -f mpegts -i "concat:temp0|temp1" -c copy -absf aac_adtstoasc output.mp4

output.mp4が既に存在する場合、3番目のffmpegは上書きするかどうかを尋ねますが、FIFOアクセスした後にこれを行います。これにより、ffmpegの1番目が閉じられます。したがって、出力ファイルには未使用の名前を選択してください。

入力ファイルが異なる場合、これは機能しない可能性があります。ビットレートの違いは問題ないと思いますが、フレームサイズ、フレームレートなどを一致させる必要があります。


多くのthx仲間、魅力のように働いた
ホセアルマンド

2
@DaveJarvisそうではありません。これはlibavチームによって意図的かつ悪意を持って広められたメッセージです。彼らはffmpegプロジェクトから分裂してavconvを開発する(そしてffmpeg名の著作権を確保できなかったために名前を変更した)開発者集団です。参照してください誰が私にffmpegの、のLibav、とはavconvの違いと関係を伝えることができますか?もう少し情報が必要です。
evilsoup

2
*** THIS PROGRAM IS DEPRECATED *** This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.ランニングで今見ているメッセージですffmpeg
ロード・ロー

@LordLoh。以前のコメントのリンクを参照してください。
evilsoup 14

1
その答えは答えではありません-mp4を連結する方法avconv
ロード・ロー。

7

mp4の場合、私が見つけた唯一の有効なソリューションは、gpacパッケージのMP4Boxでした。

#!/bin/bash
filesList=""
for file in $(ls *.mp4|sort -n);do
    filesList="$filesList -cat $file"
done
MP4Box $filesList -new merged_files_$(date +%Y%m%d_%H%M%S).mp4

またはコマンドは

MP4Box -cat file1.mp4 -cat file2.mp4 -new mergedFile.mp4

mencoderとavconvでは、動作させることができませんでした:-(


2

スクリプトdvoをありがとう。それは私にとって素晴らしい出発点でした。名前付きパイプを使用しても問題はなかったため、代わりに使用するようにスクリプトを調整しました。さらに、スペースを含むファイル名で動作するように修正しました。名前付きパイプへの出力は、読み取りを開始するまで「進行」しないため、avconvの最後の呼び出しの前に、&で最初のremuxタスクをバックグラウンドにする必要があります。さらに、-c copyを使用することを忘れないでください。さもないと、全体が再エンコードされてしまいます。

#!/bin/bash
for FILE in "$@"; do
   TAG=$(echo "$FILE" | sed -e s/[^A-Za-z0-9.]/_/g)
   mkfifo $TAG.mp4concatpipe
   avconv -loglevel "quiet" -i "$FILE"  -f mpegts -c copy -bsf h264_mp4toannexb -y $TAG.mp4concatpipe &
   IN=$IN\|$TAG.fifo
done

IN=${IN#\|}
avconv -i concat:$IN -c copy out.mp4
rm *.mp4concatpipe

何らかの理由で、これは「concat:first.m4v.fifo | second.m4v.fifo:No such file or directory」エラーを示しています。引用符(-i concat: "$ IN"または-i "concat: $ IN ")。ただし、以下の他の回答で提案されているMP4Boxは素晴らしい機能です!
vorburger

2

Mac(macOS 10.13 High Sierra)では、次を使用して成功しました。

for f in *.m4a; do echo "file '$f'" >> mylist.txt; done

必要に応じて、上記と同様に並べ替えます(./が削除されたことに注意してください-パスにより、ffmpegが安全でないファイル名エラーをスローしていました)。

次に、デフォルトのMacPorts ffmpegに指定されているコーデックとビットレートを削除して、それを気に入った:

ffmpeg -f concat -i mylist.txt  output.m4a

スーパーユーザーへようこそ!、質問を注意深くお読みください。あなたの答えは、Linuxに関する最初の質問には答えません。Linuxで動作すると思われる場合は、今後の読者が明確な理解を得ることができるように追加してください。数分を取り、お読みください: - superuser.com/helpは .Answering:superuser.com/help/how-to-answerを
mic84

2

ワンライナーを使用すると、非常に簡単になります。最終的に1つの結果のビデオファイルを提供するために必要なすべてを実行します。乾杯!

find *.mp4 | sed 's:\ :\\\ :g'| sed 's/^/file /' > list.txt; ffmpeg -f concat -i list.txt -c copy output.mp4; rm list.txts

1

evilsoupに感謝します。これは、より新しいを使用してプロセスを自動化する小さなスクリプトavconvです。
ところで、名前付きパイプは私には機能しませんでした(それらへの出力がスタックしました)。

   #!/bin/bash

    for FILE in $@; do
      avconv -i $FILE -map 0 -f mpegts -bsf h264_mp4toannexb -c:v copy -y $FILE.tmp
      IN=$IN\|$FILE.tmp
    done

    IN=${IN#\|}
    avconv -i concat:"$IN" out.mp4

    for FILE in $@; do
      rm $FILE.tmp
    done

0

で大成功を収めました

for f in ./*.m4a; do echo "file '$f'" >> mylist.txt; done

mylist.txtを少し並べ替える必要がある場合があります

ffmpeg -f concat -i mylist.txt -c:a libfdk_aac -b:a 128k output.m4a

ffmpegバージョン2.2.3

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.