parse_m3u8_info : 返回M3U8内容, 但不是最终的, 只是简单的打印出来
parse_final_m3u8_info : 返回M3U8的完整内容
如果有多路stream,默认返回的是第一路的stream
has_ext_stream : 判断M3U8中是否存在#EXT-X-STREAM-INF
has_ext_key : 判断M3U8中是否存在#EXT-X-KEY, 就是m3u8是否被加密
has_ext_discontinuity : 判断M3U8中是否存在#EXT-X-DISCONTINUITY
当码流发生切换的时候, 会提示这个标签
get_total_duration : 获取M3U8文件的总时长
1.打印M3U8内容
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
import urlparse
URL='https://tv2.youkutv.cc/2020/04/14/MbqulRmS8sjQGJG9/playlist.m3u8'
### 返回m3u8文件,不是最终的
def parse_m3u8_info(url):
val = urlparse.urlsplit(url)
if (val.scheme != 'http') and (val.scheme != 'https'):
return 'Error protocol'
result = ''
request = requests.get(url, timeout=20)
for line in request.iter_lines():
result += line + '\n'
return result
result = parse_m3u8_info(URL)
print('M3U8文件内容如下:\n' + result)
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1500000,RESOLUTION=720x406
1500kb/hls/index.m3u8
2.打印M3U8完整文件
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
import urlparse
### M3U8 Tag
TAG_PREFIX = '#EXT'
TAG_STREAM_INF = '#EXT-X-STREAM-INF'
### M3U8 Pattern Tag
REGEX_MEDIA_DURATION = TAG_MEDIA_DURATION + ':([\\d\\.]+)\\b'
URL='http://video.yjf138.com:8091/20180812/6yl0Q2YZ/index.m3u8'
### 返回最终的m3u8文件
def parse_final_m3u8_info(url):
val = urlparse.urlsplit(url)
if (val.scheme != 'http') and (val.scheme != 'https'):
return 'Error protocol'
request = requests.get(url, timeout=20)
result = ''
hasStreamInf = False
for line in request.iter_lines():
if (line.startswith(TAG_PREFIX)):
result += line + '\n'
if (line.startswith(TAG_STREAM_INF)):
hasStreamInf = True
continue
if (hasStreamInf):
return parse_final_m3u8_info(get_final_url(url, line))
hasStreamInf = False
result += get_final_url(url, line) + '\n'
return result
### 根据m3u8中的分片写法得到完整的url
def get_final_url(url, line):
val = urlparse.urlsplit(url)
hostUrl = url[0:url.index(val.netloc)+len(val.netloc)]
baseUrl = url[0:url.rindex('/')+1]
if (line.startswith('/')):
tempUrl = ''
if (line[1:].find('/') != -1):
tempIndex = line[1:].index('/')
tempUrl = line[0:tempIndex]
if (url.find(tempUrl) != -1):
tempIndex = url.index(tempUrl)
tempUrl = url[0:tempIndex] + line
else:
tempUrl = hostUrl + line[1:]
return tempUrl
else:
tempUrl = baseUrl + line[1:]
return tempUrl
if (line.startswith('http://') or line.startswith('https://')):
return line
return baseUrl + line
finalResult = parse_final_m3u8_info(URL)
print('M3U8文件最终内容如下:\n' + finalResult)
3.统计M3U8的总时长
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
import urlparse
import re
### M3U8 Tag
TAG_PREFIX = '#EXT'
TAG_MEDIA_DURATION = "#EXTINF";
TAG_STREAM_INF = '#EXT-X-STREAM-INF'
### M3U8 Pattern Tag
REGEX_MEDIA_DURATION = TAG_MEDIA_DURATION + ':([\\d\\.]+)\\b'
URL='http://video.yjf138.com:8091/20180812/6yl0Q2YZ/index.m3u8'
### 获取M3U8文件的总时长
def get_total_duration(url):
val = urlparse.urlsplit(url)
if (val.scheme != 'http') and (val.scheme != 'https'):
return 'Error protocol'
request = requests.get(url, timeout=20)
result = ''
hasStreamInf = False
totalDuration = 0
for line in request.iter_lines():
if (line.startswith(TAG_PREFIX)):
if (line.startswith(TAG_STREAM_INF)):
hasStreamInf = True
elif (line.startswith(TAG_MEDIA_DURATION)):
ret = parse_pattern_str(REGEX_MEDIA_DURATION, line)
totalDuration += float(ret)
continue
if (hasStreamInf):
return get_total_duration(get_final_url(url, line))
hasStreamInf = False
return totalDuration
def parse_pattern_str(pattern_str, str):
matchObj = re.match(pattern_str, str)
if (matchObj) :
return matchObj.group(1)
return ''
totalDuration = get_total_duration(URL)
print('此M3U8文件的总时间: --->' + str(totalDuration))
上面出现过的get_final_url函数我就不重复写了。
上面用到了一个正则匹配,需要导入import re
4.是否存在KEY
http://video.yjf138.com:8091/20180812/6yl0Q2YZ/index.m3u8 中包含#EXT-X-KEY / #EXT-X-DISCONTINUITY / #EXT-X-STREAM-INF
#EXT-X-KEY:METHOD=AES-128,URI="key.key"
说明这时候使用AES-128加密,加密的密钥是 key.key, 当然是存在当前服务器上的密钥.
5.是否存在DISCONTINUITY
当发生码流变化的时候会出现这个标签,说明前后的ts可能会出现码流、分辨率、编码格式等属性的不同。播放器需要提前做好准备。
6.是否存在多路流
为多个分辨率准备的标签,当出现这个标签的时候,会标识当前流的分辨率、码流等属性,说明下面对应出现的还是一个M3U8索引文件。