You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于现有HLS(.m3u8) Python实现,构建MPEG-DASH(.mpd)的主清单与Feed清单生成方法

基于现有HLS(.m3u8) Python实现,构建MPEG-DASH(.mpd)的主清单与Feed清单生成方法

我已经用Python完成了针对.m3u8(HLS)播放列表的两个核心方法:

  • 生成主清单(Master Manifest)
  • 生成Feed清单(Feed Manifest)

现在我想把同样的逻辑复用到.mpd(MPEG-DASH)清单文件上,最终目标是拥有4个方法:2个处理HLS格式,2个处理DASH格式,且DASH的两个方法要和HLS版本完成完全相同的业务逻辑

现有HLS实现的依赖

目前我处理HLS用的是m3u8库,它非常实用——不仅能解析.m3u8文件,还提供了一套完整的构建API(比如M3U8PlaylistMediaSegment这些类),让我可以轻松组装出符合要求的清单文件。

遇到的问题:DASH工具的局限性

我搜索了一圈处理MPEG-DASH的Python库,但找到的都是解析器,比如python-mpegdashmpd-parser。它们只能读取、解析.mpd文件的内容,却没有像m3u8那样的构建/生成能力——我没法用它们来创建新的.mpd清单,或者修改现有清单并输出。

现有HLS方法代码(供参考)

下面是我现有的HLS实现,DASH的方法需要和这些逻辑一一对应:

import logging
from datetime import timedelta
from os.path import basename

from furl import furl
from m3u8 import M3U8, Media, Playlist, Segment
from m3u8 import load as load_m3u8

def make_master_manifest(request, stream):
    if stream.info:
        bandwidth = int(stream.info["bw_out"])
        width = stream.info["meta"]["video"]["width"]
        height = stream.info["meta"]["video"]["height"]
        stream_info = {
            "bandwidth": bandwidth,
            "resolution": f"{width}x{height}",
            "codecs": "avc1.640028,mp4a.40.2",
        }
    else:
        stream_info = {"bandwidth": 1000}

    p = Playlist(basename(stream.index_manifest_url), stream_info, None, None)
    m = M3U8()
    m.add_playlist(p)

    for feed in stream.feeds.all():
        media = Media(
            type="SUBTITLES",
            group_id="feeds",
            name=f"feed-{feed.uuid}",
            language="en",
            default="YES",
            autoselect="YES",
            uri=furl(feed.manifest_url).set({"stream": stream.uuid}).url,
        )
        p.media.append(media)
        m.add_media(media)

    return m.dumps()


def make_feed_manifest(request, stream, feed):
    url = request.build_absolute_uri(stream.index_manifest_url)
    p = load_m3u8(url)
    m = M3U8()
    m.version = p.version
    m.target_duration = p.target_duration
    m.media_sequence = p.media_sequence
    for s in p.segments:
        if not m.program_date_time:
            m.program_date_time = s.current_program_date_time

        vtt_url = furl(basename(feed.webvtt_url)).set({"stream": stream.uuid})
        if s.current_program_date_time:
            vtt_url.args.update(
                {
                    "start": s.current_program_date_time.isoformat(),
                    "end": (
                        s.current_program_date_time + timedelta(seconds=s.duration)
                    ).isoformat(),
                    "epoch": stream.started_at.isoformat(),
                }
            )
        v = Segment(
            base_uri=vtt_url.url,
            uri=vtt_url.url,
            duration=s.duration,
            discontinuity=s.discontinuity,
            program_date_time=s.current_program_date_time,
        )
        m.add_segment(v)

    return m.dumps()

具体需求

我需要实现两个对应DASH格式的方法:

  1. make_master_manifest_mpd(request, stream):和HLS版本逻辑一致,生成包含对应码率、分辨率信息,以及关联字幕Feed引用的DASH主清单
  2. make_feed_manifest_mpd(request, stream, feed):基于原DASH索引清单,生成包含对应WebVTT片段的Feed清单

不管是基于现有解析器扩展,还是直接手动拼接XML(毕竟.mpd本质是XML文档),只要能实现和现有HLS方法完全相同的功能就行,求各位大佬给点思路或者实现方案!

备注:内容来源于stack exchange,提问作者Ananth

火山引擎 最新活动