Search code examples
ffmpegvlcv4l2ffprobere-encoding

Re-encoding vlc-created mpeg2 .ts file results in 20 second file; AKA: multi-stream file with hidden streams


I was recording something with vlc off v4l2 (in case that makes a difference), and I just selected the first format that worked, being mpeg2 using TS container. File resulted in .ts extension, as automatically selected by vlc. When I then tried to put the video file in my video editor, it said the video was 19,884 hours long, when it should be about 6 minutes (it is ~80mb in size). When I try to play it in xine, it correctly shows the duration (vlc doesn't), and when I use ffprobe:

[mpegts @ 0x9b2c0a0] max_analyze_duration 5000000 reached at 5000000
Input #0, mpegts, from 'loopbacktestcap.ts':   Duration: N/A, start:
17978.139456, bitrate: N/A   Program 1 
     Stream #0:0[0x44](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30
tbr, 90k tbn, 60 tbc
     Stream #0:1[0x46](): Video: mpeg2video ([2][0][0][0] / 0x0002), 90k tbn

Notice especially this line:

   Duration: N/A, start: 17978.139456, bitrate: N/A   Program 1 

I looked it up and it seems the lack of duration has to do with the container. But I have tried a few things to reencode (I tried -vcodec copy, mpeg2, libx264...) and all I can get is 20 second files of 1.1mb - 1.8mb.

So how can I reencode this file so the duration appears, and I get the full 6 minutes, instead of just the first 20 seconds?


Solution

  • First milestone was reached when I found this link: Map - ffmpeg -- Example #8 which led me to try:

    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts
    

    Yielding the following:

    [mpegts @ 0x9980f40] max_analyze_duration 90000000 reached at 90000000
    Input #0, mpegts, from 'loopbacktestcap.ts':
      Duration: 00:16:00.96, start: 17978.139456, bitrate: 695 kb/s
      Program 1 
        Stream #0:0[0x44](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
        Stream #0:1[0x45](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
        Stream #0:2[0x46](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
    

    Notice that it now gives me the correct duration as well as an extra stream and more info on the second one (which is technically the third one). So then I ran:

    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts  -map 0 -c copy map0.mp4
    

    and that now produced a 79451050 byte file map0.mp4, where my_mpeg2_file.ts is 83499636. I try to play this in vlc, and it shows the duration as 9:12, but if I jog the play position, two more vlc windows are opened and vlc begins to act strange; the video display area is hung, though the playback position indicator continues to progress. This might be just a buggy vlc, but I am stuck at this point. Let me know if anyone sees anything I am missing here.

    xine however cannot play back the new file (where it plays the original and shows that it is 6 minutes long -- actually, the duration counter goes a little nutty as I play the file and changes constantly, so I don't know).

    So, next command I tried was:

    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts  -map 0 -c libx264 map0x264.mp4
    

    Trying to play the resulting file (43652975 bytes, for the curious) led to the same strange behavior in vlc, where now I can see that it is opening a new window for each stream, and playing the stream when it is its "turn" in its respective window, freezing the other display areas of the other windows. Trying to close them stops playback for all and closes the two extra windows. I am guessing keeping all 3 streams in the same file is nonsense.

    SUCCESS!

    Next attempt was:

    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts  -map 0:0 -c copy map0_0.ts
    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts  -map 0:1 -c copy map0_1.ts
    ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts  -map 0:2 -c copy map0_2.ts
    

    which resulted in files of size:

     4912 map0_0.ts
     5372 map0_1.ts
    74728 map0_2.ts
    

    map0_0.ts is 20 seconds long, map0_1.ts is a still image 1:12 long, and map0_2.ts is 9:12. Exactly what I wanted! And my video editor accepts them no problem. SOLVED!