How to create byte-range m3u8 playlist for HLS?

2020-05-19 02:22发布

问题:

Apple gives an example of support for byte-range segments in m3u8 files for HLS

#EXTM3U
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-VERSION:4
#EXTINF:10.0,
#EXT-X-BYTERANGE:75232@0
media.ts
#EXTINF:10.0,
#EXT-X-BYTERANGE:82112@752321
media.ts 
#EXTINF:10.0, 
#EXT-X-BYTERANGE:69864
media.ts

But I cannot figure out how to create such playlist for given .ts file. Are there any tools for that?

回答1:

There is -hls_flags as a ffmpeg option. (https://www.ffmpeg.org/ffmpeg-formats.html)

Following command generates single ts file which is segmented by byte range feature(supported from HLS version 4) in m3u8 index file.

$ ffmpeg -i sample.mp3 -hls_time 20 -hls_flags single_file out.m3u8


回答2:

Looks like

ffprobe -show_frames media.ts -print_format json

gives enough information about frames to build such playlist, although some scripting will be required to construct it.

I'll update this answer with script if I succeed with that approach.

Update:

Here is couple of useful links I've found by now:

Bash scripts for generating iframe playlists - needs a bit of optimization, as it calls ffprobe multiple times

iframe-playlist-generator - project on python that can be used to generate iframe playlists from usual ones

It is not exactly what I've searched initially, but I-Frame playlists are similar to byte-range ones and fit for my task even better, so I'm going to use these two projects as a reference/starting point to create something a bit more suitable for me.

The projects actually use different methods to find size of I-Frame - the bash script just uses what ffprobe shows in pkt_size, and the python project adds a bit of voodoo by calculating size as difference of positions of packets and adding 188 to match example playlists from apple. 188 bytes is the size of mpeg-ts packet, probably that is related somehow, I have not managed to understand how, however. This difference in size calculation causes different playlists to be generated, probably one of them is incorrect in some way, but actually VLC plays both without any problems, so I'm going to stick to simpler method until it will be proven as incorrect.

Update 2:

I've created a ruby module that can extract I-Frame information of given .ts file with ffprobe and build both I-Frame and usual byterange m3u8 playlist (as it was requested in question) based on that information.

I've found the simple method of creating I-Frame playlist I mentioned before to be incorrect, so I used the method from iframe-playlist-generator. The output is almost similar to the I-Frame playlist generated by mediafilesegmenter -output-single-file -file-base output-dir/ input.ts, mentioned by Duvrai, but sometimes there are some 188-byte size misses for random frames, I could not understand the pattern, so it is currently ignored.



回答3:

You can use a standard segmenter such as Apple's mediafilesegmenter, check the lengths of the files, and then concatenate (with the cat program) them into a single file. From the file sizes you have all the information needed to specify the byte ranges in a playlist file.

Not as nice as just downloading a tool from the net, but it's not a very complicated algorithm.



回答4:

Unified Streaming also offers a tool that can do this for you:

mp4split --package-hls output-single-file -o prog_index.m3u8 input.mp4

This is part of their commercial streaming package (they offer a free trial upon request). They also provide an Amazon AWS instance with hourly fees.