33

I'm following the documentation on how to concatenate files with ffmpeg but during the process I'm seeing lots of warning and the output video stops after the first chunk but the audio keeps on playing.

This is the command I'm using to concatenate the files:

ffmpeg -f concat -i mylist.txt -c copy output.webm

This are the warnings I'm seeing:

[concat @ 0x7fee11822a00] DTS 0 < 2500 out of order
[webm @ 0x7fee11011000] Non-monotonous DTS in output stream 0:0; previous: 2500, current: 0; changing to 2500. This may result in incorrect timestamps in the output file.

The video files are coming from an external source. My current solution is to re-encode every file separately to mp4 and then to concatenate them together and then to re-encode the complete file back to webm. That, of cause, that takes some significant time but I can't find another solution.

Jason Sundram
  • 12,225
  • 19
  • 71
  • 86
Andy
  • 841
  • 2
  • 8
  • 15

7 Answers7

39

All videos for FFMPEG concatenate should have matching encoding, fps and so on, otherwise you'll get unexpected results. I guess, it's hard to get by without re-encoding if your videos come from different sources. I had to look though lots of solutions, the working ones would suggest converting your videos to the same intermediate format and then running your concat command.

Although such approach does work, it doesn't explain what goes wrong. Gyan's comment answers it.

Firstly, test your input files with ffprobe: ffprobe video1.mp4

You'll get outputs like these.

video1.mp4:

Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 1556 kb/s, 24 fps, 24 tbr, 12288 tbn, 48 tbc (default)

video2.mp4:

Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 6454 kb/s, 24 fps, 24 tbr, 90k tbn, 48 tbc (default)

Even though my FPS and other params were the same, I got 58 sec video with 3.1 fps instead of the expected 8sec @24fps video. The important parameter here is timebase tbn , which is 12288 tbn vs 90k tbn. Concatenate doesn't re-encode the input videos, only the timebase from the first input video is used messing up all subsequent videos.

Change the timebase for the first file:

ffmpeg -i video1.mp4 -video_track_timescale 90000 video1_fixed.mp4

Now concatenate produces the correct result:

( echo file 'video2.mp4' & echo file 'video1_fixed.mp4' ) | ffmpeg -y -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -c copy output.mp4
sr9yar
  • 4,850
  • 5
  • 53
  • 59
  • 2
    You're amazing! Thank you so much! – Dogcat Oct 24 '19 at 13:17
  • 4
    This is the first answer I've seen anywhere on SE that actually explained what was going on well enough for me to diagnose my problem — turned out in my case it was differing audio sample rates, but same principle. – David Moles Jul 21 '20 at 22:02
  • 3
    What to do if `tbc` does not match? – amzon-ex Sep 25 '20 at 08:23
  • This also works for me except when the second video has an inpoint specified when I get the same warnings. Can anything be done with inpoints? – Dzseti Apr 11 '21 at 07:33
  • 1
    I searched a lot and only you gave the answer about 'tbn', which is what I just needed. Thanks. – Catscarlet Mar 21 '22 at 15:14
9

Your issues are caused by the -c copy copy argument. As the name of the argument implies, it will copy the source encoding. Since each file has different timestamps, potentially starting near zero, you will get a lot of warnings. The concat demuxer also requires the same codecs in the input files so make sure they're not mixed.

The solution is to re-encode by specifying the codecs you want to use for your output, eg. -c:v libvpx-vp9 -c:a libopus.

aergistal
  • 29,947
  • 5
  • 70
  • 92
  • 1
    Thanks aergistal. Are you saying to re-encode every file separately or specifying the codecs during the concatenation? – Andy Jul 29 '15 at 23:05
  • 2
    I'm still having the same issue. During the encoding process I'm seeing the warnings and the final file stops after the first chunk. This is the command I'm using: `ffmpeg -f concat -i mylist.txt -c:v libvpx-vp9 -c:a libopus output.webm` – Andy Aug 01 '15 at 23:49
  • What version of ffmpeg are you using? – aergistal Aug 02 '15 at 07:49
  • I followed this guide to install ffmpeg on a Debian system: https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu So it is the latest release snapshot. I could upload the webm files if you would like to reproduce it? – Andy Aug 03 '15 at 02:45
  • Sure, I'll take a look – aergistal Aug 03 '15 at 07:53
  • I'm having a similar problem, but I don't understand how to reencode the source videos or how to select the proper options for that. For example, how would I know if I need `libvpx-vp9` and `libopus` as opposed to something else? – tmoore82 Aug 16 '15 at 21:29
  • @tmoore82 See this: https://en.wikipedia.org/wiki/Comparison_of_video_container_formats – aergistal Aug 17 '15 at 09:20
  • So instead of `copy`, I switched to `-c:v h264 -c:a mp3`, and I don't get the error immediately. It seems to reencode the first video just fine. But once it gets through that point, I get `DTS 3815 < 3812809 out of order`, and then a whole stream of errors along the lines of `cannot use next picture in error concealment`. Full output: http://paste.ubuntu.com/12109447/ – tmoore82 Aug 17 '15 at 16:49
  • Is this solultion lossless? – a06e Jun 03 '18 at 14:55
  • @becko - No, re-encoding is never truly lossless. Incidentally, I suspect the real source of the problems these posters were having lay in their failure to specify the encoding bitrate. They haven't bothered to specify either a video bitrate or an audio bitrate. Nor a video framerate or an audio sample rate. That's just dumb: it's naive to expect that re-encoding will succeed, if you can't be bothered to tell the encoder what common value at which to output your bunch of (potentially) differing inputs. – Ed999 Aug 17 '18 at 22:52
