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

Importing keyframes from text file

Guest
Jul 21, 2012 Jul 21, 2012

Is that possible? I have keyframe data that is in the format of After Effects keyframes, like when you do strg+c on a keyframe animation in After Effects and paste that into a text editor.

Now I want to reverse that process with a script that reads a text file with said data and applies it onto a layer. I looked into the CS3 scripting guide but couldn't find anything like that. Google wasn't much help either.

TOPICS
Scripting
8.7K
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 Expert , Jul 23, 2012 Jul 23, 2012

A lot of what you'll need is in the File System Access section of Adobe's JavaScript Tools Guide (in AE: File>Scripts>Open Script Editor; in ExtendScript editor: Help > JavaScript Tools Guide).

Like this to open the keyframe file:

var myFile = File.openDialog("Navigate to keyframe file.");

myFile.open("r");

Then use

var myLine = myFile.readln();

to read the file line-by-line.

The parsing itself would be pretty much pure JavaScript string operations, and then create the keyframes.

Not too tough, even fo

...
Translate
Community Expert ,
Jul 23, 2012 Jul 23, 2012

There's nothing in the scripting language will do that for you directly--I think you'd have to write a simple parser to read the file and create the keyframes. It should be pretty straightforward. I'd set it up to assume that you have the target layer selected. Your script would read the keyframe file to get the property name and the frame rate, then, for each keyframe entry, calculate the time and apply the value using setValueAtTime(). It could get more complicated if the keyframes are for an effect property and you want the apply the effect if it doesn't exist.

That being said, why not just create a preset?

Dan

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
Guest
Jul 23, 2012 Jul 23, 2012

Thanks for your answer!

