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

1k views Asked by At

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?

2

There are 2 answers

0
insaner On BEST ANSWER

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!

5
Mike F On

I had a similar challenge of supporting transport stream (ts) video files in our video processing infrastructure. I used ffmpeg to convert ts into mp4 files with two-pass encoding.

The command(s) in its full length:

Pass 1:

ffmpeg -i camera.ts -filter:v scale=-1:480,setsar=1/1 -pix_fmt yuv420p -threads 0 -r 25/1 -force_fps -c:v libx264 -profile:v baseline -preset slow -x264opts level=3.0:ref=1 -b:v 1000k -maxrate 1000k -bufsize 2000k -s hd480 -c:a libfaac -ar 16000 -ac 2 -ab 128000 -pass 1 -movflags faststart -y video.mp4

Pass 2:

ffmpeg -i camera.ts -filter:v scale=-1:480,setsar=1/1 -pix_fmt yuv420p -threads 0 -r 25/1 -force_fps -c:v libx264 -profile:v baseline -preset slow -x264opts level=3.0:ref=1 -b:v 1000k -maxrate 1000k -bufsize 2000k -s hd480 -c:a libfaac -ar 16000 -ac 2 -ab 128000 -pass 2 -movflags faststart -y video.mp4 >>& ffmpeg.log

I downscale the video to hd480 (852x480) reencoding the video stream with libx264 baseline level 3 with a relatively low bitrate as well as audio with libfaac and moving the moov atom to the beginning of the file for web compatibility (-movflags faststart)

See the FFMpeg documentation for all details on the flags.

Note that I just dug up this command which works for our setup: processing transport stream recordings from IP cameras. You would probably need to specifically adapt resolution and bitrates to your needs. Hope this points you in the right direction.