@@ -340,17 +340,27 @@ def __init__(self, *args, **kwargs):
340340 if args or kwargs :
341341 self .load (* args , ** kwargs )
342342
343- def load (self , atoms , fileobj ):
344- try :
345- path = atoms .path (b"moov" , b"udta" , b"meta" , b"ilst" )
346- except KeyError as key :
347- raise MP4MetadataError (key )
348-
349- free = _find_padding (path )
350- self ._padding = free .datalength if free is not None else 0
343+ def load (self , atoms : Atoms , fileobj ):
344+ for atom in atoms .atoms :
345+ if atom .children is not None :
346+ self ._recurse_atom (atom , fileobj )
347+
348+ def _recurse_atom (self , parent : Atom , fileobj ):
349+ """Recursively search for an ilst atom to read metadata from.
350+
351+ Recursing helps if the mp4/m4a container didn't store metadata correctly,
352+ which is usually expected at moov.trak.udta.meta.ilst"""
353+ if parent .name != b"ilst" :
354+ for atom in parent .children :
355+ if parent .name == b"meta" and atom .name == b"ilst" :
356+ free = _find_padding ([parent , atom ])
357+ self ._padding = free .datalength if free is not None else 0
358+
359+ if atom .children is not None and atom .name != 'ilst' :
360+ self ._recurse_atom (atom , fileobj )
361+ return
351362
352- ilst = path [- 1 ]
353- for atom in ilst .children :
363+ for atom in parent .children :
354364 ok , data = atom .read (fileobj )
355365 if not ok :
356366 raise MP4MetadataError ("Not enough data" )
0 commit comments