Copy link to clipboard
Copied
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.
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
...Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
Come back if you get stuck on anything.
Dan
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
Ugh, that makes sense, thanks!
I'm still a coding noob ![]()
Copy link to clipboard
Copied
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;

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?!)
Copy link to clipboard
Copied
Yes, for multi-dimensional properties like position, the value array would be an array of arrays:
var posArray = [[100,100],[200,200]];
Dan
Copy link to clipboard
Copied
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?
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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);
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more