Coder Social home page Coder Social logo

python-mpegdash's Introduction

python-mpegdash

MPEG-DASH MPD (Media Presentation Description) Parser compatible with Python 3+.

Build Status License


Installation

$ pip install mpegdash

Test

$ python -m unittest discover

Usage

from mpegdash.parser import MPEGDASHParser

# Parse from file path
mpd_path = './tests/mpd-samples/sample-001.mpd'
mpd = MPEGDASHParser.parse(mpd_path)

# Parse from url
mpd_url = 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/motion-20120802-manifest.mpd'
mpd = MPEGDASHParser.parse(mpd_url)

# Parse from string
mpd_string = '''
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" mediaPresentationDuration="PT0H1M52.43S" minBufferTime="PT1.5S"
profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static">
  <Period duration="PT0H1M52.43S" start="PT0S">
    <AdaptationSet>
      <ContentComponent contentType="video" id="1" />
      <Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
        <BaseURL>motion-20120802-89.mp4</BaseURL>
        <SegmentBase indexRange="674-981">
          <Initialization range="0-673" />
        </SegmentBase>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>
'''
mpd = MPEGDASHParser.parse(mpd_string)

# Write to xml file
MPEGDASHParser.write(mpd, './tests/mpd-samples/output.mpd')

License

This project is released under the MIT license. Please read and agree to the license before use, it can be found in the LICENSE file.

python-mpegdash's People

Contributors

a-detiste avatar brozikcz avatar bvc3at avatar davemevans avatar jayapraveen avatar kakao-eddy-lee avatar karthik-0 avatar kolombo avatar mykola-makarenko avatar onovy avatar rlaphoenix avatar sangwonl avatar thenewguy avatar wreszelewski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-mpegdash's Issues

Respect AdaptationSet selectionPriority

per 3.9.2 in DASH-IF Interoperability Points v4.3

@selectionPriority
See ISO/IEC 23009-1 [4], clause 5.3.7.2 Table 9.
This attribute should be used to dis-ambiguate Adaptation Sets within one group for selection and expresses the preference of the MPD author on selecting Adaptation Sets for which the DASH client does make a decision otherwise. Examples include two video codecs providing the same content, but one of the two pro-vides higher compression efficiency and is therefore preferred by the MPD author.

I could not find reference to it anywhere in the source searching for selectionPriority, selection, or priority

About viedo mpd

Can this code get the MPD file of the specified video link?

ProgramInformation writing throws exception

Given the following manifest:

<?xml version="1.0" encoding="UTF-8"?>
<MPD type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT0.451S" mediaPresentationDuration="PT0S">
<ProgramInformation>
	<Title>Test Title</Title>
	<Source>Test Source</Source>
</ProgramInformation>
<Period duration="PT0S" start="PT0S">
</Period>
</MPD>

calling .write throws the following exception:

Traceback (most recent call last):
  File "/mnt/c/work/python-mpegdash/tests/test_mpdtoxml.py", line 47, in test_pi
    MPEGDASHParser.write(mpd, './tests/mpd-samples/pi-output.mpd')
  File "/mnt/c/work/python-mpegdash/mpegdash/parser.py", line 41, in write
    cls.get_as_doc(mpd).writexml(f, indent='    ', addindent='    ', newl='\n')
  File "/mnt/c/work/python-mpegdash/mpegdash/parser.py", line 35, in get_as_doc
    write_child_node(xml_doc, 'MPD', mpd)
  File "/mnt/c/work/python-mpegdash/mpegdash/utils.py", line 61, in write_child_node
    node.write(new_elem)
  File "/mnt/c/work/python-mpegdash/mpegdash/nodes.py", line 732, in write
    write_child_node(xmlnode, 'ProgramInformation', self.program_informations)
  File "/mnt/c/work/python-mpegdash/mpegdash/utils.py", line 57, in write_child_node
    n.write(new_elem)
  File "/mnt/c/work/python-mpegdash/mpegdash/nodes.py", line 91, in write
    write_child_node(xmlnode, 'Source', self.sources)
  File "/mnt/c/work/python-mpegdash/mpegdash/utils.py", line 57, in write_child_node
    n.write(new_elem)