I actually write the keyframe data out of another program so I have control over how the data is formatted (which should make the parsing easier I guess). Currently I format it so I can manually copy paste it but that is pretty annoying thats why I want to do this script.
I have a keyframe for every frame, so tbh I have no idea how I would do a parser that just goes from line to line (don't know if thats even possible in JS, I just started using it) and collects the correct data for xyz for Position and Rotation. I imagine that being pretty complex than being simple 😕

Is there some way to make standard GUI interaction in the script? I actually just have to do what I already do manually in after effects with the sript.

What do you mean exactly with a preset? When I hear preset with After Effects than I think of Workspace presets :s

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 Expert ,
Jul 23, 2012 Jul 23, 2012

A lot of what you'll need is in the File System Access section of Adobe's JavaScript Tools Guide (in AE: File>Scripts>Open Script Editor; in ExtendScript editor: Help > JavaScript Tools Guide).

Like this to open the keyframe file:

var myFile = File.openDialog("Navigate to keyframe file.");

myFile.open("r");

Then use

var myLine = myFile.readln();

to read the file line-by-line.

The parsing itself would be pretty much pure JavaScript string operations, and then create the keyframes.

Not too tough, even for a first scripting project.

>What do you mean exactly with a preset?

You can select a property to highlight all the keyframes and then Animation>Save Animation Preset. Then you can apply the preset to other layers. But it sounds like that might not help in your situation.

Dan

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
Guest
Jul 23, 2012 Jul 23, 2012

Ah gotcha!


Ok if its that simple to read line by line I should be able to to that.

I guess I can figure out the rest with the help of the scripting guide and JS help. Thanks!

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 Expert ,
Jul 23, 2012 Jul 23, 2012

Come back if you get stuck on anything.

Dan

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
Guest
Jul 25, 2012 Jul 25, 2012

thanks, I actually got stuck.
With the most simple part.
How do I loop myself thorugh several lines?
I seem to only get line one with readln and can't proceed to the next line. I tried common Javascript solutions that I found like

var myFile = File.openDialog();

myFile.open();

var myText = myFile.read();

var lines = $('myText').val().split('\n');

for(var i = 0;i < lines.length;i++){

}

but I only get an error on var line

I tried my stuff with only one line so far to get the basic idea but without this basic line by line read I can't do much more.

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 Expert ,
Jul 25, 2012 Jul 25, 2012

I'd do it more like this:

var myFile = File.openDialog();

myFile.open();

var myLine;

while (! myFile.eof){

  myLine = myFile.readln();

  // parse the line

}

Dan

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
Guest
Jul 25, 2012 Jul 25, 2012

Ugh, that makes sense, thanks!

I'm still a coding noob

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
Guest
Jul 25, 2012 Jul 25, 2012

Ok I could set one keyframe with app.project.activeItem.selectedLayers[0].position.setValueAtTime(timeArray, posArray);

but if I want to add multiple keyframes with setValuesAtTimes(timeArray, posArray); I get the error;

http://i.imgur.com/PFv5C.jpg

Even though I have 4 values stored in posArray for 2 keyframs.

Do I need to store each position in its own array? It seems like its working fine with the timeArray (which holds the values 1 and 2)

(Oddly you can't copy those error messages?!)

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 Expert ,
Jul 25, 2012 Jul 25, 2012

Yes, for multi-dimensional properties like position, the value array would be an array of arrays:

var posArray = [[100,100],[200,200]];

Dan

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
Guest
Jul 25, 2012 Jul 25, 2012

Thats what I feared.
I will have a lot of keyframes (100+) and the amount will differ. How would I do that in this case?

Declaring an array for each frames can't be the solution (I hope). Can I store my values in its its own array directly to the posArray without specifing a name for each array?

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 Expert ,
Jul 25, 2012 Jul 25, 2012

Sure. I'd just create empty arrays:

var posArray = [];

var timeArray = [];

then, inside your loop, parse the time (t),  x, and y values and add them to the end of their arrays:

posArray.push([x,y]);

timeArray.push(t);

Dan

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
Guest
Jul 25, 2012 Jul 25, 2012

Ah ok thats how I have it atm so I just have to add brackets?

  posArray.push(parseFloat(myLine));
to
  posArray.push([parseFloat(myLine)]); ?

Doesn't work but I guess thats because I only get one value per line.

Thats how it looks atm:

var myFile = File.openDialog();

var posArray = [];

var timeArray = [];

myFile.open('r');

var myLine;

var frames= 2

for(var i = 0;i < frames;i++){

    myLine = myFile.readln();

    timeArray.push(parseFloat(myLine));

}

//var tellpos = myFile.tell();

//alert(timeArray);

while (! myFile.eof){

  myLine = myFile.readln();

  posArray.push([parseFloat(myLine)]);

}

//alert (posArray);

app.project.activeItem.selectedLayers[0].position.setValuesAtTimes(timeArray, posArray);

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 Expert ,
Jul 25, 2012 Jul 25, 2012

You need to split each text line into pieces before you can use parseFloat(). I think keyframe data has the values separated by tabs, so you need to do something like this:

var tabChar = String.String.fromCharCode(9);

Then, inside the loop:

myLine = myFile.readLine;

mySplitLine = myLine.split(tabChar);

f = parseInt(mySplitLine[1],10);

t = f/frameRate;  // you get the frame rate from the 3rd line of the keyframe data (or just specify it, if you know it).

x = parseFloat(mySliptLine[2]);

y = parseFloat(mySplitLine[3]);

You also need code to skip all the header lines (except for the one with the frame rate) and detect the end of the data (and then ignore the rest of the lines before the eof).

Dan

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
Guest
Jul 25, 2012 Jul 25, 2012

The text data is no problem, I can specify how the text file looks so I can just not output all the text stuff and just do the frames and the positions
I replicated the formatting of the AE keyframe text files with the script that creates the output file, that work is useless now I guess (maybe should have mentioned that earlier >.<)

I totally forgot about the split function, solved the problem. Thanks again, you are a great 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
Guest
Jul 26, 2012 Jul 26, 2012

Ok I finished the basic script with a two button gui but there is still something I have problems with. I want it to be a dockable gui, a script that I put in the ScriptUI Panel folder.
Now according to the scripting guide I have to use the "this" function instead of "new window" but I don't get much from the very small example in the PDF as it only makes a button but without assigning code to it.

It reads like it would be super simple to adapt scripts that use a window to this panel type gui but I'm really stuck here, I tried it in several ways but it seems I have to use it diffrently than the window gui.
The example from the scripting guide:

function createUI(thisObj) {

var myPanel = thisObj ;

myPanel.add("button", [10, 10, 100, 30], "Tool #1");

return myPanel;

}

var myToolsPanel = createUI(this);

myToolsPanel.show();

What I have at the moment:

{

var myFile;

    function Keyframe_Import(thisObj)

    {

            function onBrowsetButtonClick()

         {

               myFile = File.openDialog();

         }

            function addBrowseButton(palette, buttonRect, buttonLabel)

        {

            var newButton2 = palette.add("button", buttonRect, buttonLabel);

            newButton2.onClick = onBrowsetButtonClick;

            return newButton2;

        }

        function onScriptButtonClick()

        {

myFile.open('r');

var posArray = [];

var rotArray = [];

var timeArray = [];

var x;

var y;

var z;

var f;

var myLine;

var mySplitLine;

var frames = parseFloat(myFile.readln()); //first line contains the frames

var frames2 = frames

//alert(frames);

var fps = parseFloat(myFile.readln()); //second line contains the fps

//alert(fps);0

for(var i = 0;i < frames;i++){

f = i/fps

timeArray.push(f) 

}

//timeArray.push(parseFloat(myLine));

//var tellpos = myFile.tell();

//alert(timeArray);*/

for(var i = 0;i < frames;i++){

      myLine = myFile.readln();

      mySplitLine = myLine.split(" ");

  x = parseFloat(mySplitLine[0]);

  y = parseFloat(mySplitLine[1]);

  z = parseFloat(mySplitLine[2]);

  posArray.push([x,y,z]);0

}

app.project.activeItem.selectedLayers[0].position.setValuesAtTimes(timeArray, posArray);

while (! myFile.eof){

myLine = myFile.readln();

mySplitLine = myLine.split(" ");

  x = parseFloat(mySplitLine[0]);

  y = parseFloat(mySplitLine[1]);

  z = parseFloat(mySplitLine[2]);

rotArray.push([x,y,z]);

}

//alert (posArray);

app.project.activeItem.selectedLayers[0].orientation.setValuesAtTimes(timeArray, rotArray);

myFile.close();

        }

        function addScriptButton(palette, buttonRect, buttonLabel, buttonCurrentDirectory, buttonScriptName)

        {

            var newButton = palette.add("button", buttonRect, buttonLabel);

            newButton.onClick = onScriptButtonClick;

            return newButton;

        }

            var my_palette = new Window("palette","Keyframe Import");

            my_palette.bounds = [400,300,300,360];

            var button1 = addBrowseButton(my_palette,[25,  5, 110, 25],

                    "Browse");

            var button2 = addScriptButton(my_palette,[25,  30, 110, 50],

                    "Import/Update");

            my_palette.show();

        }

    Keyframe_Import(this);

}

Message was edited by: Malroy82

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
New Here ,
Mar 02, 2016 Mar 02, 2016
LATEST

Hello Dan!
I also have a problem with the keyframe import via custom GUI script.
I used these lines:

var myFile = File.openDialog("Navigate to keyframe file.");

             myFile.open("r");

             var myLine = myFile.readln();

but then I got stuck, for I don't understand what kind of files I should use, It would be perfect fot the script to understand just a *.jsx file. I tried to read several times just to see if something happens, but I couln't get a clue. It seems that the file doesn't do a thing.

Wating for the advice.

Best, Petr.

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