m3u8
m3u8 is a Python library designed to parse M3U8 HTTP Live Streaming (HLS) playlists. It allows loading playlists from URIs, file paths, or strings, and provides access to segments, streams, and other HLS tag information. The library is actively maintained, with its current version being 6.0.0, and receives regular updates to support new HLS specifications and bug fixes.
Warnings
- breaking In version 6.0.0, the 'BITRATE' attribute within `StreamInfo` (e.g., `playlist.playlists[0].stream_info.bandwidth['BITRATE']`) is now parsed as an integer type instead of a string. Code expecting a string for bitrate values will need to be updated.
- breaking Starting from version 5.2.0, `target_duration` is consistently parsed as an integer. Previous versions might have returned it as a float or string, which could break code expecting those types.
- breaking Version 4.0.0 dropped compatibility with Python 2.x and updated to require Python 3.7 or newer. Additionally, it now leverages built-in ISO 8601 parsing for Python 3.11+.
- gotcha When parsing playlists, especially those loaded from a URI, segment URIs can be relative. Accessing `segment.uri` directly might yield a relative path. Use `segment.absolute_uri` to get the full, resolved URL if absolute paths are required for downloading or further processing.
- gotcha The library, by default, ignores non-standard M3U8 tags (i.e., tags not defined in the HLS specification). If you need to parse or extract information from custom tags (e.g., `#MOVIE-NAME:`), you must provide a custom parser function.
Install
-
pip install m3u8
Imports
- load
import m3u8 playlist = m3u8.load('http://example.com/playlist.m3u8') - loads
import m3u8 playlist = m3u8.loads('#EXTM3U8\n...')
Quickstart
import m3u8
import requests
import os
# Example: Load a remote M3U8 playlist
# In a real scenario, use a specific, stable M3U8 URL.
# For a runnable example, we'll use a placeholder or local file.
# For demonstration, we'll simulate a playlist string.
# --- Option 1: Load from a URL (requires internet access) ---
# remote_m3u8_url = 'https://example.com/path/to/playlist.m3u8' # Replace with a real M3U8 URL if testing live
# try:
# playlist = m3u8.load(remote_m3u8_url)
# print(f"Loaded playlist from URL: {remote_m3u8_url}")
# if playlist.segments:
# print(f"First segment URI: {playlist.segments[0].uri}")
# else:
# print("No segments found in remote playlist.")
# except requests.exceptions.RequestException as e:
# print(f"Error loading remote playlist: {e}")
# --- Option 2: Load from a string (always runnable) ---
local_m3u8_content = """
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:9.009,
http://example.com/segment0.ts
#EXTINF:10.000,
http://example.com/segment1.ts
#EXT-X-ENDLIST
"""
playlist_from_string = m3u8.loads(local_m3u8_content)
print("\n--- Playlist from String ---")
print(f"Target Duration: {playlist_from_string.target_duration}")
print(f"Number of segments: {len(playlist_from_string.segments)}")
if playlist_from_string.segments:
print(f"First segment URI: {playlist_from_string.segments[0].uri}")
# Iterate through segments
print("\nSegments:")
for i, segment in enumerate(playlist_from_string.segments):
print(f" Segment {i}: Duration={segment.duration}, URI={segment.uri}")