Notifications
Clear all

[Closed] Post-Render script…

Yea I do comment out the display section when I use the netrendering.

I am having a new problem now though. It seems the first node to finish there assigned tasks runs the script and I need it to be the last node to run it or I need them to make sure the job is finished first. I am thinking that finding the number of frames to be rendered and then checking to makes sure they are all done before running the script might work. I am also trying some netrendering stuff to check to see if the job is complete before running. But I am having a hard time getting exactly what I want from either of them. Then nedrendering stuff only brings back an array finished jobs not the job that was submitted. And as for the frame numbers I cant seem to find a way to pull that number out and then check to see if there are that many frames. Anywone have any suggestions or ideas?

Yeah, figured you might run into that… your best bet is probably to submit another job that runs the script when the original job is done. Unfortunately, you can’t easily set dependencies of one job or another via scripting. You can if you install third party external functionality, such as Python used in this thread:
http://forums.cgsociety.org/showthread.php?f=98&t=692735&highlight=dependency
Edit: err for existing jobs, anyway – for new jobs, you can submit it -with- the depencies using the command line utility

Alternatively, you could set it up by checking, after each rendered frame, whether all frames are present in the output folder… and only continue if all frames are indeed present. There’s a very, very small chance that a machine is actually in the process of writing out a frame, and an even smaller chance still that you would hit that frame in the quicktime generation in the middle of that process… but a sleep() might be a reasonable safeguard.

Here what I have come up with thanks to your link to another thread. The only issue I am having is attaching the script to the dependant job.

– Created: 13-10-2008
– Last Updated: 13-11-2008
– Version: 0.14

– Author : Johan Boekhoven / johan.boekhoven [at] gmail [dot] com / subd.nl
– Version: 3ds max 2009 (11)

– Discription: Submits scene to backburner
– Usage: Just run to submit

– Credits: Helpfile / cgtalk

–*********************************************** ******************************************
– MODIFY THIS AT YOUR OWN RISK
(
/* CONNECT TO THE NETWERK MANAGER */
m = netrender.getmanager()
c1 = m.connect #automatic “255.255.255.0”

– Batch it max (PEN) runs through a folder of files opening them and submitting them via this script
localFileName = maxFilePath + maxFileName

– Will be used in the mxs submit and dosCommand dependencies!
x = 1
jobName = (filterString maxFileName “.” )[1] –+ execute “x += 1” as string

/* WHEN CONNECTION AND FILE SUCCESFULLY COPIED /
if c1 then
(
/
SUBMIT JOB */
– Easy BB submit
job = m.newjob file:localFileName
job.name = jobName
job.includeMaps = true –turn on “Include Maps”
job.submit() –this uses all servers for the job

/* FILE SETTINGS */
scriptJobName1 = jobName + “_UncompressedMov”

/* OUTPUT1 – UNCOMPRESSED MOV */
– Build stringStream
jobString1 = stringStream “”

– Create jobname
format “-jobName:% ” scriptJobName1 to:jobString1
– SET THE DEPENDENCY!
format “-dependencies:% ” jobName to:jobString1

– Add netmask
format “-netmask:255.255.255.0 ” to:jobString1

–add the render script
format “-scriptFile:\\Tta_server\3d model library\Scripts\AutoQuickTIme\autoquicktimeNetwork.ms ” to:jobString1
print jobString1

– cmdJob is in the backburner folder
maxRoot = “C:\Program Files\backburner 2\”
– Build command string
cmd = “cmdjob.exe ” + (jobString1 as string) + ” startpath:” + maxroot + ” prompt:Submitted to backburner via commandprompt”
print cmd

– Execute it
DOSCommand cmd

)
)

It seems like it should work becuse when it prints it looks good. I must be writing the -scriptfile section wrong.

on further thought I decided to go with the seep() option you mentioned. I will have wait and test it to know for sure though.

/get the number of frames to be rendered/
–check to see what the time output is set to
reTime = rendTimeType
–if it is sent to animation rage then get the number of frames
if (reTime == 3 ) then (
numFrames = rendEnd
s1 = “000” + numFrames as string
s2 = “f”
s3 = “”
FrameNum = substituteString s1 s2 s3
)

–if it is sent to active time segment then get the number of frames
if (reTime == 2 ) then (
numFrames = AnimationRange.end
s1 = “000” + numFrames as string
s2 = “f”
s3 = “”
FrameNum = substituteString s1 s2 s3
)