4

After a few days of investigation, I found make the videos have the same fps will solve this problem.

If a.mp4 and b.mp4 have different fps, Update them with 30(custom) fps

ffmpeg -i a.mp4 -vcodec mpeg4 -vf fps=30 a.output.mp4
ffmpeg -i b.mp4 -vcodec mpeg4 -vf fps=30 b.output.mp4

Write video paths into one file

echo "file a.output.mp4" > videos.txt;
echo "file b.output.mp4" > videos.txt;

Contact

ffmpeg -f concat -i videos.txt -c copy final.mp4
iamsk
  • 346
  • 5
  • 7
  • 8
    The issue isn't of framerate, but timebase. If files, even with same framerates but different timebases are muxed, there is a discontinuity of dts/pts values. Generating videos with the same timebase and coincidentally with the same framerate will solve it. – Gyan Jan 21 '16 at 08:51
  • @Mulvya Yes, the ffmpeg error info tell us it's DTS related. but there is no option to change that. Actually I don't know the root reason about this. Is there any other solutions about this and how to generate same timebase video? – iamsk Jan 23 '16 at 08:21
  • 4
    `-video_track_timescale 90000` will generate a file with `90k tbn` This is unrelated to the fps. For a good concat, you need to make sure that all videos have the same `tbn` – Gyan Jan 23 '16 at 08:26
  • Hi, if you solved it, please could you share the full command? – Rami Jun 02 '16 at 01:45
  • 2
    The point is that the reason why 90,000 works as a video timebase is because the three possible frame rates per second (24 fps, 25 fps and 30 fps) are all perfectly divisible into 90,000. Mathematically speaking, 24 x 25 x 30 equals 18,000. Thus any multiple of 18,000 makes a valid timebase (18,000 x 5 = 90,000). You could as well use 18,000 (or 630,000). All you need is an integer perfectly divisible by 24 and by 25 and by 30. – Ed999 Aug 17 '18 at 23:04
  • 2
    It also doesn't hurt that 90,000 is "perfectly" (imperfectly?) divisible by 48,000 (the normal audio sample rate, i.e. 48kHz). In fact, if you divide 90,000 by 48,000 what you get is not actually an integer. You get 1.875 (a fraction, clearly, namely *one and seven-eighths*). But it is, crucially, a "perfect" fraction, one without a remainder. If you try to divide 22 by 7, you will get a string of decimals that - literally - goes on forever. A similarly bad goes-on-forever result occurs if you divide 90,000 by 44,100 (i.e. 44.1kHz), which is why that common audio sample rate is best *avoided*. – Ed999 Aug 18 '18 at 00:22
3

I fixed my issue my not using ffmpeg but mkvtoolnix using the mkvmerge command.

Andy
  • 841
  • 2
  • 8
  • 15
2

The following is a method for solving the "DTS out of order" error when concatenating a group of mp4 video files. It also avoids re-encoding them.

Although you will typically still see the "out of order" error message reported in the console window during processing, the concatenation will nevertheless succeed (and without loss of sync).

Run this code in a batch file. I wrote it on a machine running Windows 7.

