AWS Thinkbox Discussion Forums

Job with Interval don't transfer proper value to draft

Hi,

I realize when i configure the frame range of a job, by exemple “1-10i2”, the value transfer to draft is someting like “1,10,4,6”… So when draft is trying to create the quicktime he’s crashing cause the value transfer isn’t “1-10”.

Do you know how to fix this?

here my script:

[code]import sys
import os
import datetime
import copy
import xml.etree.ElementTree as xml

import Draft
from DraftParamParser import *

print “Draft Version: %s” % Draft.LibraryInfo.Version()

def ResizeWithLetterbox(self, width, height):
if width <= 0:
raise RuntimeError(‘width must be a positive number’)
if height <= 0:
raise RuntimeError(‘height must be a positive number’)
sourceAR = float(self.width) / self.height
destAR = float(width) / height
if sourceAR == destAR:
self.Resize(width, height)
else:
image = copy.deepcopy(self)
if width <= self.width and height <= self.height:
self.Crop(0, 0, width, height)
else:
self.Resize(width,height)
self.SetToColor(Draft.ColorRGBA(0, 0, 0, 1.0))
if sourceAR > destAR:
image.Resize(width,int(round(width/sourceAR)))
else:
image.Resize(int(round(height*sourceAR)),height)
self.CompositeWithPositionAndGravity(image, 0.5, 0.5, Draft.PositionalGravity.CenterGravity, Draft.CompositeOperator.CopyCompositeOp)

Draft.Image.ResizeWithLetterbox = ResizeWithLetterbox

#Returns a list of frames based on the given frameString
def FrameListToFrames( frameString ):
frames = []
frameRangeTokens = re.split( ‘\s+|,+’, frameString )

for token in frameRangeTokens:
	try:
		if ( len(token) > 0 ):
			dashIndex = string.find( token, '-', 1)

			if ( dashIndex == -1 ):
				startFrame = int(token)
				frames.append( startFrame )
			else:
				startFrame = int(token[0:dashIndex])

				m = re.match( "(-?\d+)(?:(x|step|by|every)(\d+))?", token[dashIndex + 1:] )
				if ( m == None ):
					raise StandardError( "Second part of Token '" + token[dashIndex + 1:] + "' failed regex match" )
				else:
					endFrame = int(m.group(1))

					if ( m.group(2) == None ):
						frames.extend( range(startFrame, endFrame + 1 ))
					else:
						dir = 1
						if startFrame > endFrame:
							dir = -1

						byFrame = int(m.group(3));

						frame = startFrame
						while (startFrame * dir) <= (endFrame * dir):
							frames.add( frame )
							frame += byFrame * dir

	except:
		print "ERROR: Frame Range token '" + token + "' is malformed. Skipping this token."
		raise

frames = list(set(frames))
frames.sort()

return frames

#CHANGE ME! Path to the Deadline Repository root
deadlineRepo = “\fx-deadline\deadline\”

#CHANGE ME! Path to an image containing the background of the slate frame
slateFrame = “\\fx-deadline\deadline\Draft\Slate_Montage5K_new.png”
logoFrame = “\\fx-deadline\deadline\Draft\FrimaFX.png”

#The argument name/types we’re expecting from the command line arguments
expectedTypes = dict()
expectedTypes[‘frameList’] = ‘’
expectedTypes[‘inFile’] = ‘’
expectedTypes[‘outFile’] = ‘’
expectedTypes[‘username’] = ‘’
expectedTypes[‘entity’] = ‘’
expectedTypes[‘version’] = ‘’
#expectedTypes[‘deadlineJobID’] = ‘’

#Parse the command line arguments
params = ParseCommandLine( expectedTypes, sys.argv )

inFilePattern = params[‘inFile’]
frames = FrameListToFrames( params[‘frameList’] )

if(True):
(outDir, outFile) = os.path.split(params[‘outFile’])
(outBase, outExt) = os.path.splitext(outFile)

outFolder = os.path.basename(outDir)

if not os.path.exists(os.path.join(outDir, '1080p')):
	os.makedirs(os.path.join(outDir, '1080p'))
if not os.path.exists(os.path.join(outDir, 'halfrez')):
	os.makedirs(os.path.join(outDir, 'halfrez'))
if not os.path.exists(os.path.join(outDir, 'fullrez')):
	os.makedirs(os.path.join(outDir, 'fullrez'))

else:
(outBase, outExt) = os.path.splitext(params[‘outFile’])

outWidth = 1920
outHeight = 1080
halfWidth = 2560
halfHeight = 1350
slateFrames = 1
outLut = Draft.LUT.CreateRec709()

for eye in [‘l’,‘r’]:
#Build up the encoders
outBaseEye = outBase.replace( ‘%v’, eye )
outBaseEyeHalf = outBase.replace( ‘%v’, eye ) + “-Hres”
outBaseEyeFull = outBase.replace( ‘%v’, eye ) + “-Fres”

