sangwonl / python-mpegdash Goto Github PK
View Code? Open in Web Editor NEWMPEG-DASH MPD(Media Presentation Description) Parser
License: MIT License
MPEG-DASH MPD(Media Presentation Description) Parser
License: MIT License
RepresentationBase()
maps "profile" to "@profiles" at
python-mpegdash/mpegdash/nodes.py
Line 395 in ca75790
and
python-mpegdash/mpegdash/nodes.py
Line 418 in ca75790
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
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
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):
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
When I try to open an MPD file from an HTTPS link, urlopen throws the following error:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:1007)>
parse.py:16
I would suggest the following changes in parse.py:
def parse(cls, string_or_url) -> **def parse(cls, string_or_url, verifiySSL=false):**
def load_xmldom(cls, string_or_url) -> def load_xmldom(cls, string_or_url, verifiySSL)
...
mpd_string = urlopen(string_or_url).read() -> requests.get(string_or_url, verify=verifiySSL)
....
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
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)
With Github Action.
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'
Can this code get the MPD file of the specified video link?
ns2:default_KID is ONE possible entry. It seems to depend on the xmlns. E.g. if its from ns2, then ns2:... if its cenc, then cenc:...
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?
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="[<class 'str'>]"/>
</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="[<class 'str'>]"/>
</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
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'
Attribute is used to declare language name in manifest. While this attribute is not standard, it is used in major dash players (google/ExoPlayer#4391, shaka-project/shaka-player#811)
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
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.
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
From @davemevans's comment:
Seems that schema file available at that link has not been updated to match the current (4th) edition of the DASH spec - it only seems to match the 2nd edition.
4th Edition schema is available at https://standards.iso.org/iso-iec/23009/-1/ed-4/en/DASHSchema-4th-Ed.zip (link is in the spec) and includes
endNumber
.Originally posted by @davemevans in #57 (comment)
We need to update our schema file and make it work.
Now that python supports Typing, we can Create schema for nodes so that developers get suggestions on IDE
<!-- 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">
why is the name of the project "mdp-parser"? should be mpd-parser?
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": []
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.