This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Bounty pre-proposal: interoperability using AAF

Tags: None
(comma "," separated)
skubi
Registered Member
Posts
3
Karma
0
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
User avatar
Steve Guilford
Registered Member
Posts
207
Karma
0
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.
User avatar
farid
Registered Member
Posts
316
Karma
2
OS
hi

skubi wrote: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:
At this point, I am asking for two things:

- Comments: does this proposal make sense to you?
mm@skubi.net


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


skubi
Registered Member
Posts
3
Karma
0
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]


Bookmarks



Who is online

Registered users: Bing [Bot], gfielding, Google [Bot], Sogou [Bot]