::  *** Concatenate .MP4 files : Stream Copy ***

    ::  You can't concatenate .mp4 files. You have to convert them to an
    ::  intermediate format that can be concatenated, such as .mpg:
    ::  
    ::    1. Convert the .mp4 videos to .mpg, using ffmpeg.
    ::    2. Then run a file level concatenation command on
    ::       the .mpg files, to create a combined .mpg file.
    ::    3. Convert the concatenated .mpg file to .mp4,
    ::       using ffmpeg.

    ::  If the mp4 files contain a h264 stream, use the .TS format (MPEG-TS)
    ::  as the intermediate format (instead of .MPG)

    ::  Convert the .MP4 files to intermediate .TS
    ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input1.ts
    ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input2.ts
    ffmpeg -i input3.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input3.ts
    ffmpeg -i input4.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input4.ts
    ffmpeg -i input5.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input5.ts

    ::  MP4 Options
    SET options=-bsf:a aac_adtstoasc -movflags faststart

    ::  Concatenate the TS files & Convert the output back to MP4
    ffmpeg -i "concat:input1.ts|input2.ts|input3.ts|input4.ts|input5.ts" -c copy -video_track_timescale 25 %options% -f mp4 -threads 1 output.mp4



    ::  Report
    echo.  &  ffmpeg  -i input1.mp4 -f nul
    echo.  &  ffmpeg  -i input1.ts  -f nul
    echo.  &  ffmpeg  -i output.mp4 -f nul
Ed999
  • 2,801
  • 2
  • 16
  • 19
  • I had trouble until I changed `ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input1.ts` to `ffmpeg -i input1.mp4 -video_track_timescale 90000 -vf fps=30 -vcodec h264 -bsf:v h264_mp4toannexb -f mpegts input1.ts` and `ffmpeg -i "concat:input1.ts|input2.ts|input3.ts|input4.ts|input5.ts" -c copy -video_track_timescale 25 %options% -f mp4 -threads 1 output.mp4` to `ffmpeg -i "concat:input1.ts|input2.ts|input3.ts|input4.ts|input5.ts" -vcodec copy %options% -f mp4 -threads 1 output.mp4` – hemisphire Jul 19 '18 at 16:36
  • Please explain, which troubles you had. – David Papirov Aug 16 '18 at 15:01
  • I suspect he was attempting to concatenate a bunch of NTSC mp4 video files, that were encoded at 30 frames per second, when I had my script set up to cope with a set of PAL mp4 files running at 25 frames a second. He's changed the -video_track_timescale option from 25 to 90,000 in order to create a script which can cope with a video running at 30 fps (NTSC tv), 25 fps (PAL tv), or 24 fps (motion picture film). – Ed999 Aug 17 '18 at 22:42
  • The reason why 90,000 works as a video timebase is because the three possible frame rates per second (24 fps, 25 fps and 30 fps) are all perfectly divisible into 90,000. Mathematically speaking, 24 x 25 x 30 equals 18,000. Thus any multiple of 18,000 makes a valid timebase (18,000 x 5 = 90,000). You could as well use 18,000 (or 630,000). All you need is an integer perfectly divisible by 24 and by 25 and by 30. – Ed999 Aug 17 '18 at 23:08
  • He's also taken Gyan's point about all the input files needing to have a common tbn, so he's moved the -video_track_timescale option (with his changed value of 90,000) into the first command set, so as to be certain that all the *input* files processed in the final line by the concatenation command do all have 90k (i.e. 90,000) as their tbn (time base number). Whether this is a necessary step depends on what tbn value each of his source files had, before he ran them through my script. But it sounds like they didn't all have the same tbn value (my script had rashly assumed they did). – Ed999 Aug 17 '18 at 23:26
  • I don't have the poster's source video files, so I can't run any useful tests, but my recommendation to anyone in a similar situation is to try, as a first step, using my above script as originally written, but just replace "-video_track_timescale 25" with "-video_track_timescale 90000", before making any more drastic change. The problem with the solution suggested by user hemisphire is that it involves re-encoding all the video files. The whole point of my script is to AVOID re-encoding. We already knew that re-encoding would succeed. I was proposing a better solution, one that is *lossless*. – Ed999 Aug 17 '18 at 23:56
2

The way I solved this was to take the mp4s I wanted to concat and convert them to .ts first before performing the concat.

echo > concat.txt

for filename in file1 file2 file3; do
    ffmpeg -y -i "$filename.mp4" -c:a copy -c:v copy -bsf:v h264_mp4toannexb -f mpegts "$filename.ts"
    echo "$filename.ts" >> concat.txt
done

ffmpeg -y -f concat -i "concat.txt" -c copy "out.mp4"
BallpointBen
  • 9,406
  • 1
  • 32
  • 62
0

listw.txt contains two files each having different frame per second.

Having different fps causing this error.

I solve my problem with below command:

ffmpeg -f concat -safe 0 -f concat -i listw.txt -vcodec libvpx-vp9 output.mp4
Tyler2P
  • 2,324
  • 26
  • 22
  • 31