Registered Member
|
Hello,
I want to pass video projects back and forth between myself (I use kdenlive) and people who use other NLEs. My most important need is interoperability between kdenlive and Vegas Pro. I also desire to interoperate with other popular NLEs (this would be Adobe Premiere Pro, then Final Cut Pro, then Avid, according to some survey http://www.learningdslrvideo.com/nle-ma ... breakdown/ ) I believe that the way to do this is through AAF (Advanced Authoring Format). We should be able to convert between AAF files and kdenlive XML files. I can imagine this being included in kdenlive or taking the form of a standalone program, that does two-way conversion between kdenlive XMLs and AAFs. I am ready to offer $1000. However, this is not yet a firm offer, because the problem to solve is not defined precisely: - Which effects will be taken into account? The absolute minimum would be to convert a project that nas multiple tracks with cuts, but the more effects will be correctly converted between kdenlive and other NLEs, the better (audio volume, various audio corrections with keyframes, fade to/from black, color correction, alpha blended titles, and more) - On which NLEs will this be tested? Is the developer going to test it fully, or should I participate? - How do we convert pathnames to clips? kdenlive runs on LInux, the other NLEs run on Windows or Mac, so we need to design a conversion scheme. At this point, I am asking for two things: - Comments: does this proposal make sense to you? - Offers. A good offer would look like this: "I want the bounty, I want to do this thing within two months, it will be tested with the following NLEs ..., will work correctly with the following effects ...." Or like this: "I will do it with no effects (you can only have cuts of clips), and will test it on Vegas Pro only, for this I want $300 instead of the full bounty" Any thoughts? mm@skubi.net |
Registered Member
|
Thank you for making this offer Skubi - the Kdenlive community is starting to gather some steam as evidenced by your enthusiasm.
I will cross post this to the Kdenlive Dev-group. Presently, the focus is on getting Kdenlive ready for the KDE-5 rollout. There's also an upcoming effort to rework the Kdenlive project file format to more closely follow the mechanisms employed by MLT/Shotcut. I expect that this work would take precedence over any interoperability w/ AAF. My initial thoughts on this are that an associated program could be created to accomplish the desired interoperability w/ AAF. The program would ingest a Kdenlive project and spit out an AAF document. Ideally, we would setup a rule-based mechanism that defines the transposition that takes place for each element in a Kdenlive project. If that's all it takes, it may not be too difficult to accomplish this - time consuming though. Unfortunately, this feature will have to wait until the Kdenlive project file format gets reworked - IMO. |
Registered Member
|
hi
i am very interested in trying to find a solution to work with other editors as well. i started trying to first define a protocol or a way to address this issue. check it out: https://bugs.freedesktop.org/show_bug.cgi?id=83111 your input would be much appreciated. lets join forces. also check out this mlt to blender script: (it uses CMX 3600 EDL format ) https://eyeframeconverter.wordpress.com/mlt2edl/ cheers |
Registered Member
|
Thank you for the answers to this thread.
By modifying some kdenlive->EDL converter found on the net, I obtained a script that transforms a multi-track kdenlive project into EDLs that can be understood by Vegas Pro. This is very limited, has hardcoded stuff in it, and is generally very, very quick and dirty. Can be used only by those who understand python and are willing to get their hands dirty tweaking the script. I am posting the script, because of the lack of better stuff (I hope that my bounty will result in better stuff). """ kdenparse.py KdenParse attempts to extract and present useful information from a .kdenlive XML project file. Kdenlive video editing software can be found here: http://www.kdenlive.org """ import os, sys, argparse version_ = "%(prog)s 0.1.0" argparser = argparse.ArgumentParser(prog="kdenparse.py", add_help=True, description="Parses .kdenlive project files for various metadata and timeline informations.") argparser.add_argument('-V', '--version', action='version', version=version_) argparser.add_argument('--edl', action='store_true', default=False, dest='create_edl', help='Generate EDL output.') argparser.add_argument('--deref-proxy', action='store_true', default=False, dest='deref_proxy', help='Dereference proxy clip (show original filenames)') argparser.add_argument('--frames', action='store_true', default=False, dest='show_frames', help='Show frames instead of TC when using --edl.') argparser.add_argument('--links', action='store_true', default=False, dest='show_links', help='Show source id to filename association.') argparser.add_argument('--profile', action='store_true', default=False, dest='get_profile', help='Generate project profile metadata.') argparser.add_argument('--producers', action='store_true', default=False, dest='get_producers', help='Show MLT producers (media file) metadata.') argparser.add_argument('--kproducers', action='store_true', default=False, dest='get_kproducers',ratherather than programmingr than programming help='Show Kdenlive producers (media file) metadata.') argparser.add_argument('projectFile') args = argparser.parse_args() if not os.path.isfile(args.projectFile): print "Not a file we can work with..." sys.exit(1) try: args.projectFile.rindex(".kdenlive",-9) except ValueError: print "Invalid filename. Exiting." sys.exit(1) from xml.dom import minidom from decimal import Decimal,getcontext,ROUND_DOWN from math import modf, floor class KdenParse: def __init__(self, kdenliveFile): self.xmldoc = minidom.parse(kdenliveFile) self.realSrc = {"pr-1-1-C0003.kdenlive":"C0003POPR.MOV", "pr-1-1-C0004.kdenlive":"1-1-C0004.MXF", "C0003POPR.mov":"C0003POPR.MOV", "pr-1-2-C0001.kdenlive":"1-2-C0001.MXF", "1-2-C0001.mov":"1-2-C0001.MXF", "1-1-C0004.mov":"1-1-C0004.MXF", "1-1-C0003.mov":"1-1-C0003.MXF", "pr-2-1-C0001.kdenlive":"2-1-C0001.MXF", "2-1-C0001.mov":"2-1-C0001.MXF", "pr-2-2-C0002.kdenlive":"2-2-C0002.MXF", "2-2-C0002.mov":"2-2-C0002.MXF", "pr-P401.kdenlive":"P1000401.MP4", "pr-P403.kdenlive":"P1000403.MP4", "P1000401.mp4":"P1000401.MP4", "pr-P402.kdenlive":"P1000402.MP4", "P1000402.mp4":"P1000402.MP4", "P1000398.MP4.mov":"P1000398.MP4", "P1000399.MP4.mov":"P1000399.MP4", "P1000399.mov":"P1000399.MP4", "P1000400.MP4.mov":"P1000400.MP4", "P1000400.mov":"P1000400.MP4", "P1000403.mov":"P1000403.MP4"} def getProjectProfile(self): profileDict = {} profile = self.xmldoc.getElementsByTagName("profile") keyList = profile.item(0).attributes.keys() for a in keyList: profileDict[a] = profile.item(0).attributes[a].value return profileDict def getTracks(self): tracks = [] t = self.xmldoc.getElementsByTagName("track") for track in t: tracks.append(track.attributes["producer"].value) return tuple(tracks) def getPlaylists(self): playlistList = [] playlists = self.xmldoc.getElementsByTagName("playlist") for p in playlists: eventList = [] plDict = {} plDict["pid"] = p.attributes["id"].value #eventsAndBlanks = p.getElements() for e in p.childNodes: if e.nodeType == minidom.Node.ELEMENT_NODE: # events = p.getElementsByTagName("entry") # for event in events if e.tagName == 'entry': evDict = {} evDict["producer"] = e.attributes["producer"].value evDict["inTime"] = e.attributes["in"].value evDict["outTime"] = e.attributes["out"].value eventList.append(evDict) elif e.tagName == 'blank': evDict = {} evDict["length"] = e.attributes["length"].value eventList.append(evDict) else: None #print "***** Unexpected tag", e.tagName plDict["events"] = eventList playlistList.append(plDict) return tuple(playlistList) def getKProducers(self): kProducerList = [] profile = self.xmldoc.getElementsByTagName("kdenlive_producer") for i in profile: kpDict = {} keyList = i.attributes.keys() for a in keyList: kpDict[i.attributes[a].name] = i.attributes[a].value kProducerList.append(kpDict) return tuple(kProducerList) def getProducers(self): producerList = [] producers = self.xmldoc.getElementsByTagName("producer") for p in producers: pDict = {} pDict["pid"] = p.attributes["id"].value pDict["inTime"] = p.attributes["in"].value pDict["outTime"] = p.attributes["out"].value properties = p.getElementsByTagName("property") for props in properties: if None != props.firstChild: pDict[props.attributes["name"].value.replace(".","_")] = props.firstChild.data else: pDict[props.attributes["name"].value.replace(".","_")] = None #print "MISSING", props.attributes["name"].value producerList.append(pDict) return tuple(producerList) def linkReferences(self): sourceLinks = {} for i in self.getProducers(): srcPid = i["pid"] sourceLinks[srcPid] = i["resource"] return sourceLinks def derefProxy(self): proxyLinks = {} for i in self.getKProducers(): try: if i["proxy"]: _proxy = i["proxy"] proxyLinks[_proxy] = i["resource"] except KeyError: return False return proxyLinks def createEdl(self): sourceLinks = self.linkReferences() print '"ID";"Track";"StartTime";"Length";"PlayRate";"Locked";"Normalized";"StretchMethod";"Looped";"OnRuler";"MediaType";"FileName";"Stream";"StreamStart";"StreamLength";"FadeTimeIn";"FadeTimeOut";"SustainGain";"CurveIn";"GainIn";"CurveOut";"GainOut";"Layer";"Color";"CurveInR";"CurveOutR";"PlayPitch";"LockPitch";"FirstChannel";"Channels"' EdlEventCnt = 1 trackNumber = 0 for playlist in self.getPlaylists(): perTrackEdlEventCnt = 1 progIn = 0 # showtime tally progOut = 0 srcChannel = "C" # default channel/track assignment for event in playlist["events"]: if "producer" in event: prod = event["producer"] prodChunks = prod.split("_") srcType = prodChunks[-1].capitalize()[:1] # if it's an audio event, extract channel info from producer id if srcType == "A": srcChannel = prodChunks[1] srcIn = int(event["inTime"]) # source clip IN time srcOut = int(event["outTime"]) # source clip OUT time if perTrackEdlEventCnt != 1: srcOut = srcOut + 1 srcDur = srcOut - srcIn progOut = progIn + srcDur # increment program tally sourcePath = sourceLinks[prod] if None == sourcePath: sourceFile = "NONAME" else: sourceFile = sourcePath.split("/")[-1] if sourceFile in self.realSrc: sourceFile = self.realSrc[sourceFile] proxyList = self.derefProxy() if proxyList: try: sourceRef = "(" + proxyList[sourcePath].split("/")[-1] + ") " + sourceFile except KeyError: sourceRef = sourceFile else: sourceRef = sourceFile # print "* FROM CLIP NAME: " + sourceRef # print str(EdlEventCnt) + " " + prod + " ", if 'NONAME' != sourceRef \ and '0x000000ff' != sourceRef \ and 'lowtitle.kdenlivetitle' != sourceRef \ and 'black' != sourceRef: if sourceRef[-4:] == '.WAV': sourceKind = 'AUDIO' stretch = '2; ' lineTrailer = '2; 0.000000; -2; 0.000000; 0; -1; -2; 2; 0.000000; FALSE; 0; 0' else: sourceKind = 'VIDEO' stretch = '0; ' lineTrailer = '4; 0.000000; 4; 0.000000; 0; -1; 4; 4; 0.000000; FALSE; 0; 0' print str(EdlEventCnt) + "; " + str(trackNumber) + "; " + ("%.4f; " % (progIn*25000)) \ + ("%.4f; " % ((progOut-progIn)*25000)) \ + "1.000000; FALSE; FALSE; " + stretch + "TRUE; FALSE; " \ + sourceKind + "; " \ + '"' + sourceRef + '"; ' \ + "0; " + ("%.4f; " % ((srcOut-srcIn)*25000)) \ + ("%.4f; " % (srcIn*25000)) \ + "0.0000; 0.0000; 1.000000; " + lineTrailer #if args.show_frames: # print str(srcIn) + " " + str(srcOut) + "", # print str(progIn) + " " + str(progOut) #else: # print self.framesToDF(srcIn) + " " + self.framesToDF(srcOut), # print self.framesToDF(progIn) + " " + self.framesToDF(progOut) EdlEventCnt += 1 if perTrackEdlEventCnt == 1: progIn = progIn + 1 progIn = progIn + srcDur perTrackEdlEventCnt += 1 else: progIn += int(event['length']) trackNumber += 1 def framesToABS(self, frameAddress): getcontext().prec = 10 getcontext().rounding = ROUND_DOWN projectMeta = self.getProjectProfile() frameRate = Decimal(projectMeta["frame_rate_num"]) / Decimal(projectMeta["frame_rate_den"]) frameDuration = 1 / frameRate #print "fps = " + str(frameRate) #print "1 fr = " + str(frameDuration) + " secs" absDuration = Decimal(frameAddress) * Decimal(frameDuration) # frameAddress length in seconds #print "TC = " + str(absDuration) f, w = modf(absDuration) # split float at decimal (fraction, whole) #print "Split: " + "%f + %f" % (w, f) frameRemainder = Decimal(str(f)) / Decimal(frameDuration) m, s = divmod(w, 60) h, m = divmod(m, 60) tc = "%d:%02d:%02d:%02d" % (h, m, s, frameRemainder) return tc def framesToDF(self, framenumber): """ This method adapted from C++ code called "timecode" by Jason Wood. begin: Wed Dec 17 2003 copyright: (C) 2003 by Jason Wood email: jasonwood@blueyonder.co.uk Framerate should be 29.97, 59.94, or 23.976, otherwise the calculations will be off. Framerate can also be 25.00 (added by mm@skubi.net, 24 June 2014) """ projectMeta = self.getProjectProfile() framerate = float(projectMeta["frame_rate_num"]) / float(projectMeta["frame_rate_den"]) # Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate, # except if the European format (25 or 50 fps) is used if abs (framerate - 25.) < 0.001 or abs (framerate - 50.) < 0.001: dropFrames = 0 else: dropFrames = round(framerate * 0.066666) # Number of frames in an hour framesPerHour = round(framerate * 60 * 60) # Number of frames in a day - timecode rolls over after 24 hours framesPerDay = framesPerHour * 24 # Number of frames per ten minutes framesPer10Minutes = round(framerate * 60 * 10) # Number of frames per minute is the round of the framerate * 60 minus the number of dropped frames framesPerMinute = (round(framerate) * 60) - dropFrames if (framenumber < 0): # For negative time, add 24 hours. framenumber = framesPerDay + framenumber # If framenumber is greater than 24 hrs, next operation will rollover clock # % is the modulus operator, which returns a remainder. a % b = the remainder of a/b framenumber = framenumber % framesPerDay d = floor(framenumber / framesPer10Minutes) m = framenumber % framesPer10Minutes if (m > 1): framenumber=framenumber + (dropFrames * 9 * d) + dropFrames * floor((m-dropFrames) / framesPerMinute) else: framenumber = framenumber + dropFrames * 9 * d; frRound = round(framerate); frames = framenumber % frRound; seconds = floor(framenumber / frRound) % 60; minutes = floor(floor(framenumber / frRound) / 60) % 60; hours = floor(floor(floor(framenumber / frRound) / 60) / 60); tc = "%02d:%02d:%02d:%02d" % (hours, minutes, seconds, frames) return tc def framesToNDF(self): pass kp = KdenParse(args.projectFile) if args.create_edl: kp.createEdl() if args.get_profile: for i in kp.getProjectProfile().keys(): print i + ": " + kp.getProjectProfile()[i] if args.get_producers: for i in kp.getProducers(): print "\n=================\n" for kv in i: print kv + ": " + i[kv] if args.get_kproducers: for i in kp.getKProducers(): print "\n=================\n" for kv in i: print kv + ": " + i[kv] if args.deref_proxy: for i in kp.derefProxy(): print i + ": " + kp.derefProxy()[i] if args.show_links: for i in kp.linkReferences(): print i + ": " + kp.linkReferences()[i] """ kdenparse.py KdenParse attempts to extract and present useful information from a .kdenlive XML project file. Kdenlive video editing software can be found here: http://www.kdenlive.org """ import os, sys, argparse version_ = "%(prog)s 0.1.0" argparser = argparse.ArgumentParser(prog="kdenparse.py", add_help=True, description="Parses .kdenlive project files for various metadata and timeline informations.") argparser.add_argument('-V', '--version', action='version', version=version_) argparser.add_argument('--edl', action='store_true', default=False, dest='create_edl', help='Generate EDL output.') argparser.add_argument('--deref-proxy', action='store_true', default=False, dest='deref_proxy', help='Dereference proxy clip (show original filenames)') argparser.add_argument('--frames', action='store_true', default=False, dest='show_frames', help='Show frames instead of TC when using --edl.') argparser.add_argument('--links', action='store_true', default=False, dest='show_links', help='Show source id to filename association.') argparser.add_argument('--profile', action='store_true', default=False, dest='get_profile', help='Generate project profile metadata.') argparser.add_argument('--producers', action='store_true', default=False, dest='get_producers', help='Show MLT producers (media file) metadata.') argparser.add_argument('--kproducers', action='store_true', default=False, dest='get_kproducers',ratherather than programmingr than programming help='Show Kdenlive producers (media file) metadata.') argparser.add_argument('projectFile') args = argparser.parse_args() if not os.path.isfile(args.projectFile): print "Not a file we can work with..." sys.exit(1) try: args.projectFile.rindex(".kdenlive",-9) except ValueError: print "Invalid filename. Exiting." sys.exit(1) from xml.dom import minidom from decimal import Decimal,getcontext,ROUND_DOWN from math import modf, floor class KdenParse: def __init__(self, kdenliveFile): self.xmldoc = minidom.parse(kdenliveFile) self.realSrc = {"pr-1-1-C0003.kdenlive":"C0003POPR.MOV", "pr-1-1-C0004.kdenlive":"1-1-C0004.MXF", "C0003POPR.mov":"C0003POPR.MOV", "pr-1-2-C0001.kdenlive":"1-2-C0001.MXF", "1-2-C0001.mov":"1-2-C0001.MXF", "1-1-C0004.mov":"1-1-C0004.MXF", "1-1-C0003.mov":"1-1-C0003.MXF", "pr-2-1-C0001.kdenlive":"2-1-C0001.MXF", "2-1-C0001.mov":"2-1-C0001.MXF", "pr-2-2-C0002.kdenlive":"2-2-C0002.MXF", "2-2-C0002.mov":"2-2-C0002.MXF", "pr-P401.kdenlive":"P1000401.MP4", "pr-P403.kdenlive":"P1000403.MP4", "P1000401.mp4":"P1000401.MP4", "pr-P402.kdenlive":"P1000402.MP4", "P1000402.mp4":"P1000402.MP4", "P1000398.MP4.mov":"P1000398.MP4", "P1000399.MP4.mov":"P1000399.MP4", "P1000399.mov":"P1000399.MP4", "P1000400.MP4.mov":"P1000400.MP4", "P1000400.mov":"P1000400.MP4", "P1000403.mov":"P1000403.MP4"} def getProjectProfile(self): profileDict = {} profile = self.xmldoc.getElementsByTagName("profile") keyList = profile.item(0).attributes.keys() for a in keyList: profileDict[a] = profile.item(0).attributes[a].value return profileDict def getTracks(self): tracks = [] t = self.xmldoc.getElementsByTagName("track") for track in t: tracks.append(track.attributes["producer"].value) return tuple(tracks) def getPlaylists(self): playlistList = [] playlists = self.xmldoc.getElementsByTagName("playlist") for p in playlists: eventList = [] plDict = {} plDict["pid"] = p.attributes["id"].value #eventsAndBlanks = p.getElements() for e in p.childNodes: if e.nodeType == minidom.Node.ELEMENT_NODE: # events = p.getElementsByTagName("entry") # for event in events if e.tagName == 'entry': evDict = {} evDict["producer"] = e.attributes["producer"].value evDict["inTime"] = e.attributes["in"].value evDict["outTime"] = e.attributes["out"].value eventList.append(evDict) elif e.tagName == 'blank': evDict = {} evDict["length"] = e.attributes["length"].value eventList.append(evDict) else: None #print "***** Unexpected tag", e.tagName plDict["events"] = eventList playlistList.append(plDict) return tuple(playlistList) def getKProducers(self): kProducerList = [] profile = self.xmldoc.getElementsByTagName("kdenlive_producer") for i in profile: kpDict = {} keyList = i.attributes.keys() for a in keyList: kpDict[i.attributes[a].name] = i.attributes[a].value kProducerList.append(kpDict) return tuple(kProducerList) def getProducers(self): producerList = [] producers = self.xmldoc.getElementsByTagName("producer") for p in producers: pDict = {} pDict["pid"] = p.attributes["id"].value pDict["inTime"] = p.attributes["in"].value pDict["outTime"] = p.attributes["out"].value properties = p.getElementsByTagName("property") for props in properties: if None != props.firstChild: pDict[props.attributes["name"].value.replace(".","_")] = props.firstChild.data else: pDict[props.attributes["name"].value.replace(".","_")] = None #print "MISSING", props.attributes["name"].value producerList.append(pDict) return tuple(producerList) def linkReferences(self): sourceLinks = {} for i in self.getProducers(): srcPid = i["pid"] sourceLinks[srcPid] = i["resource"] return sourceLinks def derefProxy(self): proxyLinks = {} for i in self.getKProducers(): try: if i["proxy"]: _proxy = i["proxy"] proxyLinks[_proxy] = i["resource"] except KeyError: return False return proxyLinks def createEdl(self): sourceLinks = self.linkReferences() print '"ID";"Track";"StartTime";"Length";"PlayRate";"Locked";"Normalized";"StretchMethod";"Looped";"OnRuler";"MediaType";"FileName";"Stream";"StreamStart";"StreamLength";"FadeTimeIn";"FadeTimeOut";"SustainGain";"CurveIn";"GainIn";"CurveOut";"GainOut";"Layer";"Color";"CurveInR";"CurveOutR";"PlayPitch";"LockPitch";"FirstChannel";"Channels"' EdlEventCnt = 1 trackNumber = 0 for playlist in self.getPlaylists(): perTrackEdlEventCnt = 1 progIn = 0 # showtime tally progOut = 0 srcChannel = "C" # default channel/track assignment for event in playlist["events"]: if "producer" in event: prod = event["producer"] prodChunks = prod.split("_") srcType = prodChunks[-1].capitalize()[:1] # if it's an audio event, extract channel info from producer id if srcType == "A": srcChannel = prodChunks[1] srcIn = int(event["inTime"]) # source clip IN time srcOut = int(event["outTime"]) # source clip OUT time if perTrackEdlEventCnt != 1: srcOut = srcOut + 1 srcDur = srcOut - srcIn progOut = progIn + srcDur # increment program tally sourcePath = sourceLinks[prod] if None == sourcePath: sourceFile = "NONAME" else: sourceFile = sourcePath.split("/")[-1] if sourceFile in self.realSrc: sourceFile = self.realSrc[sourceFile] proxyList = self.derefProxy() if proxyList: try: sourceRef = "(" + proxyList[sourcePath].split("/")[-1] + ") " + sourceFile except KeyError: sourceRef = sourceFile else: sourceRef = sourceFile # print "* FROM CLIP NAME: " + sourceRef # print str(EdlEventCnt) + " " + prod + " ", if 'NONAME' != sourceRef \ and '0x000000ff' != sourceRef \ and 'lowtitle.kdenlivetitle' != sourceRef \ and 'black' != sourceRef: if sourceRef[-4:] == '.WAV': sourceKind = 'AUDIO' stretch = '2; ' lineTrailer = '2; 0.000000; -2; 0.000000; 0; -1; -2; 2; 0.000000; FALSE; 0; 0' else: sourceKind = 'VIDEO' stretch = '0; ' lineTrailer = '4; 0.000000; 4; 0.000000; 0; -1; 4; 4; 0.000000; FALSE; 0; 0' print str(EdlEventCnt) + "; " + str(trackNumber) + "; " + ("%.4f; " % (progIn*25000)) \ + ("%.4f; " % ((progOut-progIn)*25000)) \ + "1.000000; FALSE; FALSE; " + stretch + "TRUE; FALSE; " \ + sourceKind + "; " \ + '"' + sourceRef + '"; ' \ + "0; " + ("%.4f; " % ((srcOut-srcIn)*25000)) \ + ("%.4f; " % (srcIn*25000)) \ + "0.0000; 0.0000; 1.000000; " + lineTrailer #if args.show_frames: # print str(srcIn) + " " + str(srcOut) + "", # print str(progIn) + " " + str(progOut) #else: # print self.framesToDF(srcIn) + " " + self.framesToDF(srcOut), # print self.framesToDF(progIn) + " " + self.framesToDF(progOut) EdlEventCnt += 1 if perTrackEdlEventCnt == 1: progIn = progIn + 1 progIn = progIn + srcDur perTrackEdlEventCnt += 1 else: progIn += int(event['length']) trackNumber += 1 def framesToABS(self, frameAddress): getcontext().prec = 10 getcontext().rounding = ROUND_DOWN projectMeta = self.getProjectProfile() frameRate = Decimal(projectMeta["frame_rate_num"]) / Decimal(projectMeta["frame_rate_den"]) frameDuration = 1 / frameRate #print "fps = " + str(frameRate) #print "1 fr = " + str(frameDuration) + " secs" absDuration = Decimal(frameAddress) * Decimal(frameDuration) # frameAddress length in seconds #print "TC = " + str(absDuration) f, w = modf(absDuration) # split float at decimal (fraction, whole) #print "Split: " + "%f + %f" % (w, f) frameRemainder = Decimal(str(f)) / Decimal(frameDuration) m, s = divmod(w, 60) h, m = divmod(m, 60) tc = "%d:%02d:%02d:%02d" % (h, m, s, frameRemainder) return tc def framesToDF(self, framenumber): """ This method adapted from C++ code called "timecode" by Jason Wood. begin: Wed Dec 17 2003 copyright: (C) 2003 by Jason Wood email: jasonwood@blueyonder.co.uk Framerate should be 29.97, 59.94, or 23.976, otherwise the calculations will be off. Framerate can also be 25.00 (added by mm@skubi.net, 24 June 2014) """ projectMeta = self.getProjectProfile() framerate = float(projectMeta["frame_rate_num"]) / float(projectMeta["frame_rate_den"]) # Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate, # except if the European format (25 or 50 fps) is used if abs (framerate - 25.) < 0.001 or abs (framerate - 50.) < 0.001: dropFrames = 0 else: dropFrames = round(framerate * 0.066666) # Number of frames in an hour framesPerHour = round(framerate * 60 * 60) # Number of frames in a day - timecode rolls over after 24 hours framesPerDay = framesPerHour * 24 # Number of frames per ten minutes framesPer10Minutes = round(framerate * 60 * 10) # Number of frames per minute is the round of the framerate * 60 minus the number of dropped frames framesPerMinute = (round(framerate) * 60) - dropFrames if (framenumber < 0): # For negative time, add 24 hours. framenumber = framesPerDay + framenumber # If framenumber is greater than 24 hrs, next operation will rollover clock # % is the modulus operator, which returns a remainder. a % b = the remainder of a/b framenumber = framenumber % framesPerDay d = floor(framenumber / framesPer10Minutes) m = framenumber % framesPer10Minutes if (m > 1): framenumber=framenumber + (dropFrames * 9 * d) + dropFrames * floor((m-dropFrames) / framesPerMinute) else: framenumber = framenumber + dropFrames * 9 * d; frRound = round(framerate); frames = framenumber % frRound; seconds = floor(framenumber / frRound) % 60; minutes = floor(floor(framenumber / frRound) / 60) % 60; hours = floor(floor(floor(framenumber / frRound) / 60) / 60); tc = "%02d:%02d:%02d:%02d" % (hours, minutes, seconds, frames) return tc def framesToNDF(self): pass kp = KdenParse(args.projectFile) if args.create_edl: kp.createEdl() if args.get_profile: for i in kp.getProjectProfile().keys(): print i + ": " + kp.getProjectProfile()[i] if args.get_producers: for i in kp.getProducers(): print "\n=================\n" for kv in i: print kv + ": " + i[kv] if args.get_kproducers: for i in kp.getKProducers(): print "\n=================\n" for kv in i: print kv + ": " + i[kv] if args.deref_proxy: for i in kp.derefProxy(): print i + ": " + kp.derefProxy()[i] if args.show_links: for i in kp.linkReferences(): print i + ": " + kp.linkReferences()[i] |
Registered users: Bing [Bot], gfielding, Google [Bot], Sogou [Bot]