AttributeError: 'unicode' object has no attribute 'write'

Similar happens with user-created nodes except it fails with 'str' object rather than 'unicode'

Licensing

Hi,

I've been digging into your MPD parser and found it really convenient ! I was wondering under which license you were distributing it. I would not like to steal your work by mistake !

Thank you for your awesome work,
Gauthier Lamaison

ContentProtection's most likely don't use `@value`, e.g. `@cenc:pssh`

<!-- Common Encryption -->
<ContentProtection cenc:default_KID="CCF8F1AC-0700-4591-A4E1-B60D1ADA5631" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc">
</ContentProtection>
<!-- Marlin -->
<ContentProtection schemeIdUri="urn:uuid:5E629AF5-38DA-4063-8977-97FFBD9902D4">
</ContentProtection>
<!-- PlayReady -->
<ContentProtection schemeIdUri="urn:uuid:9A04F079-9840-4286-AB92-E65BE0885F95" value="MSPR 2.0">
<cenc:pssh>bAIAAAEAAQBiAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AcgBQAEgANAB6AEEAQQBIAGsAVQBXAGsANABiAFkATgBHAHQAcABXAE0AUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBDAEEARABpADIATABpAFUARAAxAG8APQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAHIAbABzAC4AYQB0AHYALQBwAHMALgBhAG0AYQB6AG8AbgAuAGMAbwBtAC8AYwBkAHAAPAAvAEwAQQBfAFUAUgBMAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</cenc:pssh></ContentProtection>
<!-- Widevine -->
<ContentProtection schemeIdUri="urn:uuid:EDEF8BA9-79D6-4ACE-A3C8-27DCD51D21ED">
<cenc:pssh>CAESEMz48awHAEWRpOG2DRraVjEaBmFtYXpvbiI1Y2lkOnpQanhyQWNBUlpHazRiWU5HdHBXTVE9PSxCYnFTNk9yMlJYdUwvWS9aWGphN1B3PT0qAlNEMgA=</cenc:pssh></ContentProtection>
<!-- Marlin -->
<ContentProtection schemeIdUri="urn:uuid:5E629AF5-38DA-4063-8977-97FFBD9902D4">

Add typing

Now that python supports Typing, we can Create schema for nodes so that developers get suggestions on IDE

write_child_node need to help str node_type

The write_child_node defined in utils.py needs handle special case for str node type.

def write_child_node(xmlnode, tag_name, node):
if node:
xmldoc = xmlnode if isinstance(xmlnode, minidom.Document) else xmlnode.ownerDocument
if isinstance(node, list):
for n in node:
new_elem = xmldoc.createElement(tag_name)
#n.write(new_elem) #This doesn't work for str type. exception throws. Add the following 4 lines of code seems to solved the problem.
if isinstance(n, str) or isinstance(n, unicode):
write_node_value(new_elem, n)
else:
n.write(new_elem)

xmlnode.appendChild(new_elem)
else:
new_elem = xmldoc.createElement(tag_name)
node.write(new_elem)
xmlnode.appendChild(new_elem)

Wrong type of SubRepresentation.content_component

In file mpegdash/nodes.py:

self.content_component = parse_attr_value(xmlnode, 'contentComponent', [str])

shouldn't it be:
self.content_component = parse_attr_value(xmlnode, 'contentComponent', str)
or
self.content_component = parse_attr_value(xmlnode, 'contentComponent', int)
?

try this code:

import mpegdash.parser

