Search code examples
ffmpeghttp-live-streaming

Ffmpeg pkt_pos vs. hls byterange differs


I have a single ts file and created a single-file m3u8 using ffmpeg. It looks like the following

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:1
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:0.000000,
#EXT-X-BYTERANGE:22184@0
video.ts
#EXTINF:1.000667,
#EXT-X-BYTERANGE:713836@22184
video.ts
#EXTINF:1.000667,
#EXT-X-BYTERANGE:549336@736020
video.ts
#EXTINF:1.000667,
#EXT-X-BYTERANGE:568324@1285356
video.ts
#EXTINF:1.000667,
#EXT-X-BYTERANGE:569264@1853680
video.ts
...

The m3u8 file works perfectly but in its creation, ffmpeg re-creates the ts file. I wanted to avoid this and thought I could simply create the m3u8 file myself. I used the following command to get the byte offset of keyframes. However, none of the keyframe locations agrees with the offsets in the m3u8 file.

ffprobe -loglevel error -skip_frame nokey -select_streams v:0 -show_entries frame=pkt_pos -of compact video.m3u8
frame|pkt_pos=22560
frame|pkt_pos=736396
frame|pkt_pos=1285732
...

All of the offsets disagree by 376 bytes. That number is twice the mpeg-ts package size (which is 188). Both locations contains the ASCII character "G" which is the package header for MPEG-TS.

How can I get the correct offset positions using ffprobe that I can use to create an HLS playlist? Does Ffmpeg just subtract 2 packages for safety, is it important?


Solution

  • The package the offset points to is a PAT (Program Association Table), followed by a PMT (Program Mapping Table). Each packet takes 188 bytes which makes a total of 376. After this meta data, the actual keyframe starts.

    In simple cases the m3u8 offset can point to the keyframe directly and the file will play correctly. However, in general cases, it makes sense for the decoder to be given the list of programs right away when seeking into the middle of a transport stream.