76

I want to merge videos in batch size of twenty (20) each. I'm running a Linux machine. The videos are in mp4 format and moderate quality. Some even have the audio stream missing. So far I've tried ffmpeg, mencoder, cvlc/vlc and MP4Box. I want to write a command line script to achieve this, since I'm doing batch processing.

The main issue is that some of the solutions I tried work well for two videos, some work well for videos with audio stream and yet others work well for some other subset of my video set. However, I have not been able to find a comprehensive solution for this task.

6
  • 3
    Please don't ask same question in multi SE sites: superuser.com/questions/928548/…
    – Maythux
    Jun 16, 2015 at 10:25
  • Could you post specifically what you've tried so far?
    – ohaal
    Jun 16, 2015 at 14:18
  • 1
    @ohaal I tried using various concatenation methods given in ffmpeg, including filters and file protocols. I also tried using the concat feature of cvlc/vlc. I also tried the concat feature of mencoder. All of these worked partially. This finally helped me solve the matter. Jun 18, 2015 at 4:25
  • Yes, you already mentioned the tools, what I meant was the actual commands you ran. Also it would be great if you could include the command that ended up solving it for you (in your answer), for future visitors.
    – ohaal
    Jun 18, 2015 at 7:18
  • Aah, I see your point. Unfortunately, I can't list the commands due to the sheer number. The command which solved my problem was this melt {input-sequence} -consumer avformat:{output-name} acodec=libmp3lame vcodec=libx264 Jun 19, 2015 at 7:14

10 Answers 10

74

I am using mkvmerge to join multiple MP4 files into single one:

mkvmerge -o outfile.mkv infile_01.mp4 \+ infile_02.mp4 \+ infile_03.mp4
5
  • 6
    It is better to use the extension .mkv for the output file, as it is a Matroska container irrespective of what extension you give.
    – haridsv
    Sep 17, 2017 at 7:27
  • 3
    Here's how to install mkvmerge: tipsonubuntu.com
    – Morgoth
    Jan 31, 2018 at 9:54
  • 3
    Only this command mkvmerge works. All ffmpeg ones fail with shifted audio at least.
    – 42n4
    Sep 22, 2019 at 11:39
  • 4
    To install mkvmerge do sudo apt install mkvtoolnix
    – bomben
    Mar 10, 2021 at 10:48
  • This is simple and fast way to merge two .mkv files.
    – EsmaeelE
    Apr 15 at 18:24
47

You can do it using ffmpeg:

ffmpeg -i concat:"input1.mp4|input2.mp4" output.mp4

reference and more info

6
  • 4
    I tried doing that. The issue with this is that it doesn't give a proper out. 1. The audio tracks are muddled. 2. There is some disturbance in the video track. Jun 16, 2015 at 11:26
  • I used it for more than sample, the result is high quality, maybe your source video quality is the problem?
    – Maythux
    Jun 17, 2015 at 5:58
  • You are probably right. This solved the issue: askubuntu.com/a/637179/420614 Jun 18, 2015 at 4:18
  • 9
    Don't use the concat protocol to concatenate MP4. It only works with certain formats that most general users don't encounter. Use concat demuxer or concat filter instead.
    – llogan
    Nov 17, 2017 at 18:11
  • 2
    Use with formats that support file level concatenation (MPEG-1, MPEG-2 PS, DV). Do not use with MP4. Source: stackoverflow.com/questions/7333232/… Feb 19, 2019 at 13:53
32