#Appends (#) on the end of the filename until we have a unique name
increment = 2
newFileName = '%s/1080p/%s%s'%(outDir, outBaseEye, outExt)
while os.path.exists( newFileName ):
	newFileName = '%s/1080p/%s (%d)%s'%(outDir, outBaseEye, increment, outExt)
	increment += 1

#Appends (#) on the end of the filename until we have a unique name
increment = 2
newFileNameHalf = '%s/halfrez/%s%s'%(outDir, outBaseEyeHalf, outExt)
while os.path.exists( newFileNameHalf ):
	newFileNameHalf = '%s/halfrez/%s (%d)%s'%(outDir, outBaseEyeHalf, increment, outExt)
	increment += 1

MJPEGencoder = Draft.VideoEncoder( newFileName, 24.0, outWidth, outHeight, 75000, "MJPEG" )
MJPEGencoderHRes = Draft.VideoEncoder( newFileNameHalf, 24.0, halfWidth, halfHeight, 325000, "MJPEG" )

#Annotation info used for burn ins
annotationInfo = Draft.AnnotationInfo()
annotationInfo.FontType = "Arial"
annotationInfo.PointSize = int( outHeight * 0.017 )
annotationInfo.Color = Draft.ColorRGBA( 1.0, 1.0, 1.0, 1.0 )

#Annotation info used for burn ins
annotationInfoBig = Draft.AnnotationInfo()
annotationInfoBig.FontType = "Arial"
annotationInfoBig.PointSize = int( outHeight * 0.02 )
annotationInfoBig.Color = Draft.ColorRGBA( 1.0, 1.0, 1.0, 1.0 )

#Annotation info used for burn ins
annotationInfoFrame = Draft.AnnotationInfo()
annotationInfoFrame.FontType = "Arial"
annotationInfoFrame.PointSize = int( outHeight * 0.025 )
annotationInfoFrame.Color = Draft.ColorRGBA( 1.0, 1.0, 1.0, 1.0 )

#prep the Slate Frame
try:
	slate = Draft.Image.ReadFromFile( slateFrame )
except:
	slate = Draft.Image.CreateImage( outWidth, outHeight )
	slate.SetToColor( Draft.ColorRGBA( 0.0, 0.0, 0.0, 1.0 ) )
	
if ( slate.width != outWidth or slate.height != outHeight ):
	slate.ResizeWithLetterbox( outWidth, outHeight )
	
#sets up the text on the slate frame
slateAnnotations = [params['entity'], params['version'], params['username'], datetime.datetime.now().strftime("%m/%d/%Y %I:%M %p"), params['frameList']]

for i in range (0, 4):
	annotation = Draft.Image.CreateAnnotation(slateAnnotations[i], annotationInfo)
	slate.CompositeWithPositionAndGravity(annotation, 0.23, 0.446 - (i * 0.03), Draft.PositionalGravity.NorthWestGravity, Draft.CompositeOperator.OverCompositeOp)

annotation = Draft.Image.CreateAnnotation(slateAnnotations[4], annotationInfo)
slate.CompositeWithPositionAndGravity(annotation, 0.327, 0.24, Draft.PositionalGravity.SouthGravity, Draft.CompositeOperator.OverCompositeOp)

oFrameRangeSplit = slateAnnotations[4].split('-')
oFrameCount = str(int(oFrameRangeSplit[1]) - int(oFrameRangeSplit[0]) + 1)
annotation = Draft.Image.CreateAnnotation(oFrameCount, annotationInfoBig)
slate.CompositeWithPositionAndGravity(annotation, 0.251, 0.237, Draft.PositionalGravity.SouthGravity, Draft.CompositeOperator.OverCompositeOp)

#encode the slate frames at the start of the video
print( "Encoding Slate Frames..." )
for i in range( 0, slateFrames ):
	MJPEGencoder.EncodeNextFrame( slate )
	MJPEGencoderHRes.EncodeNextFrame( slate )

studioAnnotation = Draft.Image.CreateAnnotation( "The Ice Age", annotationInfo )
entityAnnotation = Draft.Image.CreateAnnotation( "%s    %s" % (params['entity'], datetime.datetime.now().strftime("%m/%d/%Y")), annotationInfo )
dateAnnotation = Draft.Image.CreateAnnotation( datetime.datetime.now().strftime("%m/%d/%Y"), annotationInfo )
shotAnnotation = Draft.Image.CreateAnnotation(params['entity'], annotationInfo)

try:
	logo = Draft.Image.ReadFromFile( logoFrame )
	logo.Resize(int(0.1852*outHeight), int(0.0657*outHeight))
except:
	logo = Draft.Image.CreateImage( outWidth, outHeight )
	logo.SetToColor( Draft.ColorRGBA( 0.0, 0.0, 0.0, 1.0 ) )