mpd = '''
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" type="dynamic" minimumUpdatePeriod="PT30S" availabilityStartTime="2014-02-05T22:29:56" minBufferTime="PT12S" timeShiftBufferDepth="PT1M0S" profiles="urn:mpeg:dash:profile:isoff-live:2011">
  <BaseURL>http://test-i.akamaihd.net/dash/live/500002/linearprogram1</BaseURL>
  <BaseURL>http://test-i.akamaihd.net/dash/live/500002-b/linearprogram</BaseURL>
  <Period start="PT0S" duration="PT1M0.6S" id="1">
    <AdaptationSet mimeType="video/mp4" codecs="avc1.42CE,mp4a.40.5" frameRate="15000/1001" segmentAlignment="true" subsegmentAlignment="true" startWithSAP="1" subsegmentstartWithSAP="1" bitstreamSwitching="true">
      <ContentComponent contentType="video" id="1" />
      <SegmentTemplate timescale="90000" duration="540000" startNumber="74247" />
      <Representation id="1" width="640" height="360" bandwidth="600000">
        <SubRepresentation contentComponent="1" bandwidth="600000" codecs="avc1.42C01E" />
        <SegmentTemplate duration="540000" startNumber="74247" media="dash_video600-$Number$.mp4" initialization="dash_video600-.init" />
      </Representation>
      <Representation id="2" width="320" height="180" bandwidth="200000">
        <SubRepresentation contentComponent="1" bandwidth="200000" codecs="avc1.42C01E" />
        <SegmentTemplate duration="540000" startNumber="74248" media="dash_video200-$Number$.mp4" initialization="dash_video200-.init" />
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>
'''

parsed_mpd = mpegdash.parser.MPEGDASHParser.parse(mpd)
new_mpd = mpegdash.parser.MPEGDASHParser.toprettyxml(parsed_mpd)
print(new_mpd)

The output contains this: contentComponent="[<class 'str'>]" :

<?xml version="1.0" ?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" availabilityStartTime="2014-02-05T22:29:56" minimumUpdatePeriod="PT30S" minBufferTime="PT12S" timeShiftBufferDepth="PT1M0S">
    <BaseURL>http://test-i.akamaihd.net/dash/live/500002/linearprogram1</BaseURL>
    <BaseURL>http://test-i.akamaihd.net/dash/live/500002-b/linearprogram</BaseURL>
    <Period id="1" start="PT0S" duration="PT1M0.6S">
        <AdaptationSet frameRate="15000/1001" mimeType="video/mp4" codecs="avc1.42CE,mp4a.40.5" startWithSAP="1" segmentAlignment="true" subsegmentAlignment="true" bitstreamSwitching="true">
            <ContentComponent id="1" contentType="video"/>
            <SegmentTemplate timescale="90000" duration="540000" startNumber="74247"/>
            <Representation width="640" height="360" id="1" bandwidth="600000">
                <SegmentTemplate duration="540000" startNumber="74247" media="dash_video600-$Number$.mp4" initialization="dash_video600-.init"/>
                <SubRepresentation codecs="avc1.42C01E" bandwidth="600000" contentComponent="[&lt;class 'str'&gt;]"/>
            </Representation>
            <Representation width="320" height="180" id="2" bandwidth="200000">
                <SegmentTemplate duration="540000" startNumber="74248" media="dash_video200-$Number$.mp4" initialization="dash_video200-.init"/>
                <SubRepresentation codecs="avc1.42C01E" bandwidth="200000" contentComponent="[&lt;class 'str'&gt;]"/>
            </Representation>
        </AdaptationSet>
    </Period>
</MPD>

manifest example taken from here:
https://learn.akamai.com/en-us/webhelp/media-services-live/media-services-live-hls-hds-and-dash-ingest-user-guide-v3.2/GUID-A32F2823-ED4D-470B-9BC3-C4C455FE2F47.html

Non-text Event child nodes not supported

