FFmpeg - Transcode each segment individually

7

1

I am trying to split a video into GOPs(not fixed sizes), and transcode each part of the video(GOP) individually. I am trying to use HLS(HTTP Streaming Protocol), therefore these chunks of video are MPEG2-TS(.ts).

It seems that splitting the video is working fine, I create the manifest(.m3u8) file and it runs fine on VLC for example. However, after transcoding the video, it seems to create a problem on the segment transition, some kind of delay(gray screen).

Here is the command I am using to segment the video

ffmpeg.exe -i videotest.mp4 -vcodec copy -reset_timestamps 1 -map 0 -hls_list_size 0  out.m3u8

This command segments the video in 10 parts(.ts files) and generates the manifest file(.m3u8)

This is the output:

ffmpeg version N-81045-g450cf40 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.4.0 (GCC)
configuration: --disable-static --enable-shared --enable-gpl --enable-
version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-
nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-
fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-
libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-
libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-
libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-
libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-
librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr -
-enable-libspeex --enable-libtheora --enable-libtwolame --enable-
libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx
--enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 
--enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --
enable-decklink --enable-zlib
libavutil      55. 28.100 / 55. 28.100
libavcodec     57. 50.100 / 57. 50.100
libavformat    57. 42.100 / 57. 42.100
libavdevice    57.  0.102 / 57.  0.102
libavfilter     6. 47.100 /  6. 47.100
libswscale      4.  1.100 /  4.  1.100
libswresample   2.  1.100 /  2.  1.100
libpostproc    54.  0.100 / 54.  0.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'videotest.mp4':
 Metadata:
   major_brand     : mp42
   minor_version   : 512
   compatible_brands: isomiso2avc1mp41
   creation_time   : 2015-09-03 15:02:55
   title           : Fantastic Four: Rise of the Silver Surfer - Theatrical Trailer
   artist          : 20th Century Fox
   date            : 2007
   encoder         : HandBrake 0.10.2 2015061100
   genre           : Trailer
 Duration: 00:00:25.07, start: 0.000000, bitrate: 1884 kb/s
   Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x544 [SAR 1:1 DAR 40:17], 1742 kb/s, 23.90 fps, 23.98 tbr, 90k tbn, 180k tbc (default)
  Metadata:
    creation_time   : 2015-09-03 15:02:55
    handler_name    : VideoHandler
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 135 kb/s (default)
  Metadata:
    creation_time   : 2015-09-03 15:02:55
    handler_name    : Stereo
[hls @ 000000000127c340] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
  Last message repeated 1 times
Output #0, hls, to 'out.m3u8':
  Metadata:
    major_brand     : mp42
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    genre           : Trailer
    title           : Fantastic Four: Rise of the Silver Surfer - Theatrical Trailer
    artist          : 20th Century Fox
    date            : 2007
    encoder         : Lavf57.42.100
    Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x544 [SAR 1:1 DAR 40:17], q=2-31, 1742 kb/s, 23.90 fps, 23.98 tbr, 90k tbn, 90k tbc (default)
    Metadata:
      creation_time   : 2015-09-03 15:02:55
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2015-09-03 15:02:55
      handler_name    : Stereo
      encoder         : Lavc57.50.100 aac
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored bitrate=N/A speed=29.3x    
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
frame=  599 fps=0.0 q=-1.0 Lsize=N/A time=00:00:25.02 bitrate=N/A speed=  29x    

video:5333kB audio:314kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[aac @ 000000000127f620] Qavg: 17473.217

So far, if I run the m3u8 file, it works fine.

Here is the command I am using to encode each segment of the video

ffmpeg.exe -i segment0.ts -vcodec libx264 -s 640:480 -map 0 outputEncoded0.ts

I am running this command for each segment using a script:

#/bin/bash

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for file in /home/pi/Desktop/videoExamples/videosTranscode/*;
    do 
    echo "doing stuff"

    filename="${file##*/}"

    filename="${filename%.*}"


    ffmpeg.exe -i $file -vcodec libx264 -s 640:480 -map 0 $filename.ts

done

IFS=SAVEIFS

Here is the output

