Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

AE Script setValueAtTime rounding large values?

Community Beginner ,
Nov 03, 2015 Nov 03, 2015

Hi guys,

I'm just getting started with extendScript, and I've run in to an issue.

I'm trying to set a keyframe to an (admittedly) large value, After Effects sets it to a value that is different than the value I pass in. It seems to be snapping more than rounding, and doing so inconsistently.

For example, these are the values I'm setting int he script, and what After Effects is setting on the keyframe

1248304.6823 1248304.625

-4720535.9958 -4720536

4092748.7335 4092748.75

You can see that it seems to be 'snapping' the values to increments of .025, but it does it inconsistently from one value to the next. Is there a setting I can set in the script to force it to use the actual value I want?

What's strange is that if I copy and paste those values into After Effects directly on the keyframes, it rounds them to 3 significant digits, as I would expect.

Is it just because my numbers are too large? And if so, why does After Effects have no trouble with the values?

Any ideas or insights would be much appreciated!

for (var i = 1; i <= app.project.numItems; i++) {

    if (app.project.item(i) instanceof CompItem) {

        var comp = app.project.item(i);

        var textName = comp.layers.addText( 'test' );

        textName.threeDLayer = true;

        textName.position.setValueAtTime( 0, [ 1248304.6823, -4720535.9958, 4092748.7335 ] );

    }

}

TOPICS
Scripting
2.8K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Beginner , Nov 10, 2015 Nov 10, 2015

Zewt! You are a hero!

I took a modified approach to your idea:

I set the int and decimal parts of the value as positions on two null objects.

Then used an expression on the camera.position to combine those two values.

Finally, I used that script that I linked to convert the camera.position expressions to keyframes and deleted the nulls.

Doing it this way let me create just two separate null objects, and not have to create two for each axis (x,y,z).

Also, the slider control has a limit of 1,000,000 to

...
Translate
Advocate ,
Nov 03, 2015 Nov 03, 2015

I got the same result as you (AE CC 2014). This is a bit strange indeed. The rounding up to 0.025 px accuracy is not a crime, but the roundings appears to be quite random as you said.

I tried to investigate a bit more (see test below), it appears than it is not a 0.025 px rounding, it's something else, but i don't know how to interpret it.

Xavier

// the alert displays the value to be set, the value that has been set, and the diference (xPosition only, not full array)

var comp= app.project.activeItem;

var p = comp.layer(1).transform.position;

var x0, x, xx;

var res = "";

function random(a,b){return Math.round(a + (b-a)*Math.random());};    // a, a+1, ... b-1

for (var n=0, x0=1; n<10; n++, x0*=10) {

    x = random(x0, x0*10)+Math.random();

    res += x;            // position[0] to be set

    res += " ---> "

    p.setValue([x, 0, 0]);

    xx = p.value[0];    // position[0] that has been set

    res += xx;

    res += " (diff :  ";

    res += (xx-x);

    res+= ")\r\r";

    };

alert(res);

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 05, 2015 Nov 05, 2015

Yes, it really is quite strange.

Looking at your example, the difference seems to get larger as you enter bigger and bigger numbers.

And like you said, if it did that consistently for each value (i.e. it was actually rounding up/down to the nearest 0.025 px), it wouldn't be a problem. But as it is, I'm getting a lot of jitter in the keyframes because each one is different than the previous.

I don't suppose you have any ideas for how to work around this? Or to somehow trick AE into thinking the values were entered into the position value directly?

Thanks for your help.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 08, 2015 Nov 08, 2015

It's just rounding to a 32-bit float.  That's a bug, since the properties themselves seem to be 64-bit (on a quick look in the SDK) and it doesn't happen with expressions.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 09, 2015 Nov 09, 2015

Thanks for clarifying the issue, Zewt.

I submitted a bug to Adobe, but it feels like I just sent it off into a black hole and am not hopeful about receiving a timely response.

As I mentioned, I'm new to the world of AE scripting. What I'm trying to do is export a camera move from an external product I'm developing. The script basically sets a camera keyframe in AE for each frame in my product. Is there any kind of workaround for this bug?

Maybe creating a script that somehow works with expressions so I can set the value correctly?

Again, thanks for you insight, and I appreciate your expertise in how all this works.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 09, 2015 Nov 09, 2015

