Quicktime Event Plugin for After Effects

Hello,
We are trying to use the Quicktime Generation Example provided on the thinkbox site. http://www.thinkboxsoftware.com/deadline-5-scripteventssdk/#Quicktime_Generation_Example

We are using 5.2 beta.

At the moment I’m using ExecuteCommandAndGetOutput() and logging that to try to get some insite into why the job isn’t being submitted.

Here is the response I’m getting:

[code]=======================================================
Log Message

INFO: Deadline Slave 5.2 [v5.2.0.47398 R]

Submitting to Repository: /Volumes/RenderFarm/DeadlineRepository

Submission Contains the Following:

  1. Auxiliary File #1 ("/Users/farm8/Deadline/temp/quicktime_plugin_info.job")
  2. Auxiliary File #2 ("/Volumes/RenderFarm/DeadlineRepository/quicktime_export_settings.xml")
    Error: Object reference not set to an instance of an object (System.NullReferenceException)
    at Deadline.Controllers.DeadlineController.JobFromSubmissionInfo (System.Collections.Hashtable submissionInfoHashTable) [0x00000] in :0
    at Deadline.Submission.SubmissionUtils.SubmitNewJob (System.Collections.Hashtable htInfo, FranticX.Collections.Specialized.StringCollection2 auxillarySubmissionFileNames, System.String jobRepositoryDirectory) [0x00000] in :0
    at Deadline.Submission.SubmissionUtils.SubmitNewJob (System.Collections.Hashtable htInfo, FranticX.Collections.Specialized.StringCollection2 auxillarySubmissionFileNames) [0x00000] in :0
    at Deadline.Submission.SubmissionUtils.SubmitNewJob (System.String[] args) [0x00000] in :0
    at Deadline.Submission.Submit.Perform (System.String[] args) [0x00000] in :0

=======================================================
Log Details

Log Date/Time = Jun 01/12 10:43:38
Frames = (no task)

Slave Machine = Farm8
Slave Version = v5.2.0.47398 R

Plugin Name = QuicktimeGen

[/code]

I tried prepending “-notify” to the String Collection of arguments being passed into ExecuteCommand (as I saw in the QuicktimeSubmission.py script) and got this response:

[code]=======================================================
Log Message

INFO: Error: The Deadline main form has not been initialized. Check that this machine has the necessary Mono dependencies installed (like libgdiplus). (System.NullReferenceException)

=======================================================
Log Details

Log Date/Time = Jun 01/12 10:49:27
Frames = (no task)

Slave Machine = Farm1
Slave Version = v5.2.0.47398 R

Plugin Name = QuicktimeGen

[/code]

The plugin is enabled in Monitor. The referenced XML settings work for the standard “Submit Quicktime Job to Deadline” script.

Any help would be greatly appreciated!

Here is the modified event plugin script we are using:

[code]import re

from System.IO import *
from System.Text import *

from Deadline.Events import *
from Deadline.Scripting import *

######################################################################

This is the function that Deadline calls to get an instance of the

main DeadlineEventListener class.

######################################################################
def GetDeadlineEventListener():
return MyEvent()

######################################################################

This is the main DeadlineEventListener class for MyEvent.

######################################################################
class MyEvent (DeadlineEventListener):

def OnJobFinished( self, job ):
	
	movieSettings = GetConfigEntryWithDefault( "QTSettings", "" ).strip()
	
	# Only submit a QT job for finished Nuke jobs, and only if a QT settings file has been set.
	if movieSettings == "" or job.JobPlugin != "AfterEffects":
		return
		
	outputDirectories = job.JobOutputDirectories
	outputFilenames = job.JobOutputFileNames
	paddingRegex = re.compile("[^\\?#]*([\\?#]+).*")
	
	
	# Submit a QT job for each output sequence.
	for i in range( 0, len(outputFilenames) ):
		
		outputDirectory = outputDirectories[i]
		outputFilename = outputFilenames[i]
		outputPath = Path.Combine(outputDirectory,outputFilename).replace("//","/")
		
		# Swap out the padding character for an actual frame.
		m = re.match(paddingRegex,outputPath)
		if( m != None):
			padding = m.group(1)
			frame = StringUtils.ToZeroPaddedString(job.JobFramesList[0],len(padding),False)
			outputPath = outputPath.replace( padding, frame )
		
		inputFilename = outputPath
		movieFilename = Path.ChangeExtension( FrameUtils.GetFilenameWithoutPadding( inputFilename ), ".mov" )
		movieName = Path.GetFileNameWithoutExtension( movieFilename )
		movieFrames = job.JobFrames
		
		# Create job info file.
		jobInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "quicktime_job_info.job" )
		writer = StreamWriter( jobInfoFilename, False, Encoding.Unicode )
		writer.WriteLine( "Plugin=Quicktime" )
		writer.WriteLine( "Name=%s" % movieName )
		writer.WriteLine( "Comment=Auto-submitted QT" )
		writer.WriteLine( "Department=%s" % job.JobDepartment )
		writer.WriteLine( "Pool=%s" % job.JobPool )
		writer.WriteLine( "Group=%s" % job.JobGroup )
		writer.WriteLine( "Priority=%s" % job.JobPriority )
		writer.WriteLine( "MachineLimit=1" )
		writer.WriteLine( "Frames=%s" % movieFrames )
		writer.WriteLine( "ChunkSize=100000" )
		writer.WriteLine( "OutputFilename0=%s" % movieFilename )
		writer.Close()
		
		# Create plugin info file.
		pluginInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "quicktime_plugin_info.job" )
		writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )
		writer.WriteLine( "InputImages=%s" % inputFilename )
		writer.WriteLine( "OutputFile=%s" % movieFilename )
		writer.WriteLine( "FrameRate=24" )
		writer.WriteLine( "Codec=QuickTime Movie" )
		writer.Close()
		
		# Now submit the job.
		tempStr = ClientUtils.ExecuteCommandAndGetOutput( ("-notify", jobInfoFilename,pluginInfoFilename,movieSettings) )
		self.LogInfo(tempStr)

