86

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.

Ciro Santilli OurBigBook.com
  • 26,663
  • 14
  • 108
  • 107
Dhruv Singal
  • 1,101
  • 2
  • 8
  • 13

11 Answers11

80

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
Elder Geek
  • 35,476
  • 25
  • 95
  • 181
Szabolcs Spindler
  • 801
  • 1
  • 6
  • 2
54

You can do it using ffmpeg:

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

reference and more info

Maythux
  • 82,867
  • 54
  • 239
  • 271
  • 5
    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. – Dhruv Singal Jun 16 '15 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 '15 at 05:58
  • You are probably right. This solved the issue: http://askubuntu.com/a/637179/420614 – Dhruv Singal Jun 18 '15 at 04:18
  • 10
    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](http://trac.ffmpeg.org/wiki/Concatenate) instead. – llogan Nov 17 '17 at 18:11
  • I tried ffmpeg with 2 mp4 files of 30min each. I got an output file with length 7 hours. – A.W. Jul 03 '18 at 14:33
  • 3
    Use with formats that support file level concatenation (MPEG-1, MPEG-2 PS, DV). Do not use with MP4. Source: https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg – Platon Efimov Feb 19 '19 at 13:53
39

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
ShaDeRzz
  • 491
  • 4
  • 2
14

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

Dhruv Singal
  • 1,101
  • 2
  • 8
  • 13
7

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.

RawwrBag
  • 169
  • 1
  • 4
  • 3
    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`. – Paddy Landau Jun 14 '18 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. – tisaconundrum Nov 16 '18 at 08:05
4

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
    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 '21 at 22:01
2

LossLessCut works very well for this. Fast and painless.

passerby51
  • 131
  • 2
  • 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 '22 at 21:52
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>
Antonello
  • 719
  • 1
  • 12
  • 25
0

I'd like to throw in my "videomerge" - available for ubuntu via ppa:

Its a QT5 GUI app using drag'n drop. To install:

sudo add-apt-repository ppa:jentiger-moratai/mediatools
sudo apt update
sudo apt install videomerge

As all of my apps, I try to keep the UI very simple:

1

kanehekili
  • 5,846
  • 1
  • 12
  • 32
  • the repository give me a 404 Not Found error. Do you have a github or sourceforge link? – rayzinnz Apr 26 '23 at 19:30
  • You can find it on [github](https://github.com/kanehekili/VideoMerge). What is your ubuntu version? Since that repository still exists.. – kanehekili Apr 28 '23 at 06:42
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}"
derHugo
  • 3,306
  • 5
  • 30
  • 49
Victor Sergienko
  • 546
  • 1
  • 6
  • 19
-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
Maythux
  • 82,867
  • 54
  • 239
  • 271
kos
  • 35,535
  • 13
  • 101
  • 151
  • 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. – Dhruv Singal Jun 16 '15 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 '15 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.. – Ken Mollerup Oct 22 '15 at 14:55
  • 1
    This can't work. – vy32 Feb 29 '20 at 22:08