Selecting patterns of keyframes?

Scripting for After Effects

Selecting patterns of keyframes?

Postby zozo on 05/30/2009, 9:30 am

Does anyone know of a script or expression (writing one is out of my league), that will select patterns of keyframes? Like every 5th keyframe for example.
5th keyfram
I have done a fairly long motion track and I want to kind of smooth it out by deleting every 4 out of 5 keyframes. Doing it by hand will be my last option.

Thanks
zozo
 
Posts: 72
Joined: 08/1/2008, 10:08 pm

Re: Selecting patterns of keyframes?

Postby graymachine on 05/30/2009, 12:01 pm

Is this attempt to smooth your keyframes AFTER trying to use the Smoother in After Effects?
Harry Frank
Motion design tutorials, elements and more.
http://www.graymachine.com
graymachine
VC Moderator
VC Moderator
 
Posts: 981
Joined: 08/4/2008, 6:38 pm
Twitter: graymachine

Re: Selecting patterns of keyframes?

Postby zozo on 05/30/2009, 3:44 pm

The nature of the footage I have makes for a very jumpy track. I would probably apply smoother still after I have deleted the mentioned keyframes.

I am tracking a car on a suspension bridge. The tracker jumps off the car and on the bridge whenever the tracker goes over a suspension wire and if I delete 4 out of every 5 keyframes the track does what I need it to do much more smoothly.
zozo
 
Posts: 72
Joined: 08/1/2008, 10:08 pm

Re: Selecting patterns of keyframes?

Postby illuminatus23 on 06/1/2009, 4:11 am

Although I'm not quite sure if the technique of removing keyframes from the track is a good solution for your exact problem, here's how I would do it.

This is rather a job for a script than an expression:

Code: Select all
var project = app.project;
   var undoStr = "Delete keyframes";

   if (project){
      var myComp = app.project.activeItem;
      if (myComp != null && (myComp instanceof CompItem)){
         
         var selectedLayers = myComp.selectedLayers;
         if(selectedLayers.length == 1)
         {         
            var myLayer = selectedLayers[0];
            var selectedProps = myLayer.selectedProperties;
            if(selectedProps.length == 1)
            {
               var selectedProp = selectedProps[0];
               if(selectedProp.numKeys > 0)
               {
                  n = prompt("This script will walk through the keyframes of the selected property and delete them except every n'th keyframe. For example with n=5 it will generate this pattern: 1----6----11----16-- and so on.\nPlease specify n:", "5");
                  n = Number(n);
                  
                  if(n)
                  {
                     app.beginUndoGroup(undoStr);
                     
                     // The main part starts
                     for (var i = 2; i <= selectedProp.numKeys; i++)
                     {
                        for(var e = 1; e < n && i <= selectedProp.numKeys; e++)
                        {
                           selectedProp.removeKey(i);
                        }   
                     }
                  
                     app.endUndoGroup();
                  }else{
                     alert("Please enter an integer greater than 0.");
                  }         
               }else{
                  alert("This property isn't keyframed!");
               };
            }else{
               alert("Please select exactly one property.");
            }
         }else if(selectedLayers.length == 0)
         {
            alert("You should selected a layer before doing any keyframes stuff!");
         } else {
            alert("Please select only one layer.");
         }
      } else {
         alert("No comp selected man!");
      }
   }
   else
   {
      alert("Hey, what keyframes do you want to remove? You don't even have a project!");
   }