#annotationInfo.BackgroundColor = Draft.ColorRGBA( 0.0, 0.0, 0.0, 1.0 )

#initialize the frame to None
bgFrame = None

#Main encoding loop
for frameNumber in frames:
	print( "Processing Frame: %d...-1" % frameNumber )

	inFile = inFilePattern.replace( '%v', eye )
	inFile = ReplaceFilenameHashesWithNumber( inFile, frameNumber )

	if os.path.exists( inFile ):
		try:
			#try to read in the frame
			bgFrame = Draft.Image.ReadFromFile( inFile )
		except:
			#failed to read in, that's OK, we'll just re-encode the previous frame
			pass

	#create a black frame if we couldn't read in, and don't have a previous frame to encode
	if bgFrame == None:
		bgFrame = Draft.Image.CreateImage( outWidth, outHeight )
		bgFrame.SetToColor( Draft.ColorRGBA( 0.0, 1.0, 0.0, 1.0 ) )
	elif ( bgFrame.width != outWidth or bgFrame.height != outHeight ):
		bgFrame.ResizeWithLetterbox( outWidth, outHeight )

	#Do the frame burnins
	framesAnnotation = Draft.Image.CreateAnnotation( str( frameNumber ), annotationInfoFrame )
	bgFrame.CompositeWithPositionAndGravity( framesAnnotation, 0.825, 0.062, Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )
  
	#don't redo the other burnins, or the LUT since we've already done it for the last frame
	if os.path.exists( inFile ):
		bgFrame.CompositeWithPositionAndGravity( studioAnnotation, 0.0, 1.0, Draft.PositionalGravity.NorthWestGravity, Draft.CompositeOperator.OverCompositeOp )
		bgFrame.CompositeWithPositionAndGravity( dateAnnotation, 0.0, 0.0, Draft.PositionalGravity.SouthWestGravity, Draft.CompositeOperator.OverCompositeOp )
		bgFrame.CompositeWithPositionAndGravity( shotAnnotation, 0.5, 0.0, Draft.PositionalGravity.SouthGravity, Draft.CompositeOperator.OverCompositeOp )

		outLut.Apply( bgFrame )
		
	if os.path.exists( inFile ):	
		bgFrame.CompositeWithPositionAndGravity( logo, 0.95, 0.05, Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )

	MJPEGencoder.EncodeNextFrame( bgFrame )
	MJPEGencoderHRes.EncodeNextFrame( bgFrame )

#Finalize the encoding process
MJPEGencoder.FinalizeEncoding()
MJPEGencoderHRes.FinalizeEncoding()[/code]

Thanks !

Fred

Do you know if this is complicated to solve. It is a pretty big roadblock for us

thks

What does ‘1-10i2’ mean? Is the ‘i2’ a step, as in: 1, 3, 5, 7, 9?

yeah in step. You put this in frame range. As an exemple, the frame range 44-343 will give you

44,343,300,172,108,236,76,140,204,268,332,60,92,124,156,188,220,252,284,316,52,68,84,100,116,132,148,164,180,196,212,228,244,260,276,292,308,324,340,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,45-47,49-51,53-55,57-59,61-63,65-67,69-71,73-75,77-79,81-83,85-87,89-91,93-95,97-99,101-103,105-107,109-111,113-115,117-119,121-123,125-127,129-131,133-135,137-139,141-143,145-147,149-151,153-155,157-159,161-163,165-167,169-171,173-175,177-179,181-183,185-187,189-191,193-195,197-199,201-203,205-207,209-211,213-215,217-219,221-223,225-227,229-231,233-235,237-239,241-243,245-247,249-251,253-255,257-259,261-263,265-267,269-271,273-275,277-279,281-283,285-287,289-291,293-295,297-299,301-303,305-307,309-311,313-315,317-319,321-323,325-327,329-331,333-335,337-339,341-342

Alright! I think you can make this work by replacing FrameListToFrames in your script with:[code]#Returns a list of frames based on the given frameString
def FrameListToFrames( frameString ):
frames = []
frameRangeTokens = re.split( ‘\s+|,+’, frameString )

for token in frameRangeTokens:
    try:
        if ( len(token) > 0 ):
            dashIndex = string.find( token, '-', 1)

            if ( dashIndex == -1 ):
                startFrame = int(token)
                frames.append( startFrame )
            else:
                startFrame = int(token[0:dashIndex])

                m = re.match( "(-?\d+)(?:(x|step|by|every|i)(\d+))?", token[dashIndex + 1:] )
                if ( m == None ) :
                    raise StandardError( "Second part of Token failed regex match" )
                else:
                    endFrame = int(m.group(1))

                    if ( m.group(2) == None ):
                        frames.extend( range(startFrame, endFrame + 1 ))
                    else:
                        dir = 1
                        if startFrame > endFrame:
                            dir = -1

                        byFrame = int(m.group(3));

                        frame = startFrame
                        while (frame * dir) <= (endFrame * dir):
                            frames.append( frame )
                            frame += byFrame * dir

    except:
        print "ERROR: Frame Range token '" + token + "' is malformed. Skipping this token."
        raise

