Page 1 of 1

timeToCurrentFormat bug?

Posted: July 25th, 2010, 8:46 pm
by cob906
The problem:

While creating a script within After Effects CS3, I noticed that there were certain instances where the global function timeToCurrentFormat would return the same value for different seconds values. It makes sense, of course, for seconds values that differ only slightly to return the same value if indeed the difference in the seconds values are not greater than the length of a frame in seconds. However, the time values that I was using within the timeToCurrentFormat function's first parameter were found by getting the time value of a layer's marker through the AE Object Model.

There were certain seemingly arbitrary instances where, even though the time values of two markers were obtained from markers that were a frame a part, the same value was returned by the timeToCurrentFormat function for each of the markers. What's more confusing, even though the project's start time frame is set to 0, the timeToCurrentFormat function returns different values when the isDuration parameter is set to true.

The test:

To test this weird behavior, I setup a test by finding the length of a frame (1 divided by the composition's frameRate: 1 / 29.9700012207031 = 0.03336669867431) and utilizing a loop to go through 30 seconds worth of frames to find the corresponding frame value returned by the timeToCurrentFormat function. I quickly realized that this test was going to be unreliable since the 29.97 frame rate utilizes a drop frame. Therefore, I instead used the loop to create markers on a layer for each frame for 30 seconds, looped through all of the layer's markers, obtained their time value and used it in the timeToCurrentFormat function. Below is a link to a spreadsheet that I created that represents the time values (in seconds) taken from markers that, for 30 seconds, were spaced 1 frame apart (901 markers in all). I've also attached the After Effects CS3 file I was working with.

A link to the data can be found here:
http://spreadsheets0.google.com/ccc?key ... l=en#gid=1
timeToCurrentFormat_test.aep.zip
(17.53 KiB) Downloaded 860 times
The findings:

First, here is my current working environment:

After Effects Version: After Effects CS3 8.0.2.2.7 dva: 2.0.0.127845
OS: Mac OSX 10.5.08
QT: 7.6.6

Here is a set of descriptions for each of the header rows within the data to help you decipher and understand what is going on:

Key ID: - This column contains the index of the current marker whose time value is being referenced.
Marker Creation Time: - This column contains the seconds value that was used to create the current marker on the "Test" layer. It is provided to demonstrate that the time listed under "Marker Time Value" is not calculated based upon the time value used to create the marker.
Marker Time Value: - This column contains the seconds value that is returned by referencing the keyTime(keyIndex) method of the "Test" layer's "Marker" property. As stated above, this value is not calculated based upon the time value that the marker was created with.
timeToCurrentFormat W/ True: - This column contains the frame number returned by the timeToCurrentFormat function when it's isDuration parameter is set to true.
Matches Previously Calculated Frame: - This column contains an "*" if the current marker's "timeToCurrentFormat W/ True" value matches the same value in the previous iteration of the loop. These fields have been highlighted in red in the data.
timeToCurrentFormat Default: - This column contains the frame number returned by the timeToCurrentFormat function when it's isDuration parameter is not set (which then defaults to false).
Matches Previously Calculated Frame: - This column contains an "*" if the current marker's "timeToCurrentFormat Default" value matches the same value in the previous iteration of the loop. These fields have been highlighted in red in the data.
currentFormatToTime W/ True: - This column contains the value returned by the currentFormatToTime function when it's isDuration parameter is set to true. The frame value that is used within the function's first parameter is pulled from the current iteration's "timeToCurrentFormat W/ True" value.
Matches Initial Seconds Value: - This is used to determine whether the time value ("Marker Time Value") that is sent through the timeToCurrentFormat function (with isDuration set to true) is reproduced correctly when the value returned by the timeToCurrentFormat function is run through the currentFormatToTime function (with isDuration set to true).
currentFormatToTime Default: - This column contains the value returned by the currentFormatToTime function when it's isDuration parameter is not set (which defaults to false). The frame value that is used within the function's first parameter is pulled from the current iteration's "timeToCurrentFormat Default" value.
Matches Initial Seconds Value: - This is used to determine whether the time value ("Marker Time Value") that is sent through the timeToCurrentFormat function (with isDuration not set) is reproduced correctly when the value returned by the timeToCurrentFormat function is run through the currentFormatToTime function (with isDuration not set).

From the data, i've come to believe the calculations done within the timeToCurrentFormat function are not accurate. Although I've tried to rule out any error on my part by only using values returned by properties and methods within the AE Object Model, it is quite possible I have made a mistake somewhere along the line; hence the reason I'd like to share my findings and allow everyone to comment. Ultimately, I need the timeToCurrentFormat function to work properly in order to complete the script that I'm working on. Therefore, if you notice any errors within my coding, don't be shy, I won't be offended.

The scripts:

The script I used to create the markers:

Code: Select all

{
//Before running this script, create a composition and then add
//a null layer named "Test"
var comp = app.project.activeItem,
	info = "",
	layer = comp.layer("Test"),
	frameRate = comp.frameRate,
	i;
	
	for (i = 0; i <= comp.duration; i += (1/frameRate))
	{
		layer.property("Marker").setValueAtTime(i, new MarkerValue(i));
	}
}
The script used to create the data (copy and paste the results it into a spreadsheet):

Code: Select all

{
	//Using the composition and "Test" layer created by the previous script
	var comp = app.project.activeItem,
		info = "",
		layer = comp.layer("Test"),
		markerRef, markerTime, markerFrame,
		maxSeconds = 30,
		frameRate = comp.frameRate,
		numKeys,
		i,
		timeToCurrentFormatTrue,
		timeToCurrentFormatDefault,
		currentFormatToTimeTrue,
		currentFormatToTimeDefault,
		keyId,
		keyTime,
		prevTimeToCurrentFormatTrue = null,
		prevTimeToCurrentFormatDefault = null,
		usersTimecodeType;
	
	//Get the user's timecode display type so we can change it back when
	//we're done.
	usersTimecodeType = app.project.timecodeDisplayType;	
	
	//Set the current timecode display type to frames
	app.project.timecodeDisplayType = TimecodeDisplayType.FRAMES;
	
	alertInfo = function (m)
    {
		myWindow = new Window("dialog",
			"Info",
			undefined,
			{resizeable: false}
		);

		myWindow.grp = myWindow.add(
		"group { orientation: 'column', margins:0," +
		"alignment: ['fill','fill'], size: [350, 450]," +
		"msg: EditText {properties: {multiline:true}," +
			"alignment: ['fill', 'fill']," +
			"size: [350,430]}," +
			"b: Button {text: 'Ok'}" +
		"}");

		myWindow.grp.b.onClick = function () {
			myWindow.close();
		};

		myWindow.center();
		myWindow.grp.msg.text = m;
		myWindow.show();
    };	
	
	
	info += "Composition Name:\t" + comp.name + "\n" +
		"Layer Name:\t" + layer.name + "\n\n" +
		"Frame Rate:\t" + frameRate + "\n" +
		"Frame Length (s):\t" + (1/frameRate) + "\n\N" +
		
		//Header Rows
		"Key ID\t" +
		"Marker Creation Time\t" +
		"Marker Time Value\t" +
		"timeToCurrentFormat W/ True\t" +
		"Matches Previously Calculated Frame\t" +
		"timeToCurrentFormat Default\t" +
		"Matches Previously Calculated Frame\t" +
		"currentFormatToTime W/ True\t" +
		"Matches Initial Seconds Value\t" +
		"currentFormatToTime Default\t" +
		"Matches Initial Seconds Value\n";

	numKeys = layer.property("Marker").numKeys;
	
	for (i = 1; i < numKeys; i += 1)
	{
		//Set values		
		keyId = i;
		keyCreationTime = layer.property("Marker").keyValue(i).comment;
		keyTime = layer.property("Marker").keyTime(i);
		timeToCurrentFormatTrue = timeToCurrentFormat(keyTime, frameRate, true);		
		timeToCurrentFormatDefault = timeToCurrentFormat(keyTime, frameRate);
		currentFormatToTimeTrue = currentFormatToTime(timeToCurrentFormatTrue, frameRate, true);
		currentFormatToTimeDefault = currentFormatToTime(timeToCurrentFormatDefault, frameRate);

		//Output row
		info += keyId + "\t" +
			keyCreationTime + "\t" +
			keyTime + "\t" +
			timeToCurrentFormatTrue + "\t";
		if (timeToCurrentFormatTrue === prevTimeToCurrentFormatTrue) {
			info += "*\t";
		} else {
			info += " \t";
		}

		info += timeToCurrentFormatDefault  + "\t";
		
		if (timeToCurrentFormatDefault === prevTimeToCurrentFormatDefault) {
			info += "*\t";
		} else {
			info += " \t";
		}

		info += currentFormatToTimeTrue + "\t";
		
		if (currentFormatToTimeTrue === keyTime) {
			info += "*\t";
		} else {
			info += " \t";
		}
			
		info += currentFormatToTimeDefault + "\t";
		
		if (currentFormatToTimeDefault === keyTime) {
			info += "*\n";
		} else {
			info += "\n";
		}
			
		prevTimeToCurrentFormatTrue = timeToCurrentFormatTrue;
		prevTimeToCurrentFormatDefault = timeToCurrentFormatDefault;
	}
	alertInfo(info);
	
	//Reset the timecode display type to the user's preference	
	app.project.timecodeDisplayType = usersTimecodeType;
}

Re: timeToCurrentFormat bug?

Posted: July 26th, 2010, 7:20 am
by cob906
Adobe asked me to place the question on their forums as well... just an FYI.

http://forums.adobe.com/thread/687704