[/code]

After some investigating, I think I’ve got this pegged. I’m guessing you’re either running the Slaves in nogui mode, or as a service? It seems the problem is that Deadline is expecting a Deadline User to be active when submitting a job, which I assume there isn’t in your particular case.

The good news is that it’s an easy fix! All you should have to do is add a line to the Event Plugin specifying which user name Deadline should use as the ‘submitting user’. Let’s say for the sake of example that the user name should be ‘QtAutoSubmit’; you would need to add the following line in the bit of code that builds up the submission file:

writer.WriteLine( "UserName=QtAutoSubmit" )

The final result (based on the modified code you posted) should be like this:

[code]import re

from System.IO import *
from System.Text import *

from Deadline.Events import *
from Deadline.Scripting import *

######################################################################

This is the function that Deadline calls to get an instance of the

main DeadlineEventListener class.

######################################################################
def GetDeadlineEventListener():
return MyEvent()

######################################################################

This is the main DeadlineEventListener class for MyEvent.

######################################################################
class MyEvent (DeadlineEventListener):

def OnJobFinished( self, job ):

  movieSettings = GetConfigEntryWithDefault( "QTSettings", "" ).strip()
  
  # Only submit a QT job for finished Nuke jobs, and only if a QT settings file has been set.
  if movieSettings == "" or job.JobPlugin != "AfterEffects":
     return
     
  outputDirectories = job.JobOutputDirectories
  outputFilenames = job.JobOutputFileNames
  paddingRegex = re.compile("[^\\?#]*([\\?#]+).*")
  
  
  # Submit a QT job for each output sequence.
  for i in range( 0, len(outputFilenames) ):
     
     outputDirectory = outputDirectories[i]
     outputFilename = outputFilenames[i]
     outputPath = Path.Combine(outputDirectory,outputFilename).replace("//","/")
     
     # Swap out the padding character for an actual frame.
     m = re.match(paddingRegex,outputPath)
     if( m != None):
        padding = m.group(1)
        frame = StringUtils.ToZeroPaddedString(job.JobFramesList[0],len(padding),False)
        outputPath = outputPath.replace( padding, frame )
     
     inputFilename = outputPath
     movieFilename = Path.ChangeExtension( FrameUtils.GetFilenameWithoutPadding( inputFilename ), ".mov" )
     movieName = Path.GetFileNameWithoutExtension( movieFilename )
     movieFrames = job.JobFrames
     
     # Create job info file.
     jobInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "quicktime_job_info.job" )
     writer = StreamWriter( jobInfoFilename, False, Encoding.Unicode )
     writer.WriteLine( "Plugin=Quicktime" )
     writer.WriteLine( "Name=%s" % movieName )
     writer.WriteLine( "Comment=Auto-submitted QT" )
     writer.WriteLine( "Department=%s" % job.JobDepartment )
     writer.WriteLine( "Pool=%s" % job.JobPool )
     writer.WriteLine( "Group=%s" % job.JobGroup )
     writer.WriteLine( "Priority=%s" % job.JobPriority )
     writer.WriteLine( "MachineLimit=1" )
     writer.WriteLine( "Frames=%s" % movieFrames )
     writer.WriteLine( "ChunkSize=100000" )
     writer.WriteLine( "OutputFilename0=%s" % movieFilename )
     writer.WriteLine( "UserName=QtAutoSubmit" )
     writer.Close()
     
     # Create plugin info file.
     pluginInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "quicktime_plugin_info.job" )
     writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )
     writer.WriteLine( "InputImages=%s" % inputFilename )
     writer.WriteLine( "OutputFile=%s" % movieFilename )
     writer.WriteLine( "FrameRate=24" )
     writer.WriteLine( "Codec=QuickTime Movie" )
     writer.Close()
     
     # Now submit the job.
     tempStr = ClientUtils.ExecuteCommandAndGetOutput( ("-notify", jobInfoFilename,pluginInfoFilename,movieSettings) )
     self.LogInfo(tempStr)

[/code]

Cheers,

  • Jon

That did the trick.

Thanks, Jon!