frames = list(set(frames))
frames.sort()

return frames[/code]

I’ve attached a new version of your script that includes this change. Does it do what you want?
acrylic_cow_job_interval.zip (3.02 KB)

I’ll come back to you with the results !

No it didn’t work. I dont think the modification is in the template but more right into draft. Because even if you change something in the template, the bug apper in the submission window.

Maybe i don’t explain my problem properly.

I submit a job with a draft script
The job frame range is 1-100i2
if i go on that job, right click script, submit draft to deadline.

In the submitter window, the frame range will be already enter, and it is 1-100i2, not 1-100.

Wich cause draft to crash while encoding the movie.

Thks,

Fred

Hey Fred,

I’ve updated the Event Plugin and Job Right-Click submitter to strip out any interleaving in the Frame Ranges when pulling it from a previous Job (ie, if the original Deadline Job was “1-100i3”, it should pull over as “1-100”).

Just extract the attached zip files to their appropriate folders in the Repository (do a backup of the originals, as usual):
scripts/Jobs/JobDraftSubmission/JobDraftSubmission.py
events/Draft/Draft.py

Let me know how it goes!

Cheers,

Cool thks :slight_smile: !

It does not work, when i right click the job, and go to script, submit draft, the value pass is still 1-100i2

Hmm, sorry about that. I misunderstood how it was pulling over the frame string, I think; I was thinking it was pulling over the string literally as “1-100i2”, but it seems to be expanding it as “1, 100, 65, 33…”. Sorry!

Anyways, I’ve made another change to the scripts and this time it should work for all kinds of different frame strings; it just takes them all and re-parses them into an optimized frame string.

Same deal as last time for which scripts to update.

Cheers,

Thks ! Works well

Hi,

i realise that now, when i use a intervelate frame range (ex: 1-100i2), the proper value is been transfer to draft.
But if we do a frame range like this one : 43-293x2, wich give us the framelist 43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,257,259,261,263,265,267,269,271,273,275,277,279,281,283,285,287,289,291,293
, the same value gets transfer to draft instead of 43-293.

Also as is discuss with you in this other thread (viewtopic.php?f=127&t=7723&start=20)
if we do a job with the frame range of 143-184,272-305, deadline dosn’t transfer the proper frame range, which is suppose to be 143-305.

Thanks !

Fred

Hey Fred,

If this is the behaviour you’re looking for, you can base your scripts around the ‘startFrame’ and ‘endFrame’ parameters that Deadline already passes into your Draft template. ‘startFrame’ is the smallest frame in ‘frameList’, and ‘endFrame’ is the largest, so if all you ever want to deal with are contiguous frame ranges (ie, 1-100), and don’t care that there might be missing frames in the middle somewhere, you should use those values in your template, instead of ‘frameList’.

Based on the template you posted earlier in this thread, you could change this block:

[code]
expectedTypes = dict()
expectedTypes[‘frameList’] = ‘’
expectedTypes[‘inFile’] = ‘’
expectedTypes[‘outFile’] = ‘’
expectedTypes[‘username’] = ‘’
expectedTypes[‘entity’] = ‘’
expectedTypes[‘version’] = ‘’
#expectedTypes[‘deadlineJobID’] = ‘’

#Parse the command line arguments
params = ParseCommandLine( expectedTypes, sys.argv )

inFilePattern = params[‘inFile’]
frames = FrameListToFrames( params[‘frameList’] )[/code]

To something like this:

expectedTypes = dict()
expectedTypes['frameList'] = '<string>'
expectedTypes['inFile'] = '<string>'
expectedTypes['outFile'] = '<string>'
expectedTypes['username'] = '<string>'
expectedTypes['entity'] = '<string>'
expectedTypes['version'] = '<string>'
#expectedTypes['deadlineJobID'] = '<string>'
expectedTypes['startFrame'] = '<int>'
expectedTypes['endFrame'] = '<int>'

#Parse the command line arguments
params = ParseCommandLine( expectedTypes, sys.argv )

inFilePattern = params['inFile']

#Change the 'frameList' param, in case it's used elsewhere
params['frameList'] = "%d-%d" % (params['startFrame'], params['endFrame'])

#Just generate our array of frames using Python's range function
frames = range( params['startFrame'], params['endFrame'] + 1 )

That should essentially behave by ‘filling in’ any gaps in any frame range you pass to it.

Cheers,

  • Jon
Privacy | Site terms | Cookie preferences