– if the file exists then run
LastFrame = doesFileExist ((getFilenamePath rendOutputFilename) + (getFilenameFile rendOutputFilename) + FrameNum as String + (getFilenameType rendOutputFilename))
if( LastFrame == true) then (
–pause for 10 seconds to make sure all the frames are done
Print “sleeping”
sleep 10
– get the files rendered
files = getFiles ((getFilenamePath rendOutputFilename) + (getFilenameFile rendOutputFilename) + “*” + (getFilenameType rendOutputFilename))
– remove any still we might have rendered
if (files.count > 1) then (
stillIndex = findItem files rendOutputFilename
if (stillIndex != 0) then ( deleteItem files stillIndex )
– make sure the frames are in the correct order
sort files
)
– create an IFL
x = 01
iflName = getFilenamePath rendOutputFilename + getFilenameFile rendOutputFilename + execute “x += 1” as string + “.ifl”
iflFile = createFile iflName
for f in files do ( format “%
” f to:iflFile )
close iflFile

– open the IFL as a bitmap
iflBitmap = openBitmap iflName

– create an output bitmap
movBitmap = bitmap iflBitmap.width iflBitmap.height
– create a mov filename
movName = “\\Tta_server\3d model library\AdobeWatch\” + getFilenameFile rendOutputFilename + execute “x += 1” as string + “.mov”
– delete pre-existing quicktime mov
deleteFile movBitmap.filename
– set its name to the mov filename
movBitmap.filename = movName

– loop through its frames
for i = 0 to (iflBitmap.numFrames – 1) do (
iflBitmap.frame = i
– get the ifl’s frame into the mov bitmap
copy iflBitmap movBitmap
– save out the mov bitmap (appends as new frame)
save movBitmap frame:i
)

– close the mov so it is finalized
close movBitmap
)

Wrong again. works great with one node on the farm but it still does nothing if there are more nodes. Any ideas? I am also trying some job submission with dependancies but cant get the script to attach to the dependancy.

