AWS Thinkbox Discussion Forums

Frame count int the bottom center

Hi, in this 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 dictionary of a Deadline Job’s properties
def getDeadlineJob (job, repository):
deadlineJobPath = (repository + “\jobs\” + job + “\” + job + “.job”)
jobKeys = (xml.parse(deadlineJobPath)).getroot()
jobDict = {}
for o in list(jobKeys):
if len(o.getchildren()) < 1:
jobDict[o.tag] = o.text
else:
jobDict[o.tag] = []
for t in list(o):
(jobDict[o.tag]).append(t.text)
jobDict[‘deadlineJobPath’] = deadlineJobPath
return jobDict

#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.add( 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.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’])

#not a huge deal if we can’t connect to the repo, we’ll just be missing some info
try:
jobParams = getDeadlineJob( params[‘deadlineJobID’], deadlineRepo )
except:
jobParams = {}

outWidth = 1920
outHeight = 1080
fullWidth = 5120
fullHeight = 2700
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)
    #newFileName = "%s (%d)%s" % (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)
    #newFileNameHalf = "%s (%d)%s" % (outBaseEyeHalf, increment, outExt)
    increment += 1

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

MJPEGencoder = Draft.VideoEncoder( newFileName, 24.0, outWidth, outHeight, 75000, "MJPEG" )
MJPEGencoderHRes = Draft.VideoEncoder( newFileNameHalf, 24.0, halfWidth, halfHeight, 225000, "MJPEG" )
#MJPEGencoderFRes = Draft.VideoEncoder( newFileNameFull, 24.0, fullWidth, fullHeight, 350000, "MJPEG" )
    #Annotation info used for burn ins
annotationInfo = Draft.AnnotationInfo()
annotationInfo.FontType = "Times-New-Roman"
annotationInfo.PointSize = int( outHeight * 0.022 )
annotationInfo.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 = [
     ("SHOW", jobParams.get('ExtraInfo1', '<SKIP>')), #This line is skipped if there is not ExtraInfo1
     ("Episode", params.get('episode', '<SKIP>')), #This line is skipped if 'episode' isn't in the extra args
     ("Shot", params['entity']),
     ("Frames", params['frameList']),
     ("Handles", params.get('handles', '<SKIP>')), #This line is skipped if 'handles' isn't in the extra args
     ("Version", params['version']),
     ("",''),
     ("",''),
     ("Artist", params['username']),
     ("Date", datetime.datetime.now().strftime("%m/%d/%Y %I:%M %p") )
   ]

#comp the annotations over top the slate frame
skipLines = 0
for i in range( 0, len( slateAnnotations ) ):
    annotationTuple = slateAnnotations[i]

    if ( annotationTuple[1] == "<SKIP>" ):
        skipLines += 1
        continue

    lineNum = i - skipLines
    if ( annotationTuple[0] != "" ):
        annotation = Draft.Image.CreateAnnotation( slateAnnotations[i][0] + ": ", annotationInfo )
        slate.CompositeWithPositionAndGravity( annotation, 0.45, 0.7 - (lineNum * 0.06), Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )

    if ( annotationTuple[1] != "" ):
        annotation = Draft.Image.CreateAnnotation( slateAnnotations[i][1], annotationInfo )
        slate.CompositeWithPositionAndGravity( annotation, 0.46, 0.7 - (lineNum * 0.06), Draft.PositionalGravity.SouthWestGravity, Draft.CompositeOperator.OverCompositeOp )

outLut.Apply( slate )

#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 )
    #MJPEGencoderFRes.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 )
annotationInfo.BackgroundColor = Draft.ColorRGBA( 0.0, 0.0, 0.0, 1.0 )

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

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

    #check if the file exists
    blackFrame = ( not os.path.exists( inFile ) )

    if not blackFrame:
        try:
            #try to read in the frame
            bgFrame = Draft.Image.ReadFromFile( inFile )
        except:
            #failed to read in, encode a black frame instead
            blackFrame = True

    #create a black frame if we weren't able to read it in
    if blackFrame:
        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 ), annotationInfo )
    bgFrame.CompositeWithPositionAndGravity( studioAnnotation, 0.0, 1.0, Draft.PositionalGravity.NorthWestGravity, Draft.CompositeOperator.OverCompositeOp )
    bgFrame.CompositeWithPositionAndGravity( entityAnnotation, 0.0, 0.0, Draft.PositionalGravity.SouthWestGravity, Draft.CompositeOperator.OverCompositeOp )
    bgFrame.CompositeWithPositionAndGravity( framesAnnotation, 1.0, 0.0, Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )

    outLut.Apply( bgFrame )

    MJPEGencoder.EncodeNextFrame( bgFrame )
    MJPEGencoderHRes.EncodeNextFrame( bgFrame )
    #MJPEGencoderFRes.EncodeNextFrame( bgFrame )
 
#Finalize the encoding process
MJPEGencoder.FinalizeEncoding()
MJPEGencoderHRes.FinalizeEncoding()
#MJPEGencoderFRes.FinalizeEncoding()

[/code]

is it possible to place the frame count in the middle of the bottom ?

Thanks,

Fred

Sure thing! In this line: bgFrame.CompositeWithPositionAndGravity( framesAnnotation, 1.0, 0.0, Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )
Change the “PositionalGravity.SouthEastGravity” to “PositionalGravity.SouthGravity”: bgFrame.CompositeWithPositionAndGravity( framesAnnotation, 1.0, 0.0, Draft.PositionalGravity.SouthGravity, Draft.CompositeOperator.OverCompositeOp )

it dosen’t work. The frame count is still at the right, but his doing a king of gigeling and i cant sell all of the numbers.

Oh! Sorry, I misread the script. Please try this instead:

bgFrame.CompositeWithPositionAndGravity( framesAnnotation, 0.5, 0.0, Draft.PositionalGravity.SouthEastGravity, Draft.CompositeOperator.OverCompositeOp )

I changed the x coordinate from 1.0 (right) to 0.5 (middle). The “SouthEastGravity” part means that it will put the bottom-left corner of the framesAnnotation at the specified position. The image will then grow to the left of center. If you want the framesAnnotation to be exactly centered instead, you can change it to “SouthGravity” instead.

works very well thanks :slight_smile:

Privacy | Site terms | Cookie preferences