Yeah.  I've had great response when reporting bugs on Photoshop, but with AFX it feels like shouting down a well.

The problem you're seeing (simplified) is that 32-bit floats can either store a really big number with a small amount of precision after the decimal point, or a really small number with lots of precision after the decimal point.  You could try exporting the data as two separate numbers, and combining them with an expression.

For example, if you have the number 123456789.987654321, export it as two separate keys: one for the decimal part by calling Math.floor(n), 123456789, and one for the fractional part by subtracting it off, n-Math.floor(n): 0.987654321.  Both of these numbers should store fine in two expression slider controls, eg. CameraWhole and CameraFrac.  Then, combine them with an expression by simply adding them together.  It'll give ugly data that'll be really hard to manipulate if you want to change it later and require an expression for a silly workaround that'll slow down AFX--but it should give the right results.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 09, 2015 Nov 09, 2015

Ah, that's very interesting. I'll give that a shot, thanks!

I found this script to convert expressions into keyframes. which could help with the slowing down calculations via the expression by writing them to keyframes. But then again, that might introduce the same problem where the values get converted to a 32-bit float.

We'll see!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 10, 2015 Nov 10, 2015
LATEST

Zewt! You are a hero!

I took a modified approach to your idea:

I set the int and decimal parts of the value as positions on two null objects.

Then used an expression on the camera.position to combine those two values.

Finally, I used that script that I linked to convert the camera.position expressions to keyframes and deleted the nulls.

Doing it this way let me create just two separate null objects, and not have to create two for each axis (x,y,z).

Also, the slider control has a limit of 1,000,000 to -1,000,000 which wasn't enough for what I needed.

For any one in the future (or maybe me) who may stumble across this looking for a solution.

// Creating project

var project = app.newProject();

// Creating comp

var comp = project.items.addComp('untitled', 1920, 1080, 1, 15, 30);

// Open the comp

comp.openInViewer();

// Create a camera

var cameraLayer = comp.layers.addCamera( 'Camera', [

  '${this.model.width / 2}',

  '${this.model.height / 2}'

] );

var cameraPosition  = cameraLayer.position;

var positionInts = comp.layers.addNull();

positionInts.name = 'positionInts';

positionInts.threeDLayer = true;

var positionDecimals = comp.layers.addNull();

positionDecimals.name = 'positionDecimals';

positionDecimals.threeDLayer = true;

// Set the int of all your values on the positionInts null

positionInts.position.setValuesAtTimes(

    [0, 1, 2], [

        [4518810, -71312864, -2158705],

        [4522482, -71308958, -2158292],

        [4533658, -71297341, -2157044]

    ]

);

// Set the decimal of all values on the positionDecimals null

positionDecimals.position.setValuesAtTimes(

    [0, 1, 2], [

        [0.6400621915236115, -0.80026875436306, -0.5924631282687187],

        [0.0393883166834712, -0.00048755109310150146, -0.32361961202695966],

        [0.004953828640282154, -0.6714665293693542, -0.026646549347788095]

    ]

);

// Create an expression on the camera position

cameraPosition.expression = '[ thisComp.layer("positionInts").transform.position[0] + thisComp.layer("positionDecimals").transform.position[0] , thisComp.layer("positionInts").transform.position[1] + thisComp.layer("positionDecimals").transform.position[1], thisComp.layer("positionInts").transform.position[2] + thisComp.layer("positionDecimals").transform.position[2] ];';

// Bake all the expression keyframes

function convertToKeyframes(theProperty) {

    if (theProperty.canSetExpression && theProperty.expressionEnabled) {

        theProperty.selected = true;

        app.executeCommand(app.findMenuCommandId("Convert Expression to Keyframes"));

        theProperty.selected = false;

    }

}

convertToKeyframes( cameraPosition );

Thanks again for your input!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Nov 09, 2015 Nov 09, 2015

When you submit bugs through this form, we do read them. Specifically, one of the people who works just down the hall from me reads them and processes them. We can't respond to every one, though.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Nov 09, 2015 Nov 09, 2015

Thank you very much for your reply, Todd.

I did submit through that form and didn't mean to suggest that the issues aren't being read, but that it could be a while before a fix could actually turn up in AE, given what I'm sure is a large volume of submitted bugs and requests.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines