markreidvfx / pyaaf2

Read and write Advanced Authoring Format (AAF) files
http://pyaaf.readthedocs.io
MIT License
133 stars 36 forks source link

parse out mxf files #48

Closed steccino closed 2 years ago

steccino commented 5 years ago

hi mark!!

i can't find my last comment i made last year about this topic, sorry! is there any way for me to parse out .mxf files with this python version of pyaaf? or output some kind of human readable version of the aaf file that i can parse myself?

thank you!

markreidvfx commented 5 years ago

yes, pyaaf2 includes a mxf parser.

from aaf2 import mxf
path = "/path/to/file.mxf"
m = mxf.MXFFile(path)
m.dump()

The parser is used internally to make it really easy to link to external mxf files.

import aaf2
with aaf2.open(out_file, 'w') as f:
    path = "/path/to/file.mxf"
    mobs =  f.content.link_external_mxf(path)
steccino commented 5 years ago

sorry, i should have been more clear- i have a .aaf file and i am trying to parse out all of the .mxf paths so i can pass them to a copy tool.

a co-worker wrote some regex up to try and parse out the binary and piece the paths together- it works most of the time :P

randolfE commented 5 years ago

Hi Mark,

i would be interested in such a method either. I am specifically searching for a way to get paths to audio material for certain Mobs.

Kind Regards, Randolf

markreidvfx commented 5 years ago

File locators are always on a SourceMob's EssenceDescriptor, its pretty easy extract them.

import aaf2
with aaf2.open("/path/to/file.aaf") as f:
    for mob in f.content.sourcemobs():
        for loc in mob.descriptor.locator:
            print(loc['URLString'].value)

you can make the paths prettier with urllib

I would no recommend trying to get them out with regex expressions as a AAF file is basically a Fat32 filesystem. Some sectors of the file could be marked FREE but still contain previous data and not zeroed out.

czyz commented 5 years ago

Interestingly -- for a show with MXF files on a nexis, the sourcemob descriptor.locator turns out to often be the location of the original source media rather than the MXF media actually used within the edit.

I'm running this code:

with aaf2.open(sys.argv[1], "r") as f:
    for mobby in f.content.sourcemobs():
        #test whether locator attribute exists before accessing it to avoid error
        if hasattr(mobby.descriptor, 'locator'):
            for loc in mobby.descriptor.locator:
                file_location = unquote(loc['URLString'].value.encode('utf-8'))
                file_location = file_location.replace('file:///','/Volumes/')
                file_location = file_location.replace('file://nexispro/','/Volumes/')
                print(file_location)  

And the result of that code includes lots of entries like this one, which points to the mxf media on our SFX volume that I'd like to copy:

/Volumes/SFX/Avid MediaFiles/MXF/zMike_L.1/A02.D871DD8B_18A2A18A2A20BA.mxf

And also a bunch like this:

/Volumes/Avid_HD/Users/user/Desktop/S_070352_001.mp3

--These point to original file locations from which an editor probably imported a piece of media, and this original location info is of no use to me -- I've checked and the sequence in media composer is using mxf files in the SFX volume, not an AMA-link to an actual mp3 file that was once on someone's desktop (the horror).

I wonder if there's some actual media location metadata hiding in the AAF file for such clips? I'm not finding it, yet.

markreidvfx commented 5 years ago

Checking the Descriptor class type could help filter out those. The Mp3 file is probably from a ImportDescriptor which sounds like you don't care about. The aaf would only contains the mxf path at time of export.

janciev commented 5 years ago

Hi,

I have the same problem, I can't seem to find a way to filter out just the actual media paths (Avid structure). Has someone managed to solve this?

Thanks! Igor

conorhodder commented 5 years ago

Above code works a treat for me, assuming I add in a filter for import descriptors.

if hasattr(mob.descriptor, 'locator') and not isinstance(mob.descriptor, aaf2.essence.ImportDescriptor)

Some of the source mobs don't seem to have correlative file on disk, but they appear to be unecessary for a successful relink in AVID.

(edit for spelling)

steccino commented 4 years ago

Hi Mark!

i have an aaf file that I can successfully import into Resolve. If I take that same file, open it, do no editing and just save it out, I get this error when importing:

Error: No timeline detected in the given file, operation failed.

This is the save I am doing:

with aaf2.open(aaf_file, 'w') as f: f.save()

I was just testing out a very basic save to give to someone - I did also try the example in your docs (writing out a new mob with an mov and a wav file) and that also failed when I tired to import.

markreidvfx commented 2 years ago

@steccino I think your problem is you need to open the file as 'rw'. opeing 'w' will create a new file overwriting the old file.