mirror of
https://github.com/iluvcapra/wavinfo.git
synced 2025-12-31 08:50:41 +00:00
ADM metadata
This commit is contained in:
@@ -23,6 +23,17 @@ class TestADMWave(TestCase):
|
|||||||
dict = adm.to_dict()
|
dict = adm.to_dict()
|
||||||
self.assertIsNotNone(dict)
|
self.assertIsNotNone(dict)
|
||||||
|
|
||||||
|
def test_programme(self):
|
||||||
|
info = wavinfo.WavInfoReader(self.protools_adm_wav)
|
||||||
|
adm = info.adm
|
||||||
|
pdict = adm.programme()
|
||||||
|
self.assertIn("programme_id", pdict.keys())
|
||||||
|
self.assertIn("programme_name", pdict.keys())
|
||||||
|
self.assertEqual(pdict['programme_id'], 'APR_1001')
|
||||||
|
self.assertEqual(pdict['programme_name'], 'Atmos_Master')
|
||||||
|
self.assertIn("contents", pdict.keys())
|
||||||
|
self.assertEqual(len(pdict["contents"]), 3)
|
||||||
|
|
||||||
def test_track_info(self):
|
def test_track_info(self):
|
||||||
info = wavinfo.WavInfoReader(self.protools_adm_wav)
|
info = wavinfo.WavInfoReader(self.protools_adm_wav)
|
||||||
adm = info.adm
|
adm = info.adm
|
||||||
|
|||||||
@@ -12,29 +12,53 @@ class MyJSONEncoder(json.JSONEncoder):
|
|||||||
else:
|
else:
|
||||||
return super().default(o)
|
return super().default(o)
|
||||||
|
|
||||||
|
class MissingDataError(RuntimeError):
|
||||||
|
pass
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
|
||||||
parser.usage = 'wavinfo [FILE.wav]*'
|
parser.usage = 'wavinfo [FILES]'
|
||||||
|
|
||||||
# parser.add_option('-f', dest='output_format', help='Set the output format',
|
# parser.add_option('-f', dest='output_format', help='Set the output format',
|
||||||
# default='json',
|
# default='json',
|
||||||
# metavar='FORMAT')
|
# metavar='FORMAT')
|
||||||
|
|
||||||
|
parser.add_option('--adm', dest='adm', help='Output ADM XML',
|
||||||
|
default=False, action='store_true')
|
||||||
|
|
||||||
|
parser.add_option('--ixml', dest='ixml', help='Output iXML',
|
||||||
|
default=False, action='store_true')
|
||||||
|
|
||||||
(options, args) = parser.parse_args(sys.argv)
|
(options, args) = parser.parse_args(sys.argv)
|
||||||
for arg in args[1:]:
|
for arg in args[1:]:
|
||||||
try:
|
try:
|
||||||
this_file = WavInfoReader(path=arg)
|
this_file = WavInfoReader(path=arg)
|
||||||
ret_dict = {'file_argument': arg, 'run_date': datetime.datetime.now().isoformat() , 'scopes': {}}
|
if options.adm:
|
||||||
for scope, name, value in this_file.walk():
|
if this_file.adm:
|
||||||
if scope not in ret_dict['scopes'].keys():
|
sys.stdout.write(this_file.adm.xml_str())
|
||||||
ret_dict['scopes'][scope] = {}
|
else:
|
||||||
|
raise MissingDataError("--adm option active but ADM metadata not present")
|
||||||
|
elif options.ixml:
|
||||||
|
if this_file.ixml:
|
||||||
|
sys.stdout.write(this_file.ixml.xml_bytes())
|
||||||
|
else:
|
||||||
|
raise MissingDataError("--ixml option active but iXML metadata not present")
|
||||||
|
else:
|
||||||
|
ret_dict = {'file_argument': arg, 'run_date': datetime.datetime.now().isoformat() , 'scopes': {}}
|
||||||
|
for scope, name, value in this_file.walk():
|
||||||
|
if scope not in ret_dict['scopes'].keys():
|
||||||
|
ret_dict['scopes'][scope] = {}
|
||||||
|
|
||||||
ret_dict['scopes'][scope][name] = value
|
ret_dict['scopes'][scope][name] = value
|
||||||
|
|
||||||
json.dump(ret_dict, cls=MyJSONEncoder, fp=sys.stdout, indent=2)
|
json.dump(ret_dict, cls=MyJSONEncoder, fp=sys.stdout, indent=2)
|
||||||
|
except MissingDataError as e:
|
||||||
|
print("Missing metadata error in file %s" % arg, file=sys.stderr)
|
||||||
|
print(e, file=sys.stderr)
|
||||||
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
raise e
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -41,6 +41,53 @@ class WavADMReader:
|
|||||||
|
|
||||||
offset += calcsize(uid_fmt)
|
offset += calcsize(uid_fmt)
|
||||||
|
|
||||||
|
def xml_str(self) -> str:
|
||||||
|
"""ADM XML as a string"""
|
||||||
|
return ET.tostring(self.axml).decode("utf-8")
|
||||||
|
|
||||||
|
def programme(self) -> dict:
|
||||||
|
"""
|
||||||
|
Extract the ADM audioProgramme data structure and some of its reference properties
|
||||||
|
"""
|
||||||
|
ret_dict = dict()
|
||||||
|
|
||||||
|
nsmap = self.axml.getroot().nsmap
|
||||||
|
|
||||||
|
afext = self.axml.find(".//audioFormatExtended", namespaces=nsmap)
|
||||||
|
|
||||||
|
program = afext.find("audioProgramme", namespaces=nsmap)
|
||||||
|
ret_dict['programme_id'] = program.get("audioProgrammeID")
|
||||||
|
ret_dict['programme_name'] = program.get("audioProgrammeName")
|
||||||
|
ret_dict['programme_start'] = program.get("start")
|
||||||
|
ret_dict['programme_end'] = program.get("end")
|
||||||
|
ret_dict['contents'] = []
|
||||||
|
|
||||||
|
for content_ref in program.findall("audioContentIDRef", namespaces=nsmap):
|
||||||
|
content_dict = dict()
|
||||||
|
content_dict['content_id'] = cid = content_ref.text
|
||||||
|
content = afext.find("audioContent[@audioContentID='%s']" % cid, namespaces=nsmap)
|
||||||
|
content_dict['content_name'] = content.get("audioContentName")
|
||||||
|
content_dict['objects'] = []
|
||||||
|
|
||||||
|
for object_ref in content.findall("audioObjectIDRef", namespaces=nsmap):
|
||||||
|
object_dict = dict()
|
||||||
|
object_dict['object_id'] = oid = object_ref.text
|
||||||
|
object = afext.find("audioObject[@audioObjectID='%s']" % oid, namespaces=nsmap)
|
||||||
|
pack = object.find("audioPackFormatIDRef", namespaces=nsmap)
|
||||||
|
object_dict['object_name'] = object.get("audioObjectName")
|
||||||
|
object_dict['object_start'] = object.get("start")
|
||||||
|
object_dict['object_duration'] = object.get("duration")
|
||||||
|
object_dict['pack_id'] = pack.text
|
||||||
|
track_uid_list = []
|
||||||
|
for t in object.findall("audioTrackUIDRef", namespaces=nsmap):
|
||||||
|
track_uid_list.append(t.text)
|
||||||
|
|
||||||
|
object_dict['track_uids'] = track_uid_list
|
||||||
|
content_dict['objects'].append(object_dict)
|
||||||
|
|
||||||
|
ret_dict['contents'].append(content_dict)
|
||||||
|
|
||||||
|
return ret_dict
|
||||||
|
|
||||||
def track_info(self, index):
|
def track_info(self, index):
|
||||||
"""
|
"""
|
||||||
@@ -61,36 +108,36 @@ class WavADMReader:
|
|||||||
|
|
||||||
afext = self.axml.find(".//audioFormatExtended", namespaces=nsmap)
|
afext = self.axml.find(".//audioFormatExtended", namespaces=nsmap)
|
||||||
|
|
||||||
trackformat_elem = afext.find(".//audioTrackFormat[@audioTrackFormatID='%s']" % channel_info.track_ref,
|
trackformat_elem = afext.find("audioTrackFormat[@audioTrackFormatID='%s']" % channel_info.track_ref,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
|
|
||||||
stream_id = trackformat_elem[0].text
|
stream_id = trackformat_elem[0].text
|
||||||
|
|
||||||
channelformatref_elem = afext.find(".//audioStreamFormat[@audioStreamFormatID='%s']/audioChannelFormatIDRef" % stream_id,
|
channelformatref_elem = afext.find("audioStreamFormat[@audioStreamFormatID='%s']/audioChannelFormatIDRef" % stream_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
channelformat_id = channelformatref_elem.text
|
channelformat_id = channelformatref_elem.text
|
||||||
|
|
||||||
packformatref_elem = afext.find(".//audioStreamFormat[@audioStreamFormatID='%s']/audioPackFormatIDRef" % stream_id,
|
packformatref_elem = afext.find("audioStreamFormat[@audioStreamFormatID='%s']/audioPackFormatIDRef" % stream_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
packformat_id = packformatref_elem.text
|
packformat_id = packformatref_elem.text
|
||||||
|
|
||||||
channelformat_elem = afext.find(".//audioChannelFormat[@audioChannelFormatID='%s']" % channelformat_id,
|
channelformat_elem = afext.find("audioChannelFormat[@audioChannelFormatID='%s']" % channelformat_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
ret_dict['channel_format_name'] = channelformat_elem.get("audioChannelFormatName")
|
ret_dict['channel_format_name'] = channelformat_elem.get("audioChannelFormatName")
|
||||||
|
|
||||||
packformat_elem = afext.find(".//audioPackFormat[@audioPackFormatID='%s']" % packformat_id,
|
packformat_elem = afext.find("audioPackFormat[@audioPackFormatID='%s']" % packformat_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
ret_dict['pack_type'] = packformat_elem.get("typeDefinition")
|
ret_dict['pack_type'] = packformat_elem.get("typeDefinition")
|
||||||
ret_dict['pack_format_name'] = packformat_elem.get("audioPackFormatName")
|
ret_dict['pack_format_name'] = packformat_elem.get("audioPackFormatName")
|
||||||
|
|
||||||
object_elem = afext.find(".//audioObject[audioPackFormatIDRef = '%s']" % packformat_id,
|
object_elem = afext.find("audioObject[audioPackFormatIDRef = '%s']" % packformat_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
|
|
||||||
ret_dict['audio_object_name'] = object_elem.get("audioObjectName")
|
ret_dict['audio_object_name'] = object_elem.get("audioObjectName")
|
||||||
object_id = object_elem.get("audioObjectID")
|
object_id = object_elem.get("audioObjectID")
|
||||||
ret_dict['object_id'] = object_id
|
ret_dict['object_id'] = object_id
|
||||||
|
|
||||||
content_elem = afext.find(".//audioContent/[audioObjectIDRef = '%s']" % object_id,
|
content_elem = afext.find("audioContent/[audioObjectIDRef = '%s']" % object_id,
|
||||||
namespaces=nsmap)
|
namespaces=nsmap)
|
||||||
|
|
||||||
ret_dict['content_name'] = content_elem.get("audioContentName")
|
ret_dict['content_name'] = content_elem.get("audioContentName")
|
||||||
@@ -108,4 +155,5 @@ class WavADMReader:
|
|||||||
rd.update(self.track_info(channel_uid_rec.track_index - 1))
|
rd.update(self.track_info(channel_uid_rec.track_index - 1))
|
||||||
return rd
|
return rd
|
||||||
|
|
||||||
return dict(channel_entries=list(map(lambda z: make_entry(z), self.channel_uids)))
|
return dict(channel_entries=list(map(lambda z: make_entry(z), self.channel_uids)),
|
||||||
|
programme=self.programme())
|
||||||
@@ -27,6 +27,9 @@ class WavIXMLFormat:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def xml_bytes(self):
|
||||||
|
return ET.tostring(self.parsed).decode("utf-8")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raw_xml(self):
|
def raw_xml(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user