Event nodes may have child nodes that are not of type text. The 3rd edition of the DASH spec makes this clearer by adding the messageData attribute for use when the event data is a string (see #20 for implementation of this)

An example might be SCTE35 cues with schemeIdUri urn:scte:scte35:2013:xml or urn:scte:scte35:2014:xml+bin, where the child node would be <Signal>, with further children as required.

The library does not currently support this - the Event content is always considered to be text for parsing and writing - causing data to be lost when transforming a manifest.

project name

why is the name of the project "mdp-parser"? should be mpd-parser?

parse_child_nodes bug for str node_type

In the parse_child_nodes defined in utils.py, when node type is (unicode, str), the call to "xmlnode.firstChild.nodeValue", appears to be wrong. When I change the call to parse_node_value(elem, node_type). It correctly passed the input mpd manifest file. This bug results in wrong parsed value to the Title element in the follow XML:

<Title>inthewoods.mpd generated by GPAC</Title>

def parse_child_nodes(xmlnode, tag_name, node_type):
elements = _find_child_nodes_by_name(xmlnode, tag_name)
if not elements:
return None

nodes = []
for elem in elements:
    if node_type in (unicode, str):
        #node = xmlnode.firstChild.nodeValue           ### This seems to be wrong!!!
        node = parse_node_value(elem, node_type)  #This fixed the problem!
    else:
        node = node_type()
        node.parse(elem)
    nodes.append(node)

return nodes

MPEGDASHParser write to file throws error

When i am trying to write back the mpd object to xml file using MPEGDASHParser.write(mpd_file, mpd_file_path), i got this error:
'unicode' object has no attribute 'write'

Incorrect processing of string nodes

Any string node results in "AttributeError: 'str' object has no attribute 'parse'".
Problem is in file utils.py(line 21): if isinstance(node_type, (str, unicode)):
You are testing the type of variable node_type instead of testing the value. Line should be if node_type in (str, unicode):

Decode signal SCTE-35 <binary> strings with threefive

I've been wanting to add DASH support to threefive,
but it seems like it makes more sense to add SCTE-35 support to a DASH parser.

if you want to pull the SCTE-35 values from  a <binary> tag  base64 string  in a signal 
       <Signal
          xmlns="http://www.scte.org/schemas/35/2016">
          <Binary>/DAgAAAAAAAAAP/wDwUA15FRf//+ADS8AMAAAAAAAORhJCQ=</Binary>
        </Signal>

You can use threefive like this

from threefive import Cue

b64 ="/DAgAAAAAAAAAP/wDwUA15FRf//+ADS8AMAAAAAAAORhJCQ="
cue = Cue(b64)
cue.decode()

after calling decode all the SCTE-35 vars can be accessed via dot notation

>>>> cue.command.break_duration
38.4

cue.show() prints thje cue in json

>>>> cue.show()
{
    "info_section": {
        "table_id": "0xfc",
        "section_syntax_indicator": false,
        "private": false,
        "sap_type": "0x03",
        "sap_details": "No Sap Type",
        "section_length": 32,
        "protocol_version": 0,
        "encrypted_packet": false,
        "encryption_algorithm": 0,
        "pts_adjustment_ticks": 0,
        "pts_adjustment": 0.0,
        "cw_index": "0x00",
        "tier": "0x0fff",
        "splice_command_length": 15,
        "splice_command_type": 5,
        "descriptor_loop_length": 0,
        "crc": "0xe4612424"
    },
    "command": {
        "command_length": 15,
        "command_type": 5,
        "name": "Splice Insert",
        "break_auto_return": true,
        "break_duration": 38.4,
        "break_duration_ticks": 3456000,
        "splice_event_id": 14127441,
        "splice_event_cancel_indicator": false,
        "out_of_network_indicator": true,
        "program_splice_flag": true,
        "duration_flag": true,
        "splice_immediate_flag": true,
        "event_id_compliance_flag": true,
        "unique_program_id": 49152,
        "avail_num": 0,
        "avail_expected": 0
    },
    "descriptors": []
}

Python 3 Compatibility

I can install in python 2.7 using "sudo pip install mpegdash", but installing using pip3 fails. Any suggestions?

Bash$ sudo pip3 install mpegdash
Collecting mpegdash
Could not find a version that satisfies the requirement mpegdash (from versions: )
No matching distribution found for mpegdash

AdaptationSet should have the "profiles" attribute

RepresentationBase() maps "profile" to "@profiles" at

self.profiles = parse_attr_value(xmlnode, 'profile', str)

and

write_attr_value(xmlnode, 'profile', self.profiles)

Adaptation Sets can have the profiles attribute to signal conformance per

10.2.3.4. Adaptation Set Constraints
The @profiles parameter may be present to signal the constraints for the Adaptation Set

Probably a typo since there is @profile and also @profiles depending on the element

xs:boolean types are not cased correctly when written

Attributes parsed as boolean are not written correctly. xs:boolean is case sensitive, so may only be true or false (or 0 or 1), but the library writes them as Python booleans True or False.

Eg AdaptationSet@segmentAlignment

New version for PyPi?

There have been a bunch of changes to this library since 0.1.5 was released.

Would it be possible to make a new release and push it to PyPi?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.