Convert to Hold keyframes, output frames in between

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
lya98
Posts: 15
Joined: December 7th, 2006, 10:39 pm

Hi All,

I'd like to write a script that would automate a couple repetitive tasks I have to do for each animation I create.

1. I'd like to be able to select a number of adjacent keyframes on a single layer and have them converted into hold keyframes

2. Have each hold keyframe rendered out (using an output template) as a still.

3. For each keyframe, I'd like the script to output the number of the hold keyframe in the sequence and the number of frames between it and the next hold keyframe. This would be output to a text file that contained this information for each keyframe. The end of the text file would contain the total number of frames between the first and last keyframe in the sequence. So if there were three hold keyframes and there were five frames between each keyframe the text file would look like:
1, 5
2, 5
3, 5
15

Any suggestions or snippets of code would be very appreciated. Thank you!
Paul Tuersley
Posts: 704
Joined: June 5th, 2004, 7:59 am
Location: London, UK

Generally, you'd be better off if you started writing the script and posted more specific questions when you get stuck. You're unlikely to get much response otherwise.

But just this time :)

Here's a script that does what you want. It only checks the Position property for keyframes. You can change that to one of the other main transform properties in the first lines of the script. I've had to split this script into two parts as it was too big. Part two is in a later post. Paste both parts into a text file then save with a .jsx extension.

PART ONE

Code: Select all

{
	// choose the output module template
	var setOutputModule = "Photoshop";
	var fileExtension = ".psd"
	
	// choose the keyframed property
	var chosenProperty = "Position";

	// define variables
	var activeItem = app.project.activeItem;
	var renderQ = app.project.renderQueue;
	var keyIndices, theLayer, theProperty, theRender;
	var outType = KeyframeInterpolationType.HOLD;
	var inType, logString = "";
	
	var retStr = "\r";	
	if (system.osName != "MacOS") { retStr = "\r\n"; }
	
	// make sure a comp is active
	if (!activeItem instanceof CompItem)
	{
		alert("Select keyframes on a single layer before running this script.");
	}
	else
	{	
		// make sure one layer is selected
		if (activeItem.selectedLayers.length != 1)
		{
			alert("Select keyframes on a single layer before running this script.");
		}
		else
		{	
			// define variables for the layer and its Position property
			theLayer = activeItem.selectedLayers[0];		
			theProperty = theLayer.property("Transform").property(chosenProperty);
			
			// grab an array of selected key indices
			keyIndices = theProperty.selectedKeys;
			
			// make sure there are some keyframes selected
			if (keyIndices.length == 0)
			{	
				alert("Select keyframes on a single layer before running this script.");
			}
			else
			{
				// get the user to choose an output folder
				var theFolder = Folder.selectDialog("Choose Output Folder");
				
				// end script if they cancelled the dialog
				if (theFolder != null)
				{
					// start an undo group
					app.beginUndoGroup("Hold Keyframes and Output");

					// loop through each of the selected keyframes
					for (var x = 0; x <keyIndices.length; x++)
					{
END OF PART ONE
Last edited by Paul Tuersley on April 18th, 2007, 7:58 am, edited 1 time in total.
Paul Tuersley
Posts: 704
Joined: June 5th, 2004, 7:59 am
Location: London, UK

I just noticed the script isn't writing the last line of the text file in the way you described. I'll leave you to figure that one out.
lya98
Posts: 15
Joined: December 7th, 2006, 10:39 pm

Wow! That was way beyond anything I expected. Thanks a lot Paul! I'll take your advice the next time I post.
Paul Tuersley
Posts: 704
Joined: June 5th, 2004, 7:59 am
Location: London, UK

I just noticed that a section in the middle of the script was missing, presumably because it was too big to fit in one "code" container. You'll need to paste both parts of the code into a text doc and save with a .jsx extension.

PART TWO

Code: Select all

						// grab the current in interpolation for this keyframe
					 	inType = theProperty.keyInInterpolationType(keyIndices[x]);
					 	
						// set the keyframes out interpolation to hold
						theProperty.setInterpolationTypeAtKey(keyIndices[x], inType, outType);

						// add comp to the render queue
						theRender = renderQ.items.add(activeItem);
						
						// set start and end time for this frame
						theRender.timeSpanStart = theProperty.keyTime(keyIndices[x])
						theRender.timeSpanDuration = activeItem.frameDuration;
						
						// grab the output module
						theOutputModule = theRender.outputModules[1];
						
						// apply the chosen output module template
						theOutputModule.applyTemplate(setOutputModule);	
						
						// create file path and name
						theOutputModule.file = new File(theFolder.absoluteURI + "/" + activeItem.name + "_" + (x+1) + "_\[####\]" + fileExtension);

						if (x > 0)
						{
							// assemble text string for one line of the log report
							logString += x + ", " + ((theProperty.keyTime(keyIndices[x])-theProperty.keyTime(keyIndices[x-1])) / activeItem.frameDuration) + retStr;

							// if this is the last keyframe, also add the last held keyframe number
							if ( (x + 1) == keyIndices.length)
							{
								logString += String(x+1);
							}
						}	
					}
					// save the text log in the output folder
					// define the file path and name
					var theLogFile = new File(theFolder.absoluteURI + "/" + activeItem.name + "_LOG.txt");
					// make sure it's valid
					if (theLogFile != null)
					{
						// open the file and write the text log string
						theLogFile.open("w","TEXT","????");
						theLogFile.write(logString);
						// close and execute (this will open) the log file.		
						theLogFile.close();
						theLogFile.execute();
					}
					// end the undo group			
					app.endUndoGroup();			
				}	
			}
		}
	}
}
END OF PART TWO
Post Reply