24

I want to concatenate 2 videos using ffmpeg. I am using:

ffmpeg -i output1.mp4 -scodec copy -vbsf h264_mp4toannexb i0.ts

But the mp4 file I get looks much worse then the source file.

Here is the information about both the files

   Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output1.mp4':
   Metadata:
   major_brand     : isom
   minor_version   : 1
   compatible_brands: isom
   creation_time   : 2013-06-13 15:40:36
   Duration: 00:00:15.72, start: 0.000000, bitrate: 2053 kb/s
   Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720, 1931 kb/s, 25 fps, 25 tbr,   12800 tbn, 50 tbc
   Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 128 kb/s

  Input #0, mpegts, from 'i0.ts':
  Duration: 00:00:15.64, start: 1.400000, bitrate: 1382 kb/s
  Program 1 
  Metadata:
  service_name    : Service01
  service_provider: Libav
  Stream #0.0[0x100]: Video: mpeg2video (Main), yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 104857 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
  Stream #0.1[0x101](und): Audio: mp2, 44100 Hz, stereo, s16, 128 kb/s

How can I solve this problem?

3
  • sorry. Then i concat them with ffmpeg -i "concat:i0.ts|i1.ts" output1111.mp4. But the problem is that the quality is bad already when i make ts-files
    – jenia
    Jun 13, 2013 at 17:34
  • yes, exactly. All are equall
    – jenia
    Jun 13, 2013 at 18:22
  • 1
    See also stackoverflow.com/questions/7333232/…
    – rogerdpack
    Jun 15, 2016 at 9:01

4 Answers 4

43

Consider using the concat demuxer. This way you can avoid creating temporary, lossy intermediate files and skip an extra step of re-encoding.

Note: All inputs must have the same stream types (same formats, same time base, etc.).

  1. Create a text file and include the paths and names of each file to concatenate (or "join"). Example file, input.txt:

    file '/home/jenia/input1.mp4'
    file '/home/jenia/input2.mp4'
    file '/home/jenia/input3.mp4'
    
  2. Now you can use the concat demuxer:

    ffmpeg -f concat -i input.txt -codec copy output.mp4
    

If you do not have this feature, then either your ffmpeg is too old, or you're using a "fake" ffmpeg from the libav fork.

Easy to use static builds are available for Linux, OS X, and Windows via the FFmpeg download page, or you can follow a step-by-step guide to compile ffmpeg.

Also see:

1
  • This is exactly what I wanted and helped me merge 2 .mov files from my iPhone 6. Thanks.
    – Ryan
    Feb 22, 2016 at 18:51
8

The quickest 1-liner would be:

ls Movie\ Part\ * | while read line; do echo file \'$line\'; done | ffmpeg -f concat -i - -c copy output.mp4
2
  • Any chance to get such a 1-onliner for windows command line?
    – PeterCo
    Sep 14, 2016 at 13:20
  • 2
    On Linux I used this oneliner: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv (mkv accepts more codecs than mp4, but you could also try it with mp4). The -safe 0 is for recent ffmpeg versions complaining about Unsafe file name, and the -type f is for only listing files. I added | sort to sort the files alphabetically; because find reads them in order as saved on filesystem. Works also for files with whitespaces.
    – erik
    Dec 2, 2016 at 14:18
0

In answer to erik's request for a Windows one-liner - here is llogan's solution written as such:

(type NUL > input.txt) && (for /F "usebackq delims=" %x in (`dir /B *.mp4`) do echo file '%x' >> input.txt) && (ffmpeg -f concat -i input.txt -codec copy output.mp4)

Which is actually the following 3 commands glued together:

Overwrite any pre-existing input.txt file with an empty file:

type NUL > input.txt

For each file matching *.mp4, append file filename.mp4 to input.txt.

for /F "usebackq delims=" %x in (`dir /B *.mp4`) do echo file '%x' >> input.txt

Finally run FFMPEG as demonstrated in llogan's answer.

ffmpeg -f concat -i input.txt -codec copy output.mp4
0

*/ EDIT

  • You can easily resolve it using this answer from @Gyan
ffmpeg -i "concat:File1.mp4|File2.mp4" -c:v copy -c:a copy  -codec copy .\output.mp4
ffmpeg -i "concat:File_1.mp4|File_2.mp4|File_3.mp4|File_4.mp4|...| File_nn.mp4" -c:v copy -c:a copy -codec copy .\output.mp4

EDIT */


This can be done by one line:

>input.txt (for %x in (*.mp4)do @echo file '%~x') && ffmpeg -safe 0 -f concat -i input.txt -codec copy .\output.mp4

  1. Create/Overwrite file >input.txt with (command block) output

      >input.txt (for %x in (*.mp4)do @echo file '%~x')
    
  2. List all files with name.extension to output with layout file '%~x'

      >input.txt (for %x in (*.mp4)do @echo file '%~x')
    
  3. Only if last (block command) execution return 0 (by operator &&), then run ffmpeg command:

     && ffmpeg -safe 0 -f concat -i input.txt -codec copy .\output.mp4
    
  • You can also work with different drivers/folders:

    >"%temp%\input.txt" (for %x in ("d:\movies\last\*.mp4")do @echo file '%~x') && "c:\ffmepg\bin\ffmpeg.exe" -safe 0 -f concat -i "%temp%\input.txt" -codec copy "d:\movies\last\concat\output.mp4"
    
0

You must log in to answer this question.