- Notifications
You must be signed in to change notification settings - Fork0
Python m3u8 Parser for HTTP Live Streaming (HLS) Transmissions
License
tnt-wolve/m3u8
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Pythonm3u8 parser.
The basic usage is to create a playlist object from uri, file path ordirectly from a string:
import m3u8m3u8_obj = m3u8.load('http://videoserver.com/playlist.m3u8') # this could also be an absolute filenameprint m3u8_obj.segmentsprint m3u8_obj.target_duration# if you already have the content as string, usem3u8_obj = m3u8.loads('#EXTM3U8 ... etc ... ')
- #EXT-X-TARGETDURATION
- #EXT-X-MEDIA-SEQUENCE
- #EXT-X-PROGRAM-DATE-TIME
- #EXT-X-MEDIA
- #EXT-X-PLAYLIST-TYPE
- #EXT-X-KEY
- #EXT-X-STREAM-INF
- #EXT-X-VERSION
- #EXT-X-ALLOW-CACHE
- #EXT-X-ENDLIST
- #EXTINF
- #EXT-X-I-FRAMES-ONLY
- #EXT-X-BYTERANGE
- #EXT-X-I-FRAME-STREAM-INF
- #EXT-X-DISCONTINUITY
- #EXT-X-CUE-OUT
- #EXT-X-CUE-OUT-CONT
- #EXT-X-INDEPENDENT-SEGMENTS
- #EXT-OATCLS-SCTE35
- #EXT-X-CUE-OUT
- #EXT-X-CUE-IN
- #EXT-X-CUE-SPAN
- #EXT-X-MAP
- #EXT-X-START
The segments may be or not encrypted. Thekeys
attribute list willbe an list with all the different keys as described with#EXT-X-KEY:
Each key has the next properties:
method
: ex.: "AES-128"uri
: the key uri, ex.: "http://videoserver.com/key.bin"iv
: the initialization vector, if available. OtherwiseNone
.
If no#EXT-X-KEY
is found, thekeys
list will have a unique elementNone
. Multiple keys are supported.
If unencrypted and encrypted segments are mixed in the M3U8 file, then the list will contain aNone
element, with oneor more keys afterwards.
To traverse the list of keys available:
import m3u8m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ...')len(m3u8_obj.keys) => returns the number of keys available in the list (normally 1)for key in m3u8_obj.keys: if key: # First one could be None key.uri key.method key.iv
There are cases where listing segments for a given key is important. It's possible toretrieve the list of segments encrypted with one key viaby_key
method in thesegments
list.
Example of getting the segments with no encryption:
import m3u8m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ...')segmk1 = m3u8_obj.segments.by_key(None)# Get the list of segments encrypted using last keysegm = m3u8_obj.segments.by_key( m3u8_obj.keys[-1] )
With this method, is now possible also to change the key from some of the segments programatically:
import m3u8m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ...')# Create a new Key and replace itnew_key = m3u8.Key("AES-128", "/encrypted/newkey.bin", None, iv="0xf123ad23f22e441098aa87ee")for segment in m3u8_obj.segments.by_key( m3u8_obj.keys[-1] ): segm.key = new_key# Remember to sync the key from the list as wellm3u8_obj.keys[-1] = new_key
A playlist can have a list to other playlist files, this is used torepresent multiple bitrates videos, and it's calledvariant streams.See anexample here.
variant_m3u8 = m3u8.loads('#EXTM3U8 ... contains a variant stream ...')variant_m3u8.is_variant # in this case will be Truefor playlist in variant_m3u8.playlists: playlist.uri playlist.stream_info.bandwidth
the playlist object used in the for loop above has a few attributes:
uri
: the url to the streamstream_info
: aStreamInfo
object (actually a namedtuple) withall the attributes available to#EXT-X-STREAM-INFmedia
: a list of relatedMedia
objects with all the attributesavailable to#EXT-X-MEDIAplaylist_type
: the type of the playlist, which can be one ofVOD(video on demand) orEVENT
NOTE: the following attributes are not implemented yet, followissue 4 for updates
alternative_audios
: its an empty list, unless it's a playlistwithAlternative audio, in this case it's a list withMedia
objects with all the attributes available to#EXT-X-MEDIAalternative_videos
: same asalternative_audios
A variant playlist can also have links toI-frame playlists, which are usedto specify where the I-frames are in a video. SeeApple's documentation onthis for more information. These I-frame playlists can be accessed in a similarway to regular playlists.
variant_m3u8 = m3u8.loads('#EXTM3U ... contains a variant stream ...')for iframe_playlist in variant_m3u8.iframe_playlists: iframe_playlist.uri iframe_playlist.iframe_stream_info.bandwidth
The iframe_playlist object used in the for loop above has a few attributes:
uri
: the url to the I-frame playlistbase_uri
: the base uri of the variant playlist (if given)iframe_stream_info
: aStreamInfo
object (same as a regular playlist)
$ ./runtests
All contribution is welcome, but we will merge a pull request if, and only if, it
- has tests
- follows the code conventions
If you plan to implement a new feature or something that will take morethan a few minutes, please open an issue to make sure we don't work onthe same thing.
About
Python m3u8 Parser for HTTP Live Streaming (HLS) Transmissions
Resources
License
Stars
Watchers
Forks
Packages0
Languages
- Python99.4%
- Shell0.6%