python m3u8解析器

m3u8的Python项目详细描述


https://travis-ci.org/globocom/m3u8.svghttps://coveralls.io/repos/globocom/m3u8/badge.png?branch=masterhttps://badge.fury.io/py/m3u8.svg

m3u8

pythonm3u8解析器。

文档

基本用法是从uri、文件路径或 直接从字符串:

import m3u8

m3u8_obj = m3u8.load('http://videoserver.com/playlist.m3u8')  # this could also be an absolute filename
print m3u8_obj.segments
print m3u8_obj.target_duration

# if you already have the content as string, use

m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ... ')

支持的标记

  • #EXT-X-TARGETDURATION
  • #EXT-X-媒体序列
  • #ext-x-不连续序列
  • #ext-x-program-date-time
  • #EXT-X-媒体
  • #ext-x-playlist-type
  • #EXT-X-键
  • #ext-x-stream-inf
  • #EXT-X-版本
  • #ext-x-allow-cache
  • #EXT-X-ENDLIST
  • #熄灭
  • #仅限Ext-X-I-Frames
  • #ext-x-byterange
  • #ext-x-i-frame-stream-inf
  • #EXT-X-不连续性
  • #EXT-X-CUE-OUT
  • #EXT-X-CUE-OUT-CONT
  • #EXT-X-独立段
  • #EXT-OATCLS-SCTE35
  • #EXT-X-CUE-OUT
  • #EXT-X-CUE-IN
  • #外部-X-提示-SPAN
  • #EXT-X-MAP
  • #EXT-X-启动
  • #ext-x-server-control
  • ExT-X-PAR-IF EXT-X部分
  • #ext-x-rendition-report
  • #EXT-X-SKIP

加密密钥

段可以加密,也可以不加密。keys属性列表将 如#EXT-X-KEY

每个键都有下一个属性:

如果找不到#EXT-X-KEY,则keys列表将具有唯一的元素None。支持多个密钥。

如果m3u8文件中混合了未加密段和加密段,那么列表将包含一个None元素,其中有一个 或者更多的钥匙。

遍历可用键列表:

import m3u8

m3u8_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

获取用一个密钥加密的段

在某些情况下,列出给定键的段非常重要。有可能 通过中的by_key方法检索用一个密钥加密的段列表 segments列表。

获取不加密段的示例:

import m3u8

m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ...')
segmk1 = m3u8_obj.segments.by_key(None)

# Get the list of segments encrypted using last key
segm = m3u8_obj.segments.by_key( m3u8_obj.keys[-1] )

使用此方法,现在还可以通过编程方式更改某些段的键:

import m3u8

m3u8_obj = m3u8.loads('#EXTM3U8 ... etc ...')

# Create a new Key and replace it
new_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 well
m3u8_obj.keys[-1] = new_key

可变播放列表(可变比特率)

播放列表可以包含其他播放列表文件的列表,这用于 表示多个比特率视频,称为variant streams。 见example here

variant_m3u8 = m3u8.loads('#EXTM3U8 ... contains a variant stream ...')
variant_m3u8.is_variant    # in this case will be True

for playlist in variant_m3u8.playlists:
    playlist.uri
    playlist.stream_info.bandwidth

上面for循环中使用的playlist对象有几个属性:

  • uri:流的url
  • stream_info:具有 所有可用于#EXT-X-STREAM-INF
  • media:包含所有属性的相关Media对象的列表 可用于#EXT-X-MEDIA
  • playlist_type:播放列表的类型,可以是VOD (视频点播)或EVENT

注意:以下属性尚未实现,请遵循 issue 4用于更新

  • alternative_audios:它是一个空列表,除非它是一个播放列表 对于Alternative audio,在本例中是一个带有^{tt16}的列表$ 具有#EXT-X-MEDIA所有可用属性的对象
  • alternative_videos:与alternative_audios
  • 相同

变体播放列表也可以有指向I-frame playlists的链接,这些链接被使用 指定视频中i帧的位置。见Apple’s documentation上的 这是为了获取更多信息。这些i-frame播放列表可以在类似的 常规播放列表的方式。

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

上面for循环中使用的iframe_playlist对象有几个属性:

  • uri:i-frame播放列表的url
  • base_uri:变体播放列表的基本uri(如果给定的话)
  • iframe_stream_info:一个StreamInfo对象(与常规播放列表相同)

自定义标记

引用文档:

Lines that start with the character '#' are either comments or tags.
Tags begin with #EXT.  They are case-sensitive.  All other lines that
begin with '#' are comments and SHOULD be ignored.

默认情况下,此库忽略所有非标准标记。如果你想把它们收起来加载文件内容, 您需要将函数传递给load/loads函数,如下所示:

import m3u8

def get_movie(line, data, lineno):
    if line.startswith('#MOVIE-NAME:'):
        custom_tag = line.split(':')
        data['movie'] = custom_tag[1].strip()

m3u8_obj = m3u8.load('http://videoserver.com/playlist.m3u8', custom_tags_parser=get_movie)
print(m3u8_obj.data['movie'])  #  million dollar baby

运行测试

$ ./runtests

贡献

欢迎所有贡献,但我们将合并一个拉取请求,前提是且仅当它

  • 有测试
  • 遵循代码约定

如果你计划实现一个新的特性或者需要更多 再过几分钟,请打开一个问题以确保我们不工作 同样的事情。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
如何获得@sign,以便在Java代码中键入@override?   java Facebook登录不起作用,我忘了什么?   json如何在java中从MongoDB Atlas获取特定字段?   java如何在Android上的JNI中实现委托/协议(在iOS上)?   java为什么这个循环多次的程序在循环后有一个“println”时需要花费时间?   java无法使组合框正常工作   JavaCQ5。如何为作者显示列表发布者?版本5.5   java我可以要求泛型参数具有泛型参数吗?   JavaOKHTTP无法获取整个JSON   数组Java:用字符减去字符意味着什么?   java为什么Eclipse content assist无法从部分方法名生成方法存根?   java使用线程在Android Studio中一次加载一个多位图   java遍历二叉树并返回一个值