ffmpeg version N-81045-g450cf40 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.4.0 (GCC)
configuration: --disable-static --enable-shared --enable-gpl --enable-
version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-
nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-
fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-
libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-
libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-
libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-
libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-
librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr -
-enable-libspeex --enable-libtheora --enable-libtwolame --enable-
libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx 
--enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 
--enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --
enable-decklink --enable-zlib
libavutil      55. 28.100 / 55. 28.100
libavcodec     57. 50.100 / 57. 50.100
libavformat    57. 42.100 / 57. 42.100
libavdevice    57.  0.102 / 57.  0.102
libavfilter     6. 47.100 /  6. 47.100
libswscale      4.  1.100 /  4.  1.100
libswresample   2.  1.100 /  2.  1.100
libpostproc    54.  0.100 / 54.  0.100
Input #0, mpegts, from 'out0.ts':
  Duration: 00:00:05.69, start: 1.503789, bitrate: 215 kb/s
  Program 1 
    Metadata:
      service_name    : Fantastic Four: Rise of the Silver Surfer - Theatrical Trailer
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B),     yuv420p(tv, bt709), 1280x544 [SAR 1:1 DAR 40:17], 23.98 tbr, 90k tbn, 180k tbc
    Stream #0:1[0x101]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 11 kb/s
fixme:msvcrt:MSVCRT__wsopen_s : pmode 0x01b6 ignored
[libx264 @ 0000000001244ae0] using SAR=30/17
[libx264 @ 0000000001244ae0] using cpu capabilities: MMX2 SSE2Fast     SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[libx264 @ 0000000001244ae0] profile High, level 3.0
[mpegts @ 00000000012433e0] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
    Last message repeated 1 times