Save it into a file ending with .jsx and in After Effects choose File/Scripts (or Execute Script, actually I don't have the English version) select the script in the file dialog and execute it.
Make sure you have your keyframed property selected when executing it.

Lets have a look at the code:
The part actually doing something is very small. Basicly we have a bunch of if-statements ensuring that you have a keyframed property selected. It checks the following:
- Is there a project?
- Is there a comp selected in that project?
- Is there a layer selected in that comp?
- Is a property of that layer selected?
- Are there keyframes applied to that property?

If one of this conditions isn't fulfilled the script will respond with the matching error message. If everything is alright it requires you to enter a number, it checks if it's really a number and it begins an undo-group, which allows you to undo everything the script has done with Edit/Undo.
Then it executes the main code consisting of two for-loops and closes the undo-group. So you see what the script actually does is really not that complicated.

So let's face it, here's what the main code does:
The outer for-loop walks through all keyframes starting with the second (not the first) as we want the first keyframe not to be deleted. The loop repeats itself as long as i <= selectedProp.numKeys. That means until it has reached the end of the list of keyframes.
The problem is, once you delete a keyframe the next one takes its place. That means, if I have a list of keyframes 1,2,3,4,5,6 after deleting the first one with selectedProp.removeKey(1); I've got 2,3,4,5,6, but if I also want to delete the second one you have to use selectedProp.removeKey(1); again as the second keyframe has become the first keyframe after deleting the keyframe that was previously the first one. Confused?

Have look at this code:
Code: Select all
for (var i = 2; i <= selectedProp.numKeys; i++)
{
     selectedProp.removeKey(i);
}


At first one might think that this codes deletes all keyframes. But it doesn't. It deletes every second keyframe, because this list of keyframes is always updated.
This is what happens (the underlined number is the current keyframe, determined by the variable i, that is to be deleted):
i=2 -> 1,2,3,4,5,6,7,8,9,10
i=3 -> 1,3,4,5,6,7,8,9,10
i=4 -> 1,3,5,6,7,8,9,10
i=5 -> 1,3,5,7,8,9,10
i=6 -> 1,3,5,7,9,10
result -> 1,3,5,7,9

Deleting every second keyframe is almost what we want, except we want to control the width of the "gap", that means how many keyframes are to be deleted between the ones that are not deleted.
That's where we need the inner for-loop. It deletes n-1 keyframes before allowing the outer for-loop to go to the next item.
This is what happens with an n of 3:
i=2, e=1 -> 1,2,3,4,5,6,7,8,9,10
i=2, e=2 -> 1,3,4,5,6,7,8,9,10
i=3, e=1 -> 1,4,5,6,7,8,9,10
i=3, e=2 -> 1,4,6,7,8,9,10
i=4, e=1 -> 1,4,7,8,9,10
i=4, e=2 -> 1,4,7,9,10
result -> 1,4,7,10

You see we have deleted all keyframes except every third one.

The reason the condition for the inner for-loop is not only e < n, but e < n && i <= selectedProp.numKeys is that we have to stop the inner for-loop from looping on after the end of the list of keyframes has already been reached, because trying to delete a keyframe that doesn't exist would cause an error.

Well, good luck with the script!
illuminatus23
 
Posts: 88
Joined: 02/23/2009, 3:47 pm

Re: Selecting patterns of keyframes?

Postby Tim_Wiesner on 01/27/2016, 10:46 am

I have a problem with this script:
I converted audio into keyframes, therfore I have a lot of keyframes on a slider. I selected the slider and run the script, but it said that "Please select exactly one property". But isn't that what I did? I'm pretty confused :shock:
Tim_Wiesner
 
Posts: 1
Joined: 01/27/2016, 10:30 am
System Specs: GeForce GTX 770
AMD Fx 8350 4.0Ghz
8 GB

Re: Selecting patterns of keyframes?

Postby thurows on 05/11/2017, 6:06 pm

Tim_Wiesner wrote:I have a problem with this script:
I converted audio into keyframes, therfore I have a lot of keyframes on a slider. I selected the slider and run the script, but it said that "Please select exactly one property". But isn't that what I did? I'm pretty confused :shock:



I used this script recently and got around this problem by creating a null layer and copying and pasting the keyframes to the "Opacity" property, running the script and then replacing the original keyframes.
thurows
 
Posts: 1
Joined: 05/11/2017, 6:03 pm
System Specs: MBP Sierra


Return to After Effects Expressions