/*get the number of frames to be rendered*/
 --check to see what the time output is set to  
 reTime = rendTimeType
 --if it is set to animation rage then get the number of frames
 if (reTime == 3 ) then (
 	st = rendStart
 	en = rendEnd
 	numFrames = (en - st)
 	s1 = "0" + numFrames as string
 	s2 = "f"
 	s3 = ""
 	FrameNum = substituteString s1 s2 s3
 )
 --if it is set to active time segment then get the number of frames
 else if (reTime == 2 ) then (
 	animS = animationRange.start 
 	animE = animationRange.end
 	numFrames = (animE - animS)
 	s1 = "0" + numFrames as string
 	s2 = "f"
 	s3 = ""
 	FrameNum = substituteString s1 s2 s3
 )
 
 -- Get the files rendered
 FileLoc = getFiles ((getFilenamePath rendOutputFilename) + (getFilenameFile rendOutputFilename) + "*" + (getFilenameType rendOutputFilename))
 --get the amount of files done and convert it to a number minus one
 FramesDone = FileLoc.count as integer - 1
 NewFrameNum = FrameNum as integer
 
 if (FramesDone == NewFrameNum) then (
 		--pause for 1 minute to make sure all the frames are done
 		sleep 60
 		--get the files rendered
 		files = getFiles ((getFilenamePath rendOutputFilename) + (getFilenameFile rendOutputFilename) + "*" + (getFilenameType rendOutputFilename))
 	
 						-- remove any still we might have rendered
 						if (files.count > 1) then (
 							stillIndex = findItem files rendOutputFilename
 							if (stillIndex != 0) then ( deleteItem files stillIndex )
 							-- make sure the frames are in the correct order
 							sort files
 						)
 						
 		-- create an IFL
 		iflName = getFilenamePath rendOutputFilename + getFilenameFile rendOutputFilename + ".ifl"
 		iflFile = createFile iflName
 		for f in files do ( format "%
" f to:iflFile )
 		close iflFile
 
 	-- open the IFL as a bitmap
 	iflBitmap = openBitmap iflName
 
 	-- create an output bitmap
 	movBitmap = bitmap iflBitmap.width iflBitmap.height
 	-- create a mov filename
 	movName = "\\\\Tta_server\\3d model library\\AdobeWatch\\" + getFilenameFile rendOutputFilename + ".mov"
 	-- delete pre-existing quicktime mov
 	deleteFile movBitmap.filename
 	-- set its name to the mov filename
 	movBitmap.filename = movName
 
 	-- loop through its frames
 	for i = 0 to (iflBitmap.numFrames - 1) do (
 		iflBitmap.frame = i
 		-- get the ifl's frame into the mov bitmap
 		copy iflBitmap movBitmap
 		-- save out the mov bitmap (appends as new frame)
 		save movBitmap frame:i
 		)
 
 -- close the mov so it is finalized
 close movBitmap
 )

Here is what I have for submiting a job and adding the dependancy. I got most of this code from another thread it was written by Johan Boekhoven / johan.boekhoven [at] gmail [dot] com / subd.nl


  (
	  /* CONNECT TO THE NETWERK MANAGER */
	  m = netrender.getmanager()
	  c1 = m.connect #automatic "255.255.255.0"
	  
	  -- Batch it max (PEN) runs through a folder of files opening them and submitting them via this script
	  localFileName = maxFilePath + maxFileName
	  
	  -- Will be used in the mxs submit and dosCommand dependencies!
	  jobName = (filterString maxFileName "." )[1] --  < add some extra string here to allow to sent unique jobs
	  
	  /* WHEN CONNECTION AND FILE SUCCESFULLY COPIED */
	  if c1 then
	  (
		  /* SUBMIT JOB */
		  -- Easy BB submit
		  job = m.newjob file:localFileName
		  job.name = jobName
		  job.includeMaps = true --turn on "Include Maps"
		  job.submit() --this uses all servers for the job
		  
		
		  /* FILE SETTINGS */

		  scriptJobName1 = jobName + "_UncompressedMov"
  
		  /* OUTPUT1 - UNCOMPRESSED AVI */
		  -- Build stringStream
		  jobString1 = stringStream ""
		  
		--attach the script pretty sure this is the wrong way to do this
		files = getFiles "\\\\Tta_server\\3d model library\\Scripts\\AutoQuickTIme\\autoquicktimeFinale121608.ms"
		for file in files do fileIn file
			
		  -- Create jobname
		  format "-jobName:% " scriptJobName1 to:jobString1

		  -- SET THE DEPENDENCY!
		  format "-dependencies:% " jobName to:jobString1
		  
		  -- Add netmask
		  format "-netmask:255.255.255.0 " to:jobString1
  
		  -- This is probably wrong since cmdJob is in the backburner folder, but it works.... I should check that out!
		  maxRoot = "C:\\Program Files\\Autodesk\\backburner\\jobs\\"
		  
		  -- Build command string
		  cmd = "cmdjob.exe " + (jobString1 as string) + " startpath:" + maxroot + " prompt:Submitted to backburner via commandprompt"
		  
		  -- Execute it
		  DOSCommand cmd
  
	  )
  )

I haven’t read the thread so feel free to pay no attention if I’m way off base. Can’t you just render frames to an uncompressed AVI and then use a command-line encoder (Mencoder or ffmpeg) to convert to a .mov/.mp4 file? Then again I haven’t taken the time to read the thread to get context on what you have to do, but I thought I’d just throw that out there.

yes he could – which would take the minor part of loading the images and saving to quicktime, via script, out of the equation

That depends. We need to render through our render farm which has multiple nodes so I belive the only way to do this is to render an image sequence first. Unless I am mistken that is.

I also dont need .mov if I could get an uncompressed .avi that would be fine. I just need a file format that adobe media encoder can read.

The end result here is just to automate the process of convert image sequences to .flv files. Which is what all are work needs to be at the end of our pipline. So if there is a command line encoder that could do that I would need to write this script anymore. I know adobe has a solution for this but it is around $6,000. and my company is pretty small so I am just rying to find a workaround and save all the man hours we spend setting at our computers using photoshop to encode .flv’s.

Writing frames to an uncompressed avi is really easy, actually. You just need to render frames, and this is what I do:


fn createSequence animBmpFilename bmpArr width height =
(
	local animBmp = bitmap width height filename:animBmpFilename
	for i = 1 to bmpArr.count do
	(
		copy (openBitmap bmpArr[i]) animBmp
		save animBmp frame:i
	)
	close animBmp
)

There’s probably a way to get the width and height from the file without having to pass them in. animBmpFilename is something like “C:\ empComp.avi” and bmpArr is an array of bitmap filenames. Make sure you have the save <bitmap> frame:<integer> in there or you will run into memory issues.

Page 3 / 4