Create a file files.txt with all the files you want to have concatenated in the following form (lines starting with a # are ignored):

# this is a comment
file 'file1.mp4'
file '/path/to/file2.mp4'
file 'file3.mp4'

Note that these can be either relative or absolute paths. Then you can stream copy or re-encode your files:

ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4
5
  • -safe 0 worked for me Apr 9, 2021 at 8:46
  • For those having issues merging vids with different widths.. this solution works fine... Apr 23, 2021 at 5:44
  • Is it possible to specify in the same files multiple outputs, eg file 'fileA1. mp4' 'A.mp4', 'fileA2. mp4' 'A.mp4', file 'B1.mp4' 'B.mp4', etc ?
    – Antonello
    Aug 24, 2021 at 15:39
  • Life saver alert!
    – Chetan
    Nov 19, 2021 at 5:42
  • this ended up working for me but I had to make both the inputs and the output .mkv for it to function. .mp4 would bork the audio.
    – tatsu
    Apr 1 at 0:22
12

This solved the matter: https://stackoverflow.com/a/22324018/5014767

melt is a great command line utility for this. Here is the page

Edit from comments: The command which solved my problem was this melt {input-sequence} -consumer avformat:{output-name} acodec=libmp3lame vcodec=libx264

6

I wrote a little shell script to concat MP4s without transcoding using ffmpeg.

for f in $(ls *.MP4); do
    ffmpeg -i $f -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts
done

CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g")

ffmpeg -i "concat:$CONCAT" -c copy -bsf:a aac_adtstoasc output.mp4

rm *.ts

This creates intermediate files in an MPEG container and then concatenates them into an MP4.

2
  • 2
    It's important to note that this script will fail if any of the filenames contain spaces or, in some cases, special characters. For the loop, it's significantly better to use just for f in *.MP4 without using ls. (You should always avoid using ls in scripts for a couple of important reasons; there are better options.) Also, use quotes for variables unless you are certain that there are no spaces or other special characters, so "${f}" (or just "$f") instead of unquoted $f. Jun 14, 2018 at 14:11
  • CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g") doesn't work well with file names that are 1, 2, 3... 10... 20. It ends up parsing them as 1, 10... 2, 20... etc. I suggest CONCAT=$(echo $(ls -v *.ts) | sed -e "s/ /|/g") this will ensure order. Nov 16, 2018 at 8:05
3

I wrote a wrapper around ffmpeg called vidmerger 🎞, which makes it very easy to merge multiple videos inside a folder, for instance to merge all mp4 files inside the current directory, just run:

vidmerger .
1
  • 1
    Works like a charm, built in Rust! I opted to just cargo build --release directly from the repo as I needed to use the -safe 0 option on ffmpeg
    – Cameron
    Mar 26, 2021 at 22:01
2

LossLessCut works very well for this. Fast and painless.

1
  • I use losslesscut but the result video only working right for firsty 5 minutes. After that images and sound get lagged.
    – Nam G VU
    May 12 at 21:52
0

My script, purely in bash and ffmpeg. Re-encodes files given on a command line into one.

Requires the files to be of the same resolution. Accepts different metadata rotation, which ffmpeg concat: doesn't.

rm ffmpeg-concat-output.mkv

FILE_COUNT=$#
INPUTS=""
FILTER=""
INDEX=0
for FNAME in $@; do
    echo "Processing ${FNAME}"
    INPUTS="${INPUTS} -i $FNAME"

    if [ -z "${FILTER}" ]; then
        FILTER="[$INDEX:v:0] [$INDEX:a:0]"
    else
        FILTER="${FILTER} [$INDEX:v:0] [$INDEX:a:0]"
    fi
    let INDEX+=1
done

COMMAND="ffmpeg ${INPUTS} \
    -filter_complex '${FILTER} \
        concat=n=${INDEX}:v=1:a=1 [v] [a]' \
    -map '[v]' -map '[a]' \
    ffmpeg-concat-output.mkv"

#   -af 'volume=15dB' # won't work with -filter_complex

bash -c "${COMMAND}"
0

I created a Python script that, using moviepy, can concatenate also subsegments (useful if you want for example remove some parts from a video).

Use it with:

vcat -i inputfile1,inputfile2[start-end],... -o <outputfile>
-2

In addition to Maythux's answer, from :

A few multimedia containers (MPEG-1, MPEG-2 PS, DV) allow one to concatenate video by merely concatenating the files containing them.

I.e. the videos to be concatenated use one of the abovementioned video containers (to which I'll add MPEG-4 Part 14 for personal experience), you could simply:

cat video1.ext video2.ext video3.ext > video4.ext
4
  • 2
    I tried this but it only returns the first video as the output. I read somewhere that it doesn't work, though I don't remember the rationale behind this. Jun 16, 2015 at 11:28
  • @DhruvSingal Yes, I can confirm this, I've tried this on two MP4 videos with the exact same video / audio encoding and as you I could only browse through the first video. Which seems reasonable, however I'm pretty sure that I've done this before once with a couple of MP4 videos. Perhaps the memory isn't serving well here, or there are other requirements for this to work. I want to research on this since I'm interested also, if I find something I'll update the answer and drop you a comment
    – kos
    Jun 16, 2015 at 11:45
  • We somehow need to change the metadata at the start of the first video to encompass the entire length of the combined movie, and other stuff probably. Only a few mpeg4 files let me see the metadata.. Oct 22, 2015 at 14:55
  • 1
    This can't work.
    – vy32
    Feb 29, 2020 at 22:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.