Output #0, mpegts, to 'outputEncoded0.ts':
  Metadata:
    encoder         : Lavf57.42.100
    Stream #0:0: Video: h264 (libx264), yuv420p, 640x480 [SAR 30:17     DAR 40:17], q=-1--1, 23.98 fps, 90k tbn, 23.98 tbc
    Metadata:
      encoder         : Lavc57.50.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1: Audio: mp2, 48000 Hz, stereo, s16, 384 kb/s
    Metadata:
      encoder         : Lavc57.50.100 mp2
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> mp2 (native))
Press [q] to stop, [?] for help
frame=  116 fps=0.0 q=28.0 size=     174kB time=00:00:04.90 bitrate=     291.0kbits/frame=  135 fps=0.0 q=-1.0 Lsize=     344kB time=00:00:05.60 bitrate= 503.0kbits/s speed=7.82x    
video:28kB audio:263kB subtitle:0kB other streams:0kB global     headers:0kB muxing overhead: 18.113007%
[libx264 @ 0000000001244ae0] frame I:1     Avg QP:15.64  size: 16539
[libx264 @ 0000000001244ae0] frame P:36    Avg QP:13.14  size:   201
[libx264 @ 0000000001244ae0] frame B:98    Avg QP:18.22  size:    52
[libx264 @ 0000000001244ae0] consecutive B-frames:  3.0%  0.0%  2.2%     94.8%
[libx264 @ 0000000001244ae0] mb I  I16..4: 21.8% 65.8% 12.3%
[libx264 @ 0000000001244ae0] mb P  I16..4:  0.7%  1.9%  0.0%  P16..4:      2.1%  0.2%  0.1%  0.0%  0.0%    skip:95.0%
[libx264 @ 0000000001244ae0] mb B  I16..4:  0.0%  0.2%  0.0%  B16..8:  1.7%  0.0%  0.0%  direct: 0.0%  skip:98.1%  L0:47.1% L1:52.9% BI: 0.0%
[libx264 @ 0000000001244ae0] 8x8 transform intra:71.6% inter:84.1%
[libx264 @ 0000000001244ae0] coded y,uvDC,uvAC intra: 17.1% 18.0% 7.8% inter: 0.1% 0.1% 0.0%
[libx264 @ 0000000001244ae0] i16 v,h,dc,p: 61% 33%  4%  2%
[libx264 @ 0000000001244ae0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 47%  9% 41%  1%  0%  1%  0%  1%  1%
[libx264 @ 0000000001244ae0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 51% 20%  5%  2%  3%  4%  4%  3%  7%
[libx264 @ 0000000001244ae0] i8c dc,h,v,p: 81% 10%  9%  1%
[libx264 @ 0000000001244ae0] Weighted P-Frames: Y:5.6% UV:5.6%
[libx264 @ 0000000001244ae0] ref P L0: 79.4%  1.1% 12.6%  6.9%
[libx264 @ 0000000001244ae0] ref B L0: 52.6% 40.8%  6.6%
[libx264 @ 0000000001244ae0] ref B L1: 84.0% 16.0%
[libx264 @ 0000000001244ae0] kb/s:40.72    

The error presented is a delay on the transition from one segment to the next. There is also another error, that happens sometimes, the first segment plays fine, but when the second segment starts, it plays really fast, and all the other segments seem to play at the same time.

Here are the files I used and created for this example, along with the original video and the manifest created: https://drive.google.com/open?id=0B2kwpgNH6c0AMy0zemxuUk84clU

I am new to FFmpeg, and also to the forum, so if I did anything wrong, please tell me.

Would anyone be able to help me with that?

Mateus Souza

Posted 2016-08-04T15:58:12.993

Reputation: 121

Are you using Windows binaries on Linux using Wine? If so, try with native binaries.

– Gyan – 2016-08-04T16:16:35.743

Yes, would that be a problem in any way? I downloaded the native binaries, but it seems to generate the same problem on the playback. – Mateus Souza – 2016-08-04T19:12:25.437

I couldn't try this yet, but my assumption is that the timestamps of the segments are getting completely reset once you encode them again, whereas in the original segments, they would monotonically increase, e.g. with segment 1 starting at 00:00:00.000, segment 2 starting at 00:00:02.000, etc. Perhaps this is causing playback problems? I'll see and have a look tomorrow. (Good question, by the way, you added all the necessary details!) – slhck – 2016-08-04T20:00:43.493

As I assumed, the duration of your individual .ts files changes after encoding. The number of frames is the same, but the timestamps are different. Thus, the original M3U8 file you're using isn't suitable for playing back the new files. You'd have to generate a new M3U8 file based on the transcoded files. I'm pretty sure ffmpeg can't do that, as it always segments and creates the M3U8 file, but I could be wrong. – slhck – 2016-08-05T12:27:15.643

Yeah, it seems that the segment starting time is being changed to 1:48 seconds, and that is the reason. I found this ticket : https://trac.ffmpeg.org/ticket/4037 , the problem seems to be the same, but they didn't seem to provide a solution.

– Mateus Souza – 2016-08-05T18:51:35.577

I understand the reasoning that re-encoding individual segments is probably not a typical use case and that you should rather provide different encodings of the original, then segment. So, as suggested, taking the original M3U8 file as input, then re-encoding the entire stream and segmenting again may be a solution – I'm surprised that apparently does not work either. But I cannot test it now with a latest build of ffmpeg. Have you tried this with your stream? (Btw: Please write @slhck in comments, otherwise I will not get a notification, thanks!) – slhck – 2016-08-06T10:45:26.863

Answers

5

I found a solution to the problem.

FFmpeg has a flag(copyts), which according to the documentation: "Do not process input timestamp, but keep their values trying to sanitize them".

This flag solves the problem I described on the post, allowing the fragments transition to be normal .

However, the splitting and transcoding process, generates a delay(0.7 seconds) on the frame's Play Time Seconds. Surprisingly, when we are dealing with .ts files,this delay is doubled, which means the first frame will have a 1.4 seconds delay to play.

More information here: https://stackoverflow.com/questions/29527882/ffmpeg-copyts-to-preserve-timestamp?answertab=active#tab-top

The solution to this problem is also using another property (muxdelay), that sets the maximum demux-decode delay. If we set this property to 0, the 0.7 seconds delay no longer exists.

Which means my commands now look like this:

Splitting:

ffmpeg.exe -i $inputVideo -vcodec copy -acodec copy -f segment -muxdelay 0 -segment_list out.m3u8 out%d.ts

Transcoding

ffmpeg -i $segmentInput -vcodec libx264 -acodec copy -s 640:480 -copyts -muxdelay 0 $outputFilename.ts

For some reason, the segmenting is still generating a really small delay(I tested with 2 small videos(30 sec and 2min) and the delay was 0.08-0.1 seconds, I am not sure why this is happening, and I can't go after this right now. If anyone finds the reason, please send me a message or answer here(I don't know if that is allowed).

Anyway, this solved the posted question, I hope I have helped.

Mateus Souza

Posted 2016-08-04T15:58:12.993

Reputation: 121

Does anybody know about remaining delay of 0.08-0.1 seconds, despite "-muxdelay 0" option? I'm suffering this with version 4.1. – Patricio – 2019-04-16T18:24:05.377

@Patricio try using the combination -muxdelay 0 -muxdelay 0 and report back. – 林正浩 – 2019-09-08T14:36:13.513