audio-metadata
audio-metadata copied to clipboard
Add MP4 (M4A) load(s) support
This has been sitting around locally for too long. Time to get some other people looking at/testing it, so it can finally get across the finish line.
For anyone willing to do some testing of MP4 support: pip install -U git+https://github.com/thebigmunch/audio-metadata@mp4
.
I set a warning to emit when it runs into tags using data types I don't currently have explicitly handled. I'd love to get any files that emit this warning.
Any questions/issues/discussion, post here.
TODO
- Implement any remaining tag types. Specifically the freeform
----
tags. - Handle multiple value tags.
- Finish extension parsing code.
- Reorganize/cleanup parsing code as necessary.
- Expose any attributes deemed worthy of exposing on
MP4StreamInfo
et al.
Hello! Found my issue got updated by this. Decided to test mp4 support. Seems to work for the most part. [Tested standard aac audio, not the weirded parts yet.]
Detects cover but doesn't detect other covers. [Again, those are placeholder images.]
Update 1:
Tested Apple AAC Encoding. Well it detects correctly but it doesn't detect HE-AAC
, still displays it as AAC LC
Referance Track
audio-metadata:
ffprobe:
Thanks for testing. I'm not sure everyone knows just how much I need people to test this stuff on their own files.
About the multiple tags, yeah, I hadn't gotten to supporting multiples for any of the MP4 tags yet. One of the things I need to finish up, though I had forgotten to list it.
And thanks especially for the HE-AAC track. So, HE-AAC is actually AAC LC with SBR extension (v1) or SBR and PS extensions (v2). But, I haven't finished the extension parsing yet to be able to modify the codec description. This appears to be a v1 file. Glad to have an example.
Hopefully I'll get motivation to work on the MP4 stuff again soon. Been banging out a lot of other stuff recently.
Just pushed a new version that supports multiple covers.
And, now it should set the codec description for your AAC-HE file. Plus, I found and fixed a bug along the way.
Apple AAC Works:
Also Doesn't detect Nero Encoded AAC for whatever reason... Test file if needed
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'untitledneroaac.m4a':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: M4A mp42isom
creation_time : 2020-03-08T08:37:28.000000Z
iTunSMPB : 00000000 00000A40 000001C0 0000000000096000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
encoder : Nero AAC codec / 1.5.4.0
Duration: 00:00:12.86, start: 0.054667, bitrate: 96 kb/s
Chapter #0:0: start 0.054667, end 12.918667
Metadata:
title :
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 93 kb/s (default)
Metadata:
creation_time : 2020-03-08T08:37:28.000000Z
handler_name : Sound Media Handler
Tossed a few static gif images into appleaac.m4a for cover test.. and it crashed. File in Question
>>> metadata = audio_metadata.load('untitledappleaac.m4a')
ValueError: 0 is not a valid MP4CoverFormat
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\api.py", line 125, in load
return parser_cls.parse(data)
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\formats\mp4.py", line 671, in parse
self.tags = MP4Tags.parse(data, ilst)
File "C:\Users\joshw\AppData\Roaming\Python\Python38\site-packages\wrapt\wrappers.py", line 621, in __call__
return self._self_wrapper(self.__wrapped__, instance, args,
File "C:\Program Files\Python38\lib\site-packages\tbm_utils\decorators.py", line 41, in wrapper
return wrapped(*args, **kwargs)
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\formats\mp4.py", line 219, in parse
tag = MP4Tag.parse(data, child)
File "C:\Users\joshw\AppData\Roaming\Python\Python38\site-packages\wrapt\wrappers.py", line 621, in __call__
return self._self_wrapper(self.__wrapped__, instance, args,
File "C:\Program Files\Python38\lib\site-packages\tbm_utils\decorators.py", line 41, in wrapper
return wrapped(*args, **kwargs)
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\formats\mp4_tags.py", line 129, in parse
return MP4CoverTag.parse(atom.read_data(data))
File "C:\Users\joshw\AppData\Roaming\Python\Python38\site-packages\wrapt\wrappers.py", line 621, in __call__
return self._self_wrapper(self.__wrapped__, instance, args,
File "C:\Program Files\Python38\lib\site-packages\tbm_utils\decorators.py", line 41, in wrapper
return wrapped(*args, **kwargs)
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\formats\mp4_tags.py", line 60, in parse
covers.append(MP4Cover.parse(data))
File "C:\Users\joshw\AppData\Roaming\Python\Python38\site-packages\wrapt\wrappers.py", line 621, in __call__
return self._self_wrapper(self.__wrapped__, instance, args,
File "C:\Program Files\Python38\lib\site-packages\tbm_utils\decorators.py", line 41, in wrapper
return wrapped(*args, **kwargs)
File "C:\Program Files\Python38\lib\site-packages\audio_metadata\formats\mp4_tags.py", line 24, in parse
format_ = MP4CoverFormat(struct.unpack('>I', data.read(4))[0])
File "C:\Program Files\Python38\lib\enum.py", line 304, in __call__
return cls.__new__(cls, value)
File "C:\Program Files\Python38\lib\enum.py", line 595, in __new__
raise exc
File "C:\Program Files\Python38\lib\enum.py", line 579, in __new__
result = cls._missing_(value)
File "C:\Program Files\Python38\lib\enum.py", line 608, in _missing_
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 0 is not a valid MP4CoverFormat
Though... FFmpeg also says a Unknown Cover Type and just skips it entirely:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0000024a2520c1c0] Unknown cover type: 0x0.
Last message repeated 2 times
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'untitledappleaac.m4a':
Metadata:
major_brand : M4A
minor_version : 0
compatible_brands: M4A mp42isom
creation_time : 2020-03-07T09:13:17.000000Z
encoder : qaac 2.68, CoreAudioToolbox 7.9.8.3, AAC-HE Encoder, CVBR 16kbps, Quality 96
iTunSMPB : 00000000 00000840 000007C0 000000000004B000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Encoding Params : vers
Duration: 00:00:12.97, start: 0.044000, bitrate: 92 kb/s
Stream #0:0(und): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 15 kb/s (default)
Metadata:
creation_time : 2020-03-07T09:13:17.000000Z
Yeah, for the cover art, apparently it can be set as the IMPLICIT
MP4 atom type. I don't know enough about MP4 to know if that's wrong or just nonsensical. Either way, I can just add an UNKNOWN
cover format to handle that case. Taglib does the same. No reason to skip it.
Just pushed changes to support that and the Nero-encoded file. Though, it did remind me that I haven't added support for the freeform ----
tags yet.
Thanks again for the testing.
Hi,
It seems like the bitrate is not being read correctly for some of my .m4a files. Any ideas as to why this could be happening?
What's the current state of this issue? Thanks.
For the code base I'm using this branch with, I'm not doing anything particularly fancy so it mostly works. Biggest issues I hit were:
- m4v isn't in the list of supported file extentions
- Freeform fields are definitely still broken in that they don't properly append
It is working for m4a files recorded with quicktime media! thanks!!
For anyone that cares, here's a fix for the freeform fields bug: https://github.com/whatsnowplaying/audio-metadata/commit/920b2bfde57a16292214afdf2660d43e572eafd5