Skip to main content
CharlesBandla
Participating Frequently
August 1, 2026
Answered

Request for help with a script

  • August 1, 2026
  • 11 replies
  • 99 views

I’m working on a Visual Music film that uses Audio Amplitude layer keyframes created through Audio Layer > Keyframe Assistant > Convert Audio to Keyframes. The result is one linear keyframe per frame (@ 24 fps). Because its desired to act as a switch to turn on/off I’ve converted all the keyframes to hold keyframes.

These key frames will be used to turn the opacity of a shape layer on and off to synchronize graphics to audio. The desired value of the keyframes should be restricted to 0 (off) or 100 (on). Keyframes of any value of other than 0 or 100 are to be deleted.

I worked up an algorithm by hand processing the keyframes. But since there are over 1000 keyframes to be processed I’d like to automate the process with a script. An elaborate interface is not necessary, the goal is get the keyframes processed to get on to making the film.


The workflow:

    •    Prompt user to select a range of keyframes. 

    •    Create array of keyframe values from selection. 

    •    Set first keyframe in selection to 0.0. 

    •    Set second keyframe in selection to 100.0.  

    •    Set last keyframe in selection to 0.0. 

    •    In a loop find any elements in array that are > 0.0 and < 100.0 and delete them. 


My problem is that the last actual programming experience I’ve had was 40 years ago in a community college course in c++. I’ve had no experience in Javascript which After Effects uses. 

I’m using a M1 Pro MacBook Pro running Tahoe 26.5.1 with 32 GB memory.

Can anyone off some assistance/advice how to accomplish this? Thanks in advance.

Charles Bandla

Rochester, ny

    Correct answer Dan Ebberts

    This is pretty rough and could use some better error checking, but it should give you the idea:

    function processKeys(){
    var myProps = app.project.activeItem.selectedProperties;
    var myProp;
    var myKeys = [];
    var keysToRemove = [];
    app.beginUndoGroup("Prkocess Keyframes");
    for (var i = 0; i < myProps.length; i++){
    myProp = myProps[i];
    if (myProp.isTimeVarying){
    myKeys = myProp.selectedKeys;
    if (myKeys.length >= 3){
    for (var j = 0; j < myKeys.length; j++){
    if (j == 0){
    myProp.setValueAtKey(myKeys[0],0.0)
    }else if (j == 1){
    myProp.setValueAtKey(myKeys[1],100.0)
    }else if (j == myKeys.length - 1){
    myProp.setValueAtKey(myKeys[myKeys.length-1],0.0);
    }else{
    if (myProp.valueAtTime(myProp.keyTime(myKeys[j]),false) > 0.0 && myProp.valueAtTime(myProp.keyTime(myKeys[j]),false) < 100.0){
    keysToRemove.push(myKeys[j]);
    }
    }
    }
    while (keysToRemove.length > 0){
    myProp.removeKey(keysToRemove.pop());
    }
    }else{
    alert ("Less than 3 keys selected.");
    return;
    }
    }
    }
    app.endUndoGroup();
    }
    processKeys();

     

    11 replies

    CharlesBandla
    Participating Frequently
    August 8, 2026

    Dan, I’ve got some feedback you might be interested in. I did some experimenting and found the original script issue with staying on the property you’re editing is related to zoom in setting. If used at single frame level it drops to the highest level of the layer. If I zoom out a bit it retains the correct property when finished. 

    CharlesBandla
    Participating Frequently
    August 6, 2026

    Dan, thanks again for being so generous with your assistance. This is just what I was looking for, I made the script structure much clearer for me. I’ve found in a book on javascript to help getting further into it. 

    There is one thing that would I’d like to add to make the script more efficient. The way I’m using the script is to modify keyframes produced using Keyframe Assistant -> Convert audio to keyframes. The script is then run on the Audio Amplitude -> Effects -> Left Channel -> Slider where I view the keyframes in the Edit Value Graph mode to make the selections the script acts on.

    When the script finishes running the layer selection defaults to the layer name (the highest level of the layer) and I have to reselect Audio Amplitude -> Effects -> Left Channel -> Slider to see what I’m working on again. It would be much more efficient if I could have the script reselect the Left Channel Slider on finishing so I can go right into selecting the next group of keyframes. Is this possible?

    p.s. If I’m asking too much please just tell me and I’ll leave you alone. I really appreciate your time so far.

    Dan Ebberts
    Community Expert
    Community Expert
    August 6, 2026

    It’s a little trickier than I expected, but I think it will work if you add this code right before the endUndoGroup():

    	for (var i = 0; i < myProps.length; i++){
    myProps[i].selected = false;
    }
    myProp.selected = true;
    var mySelectedKeys = myProp.selectedKeys;
    for (var i = 0; i < mySelectedKeys.length; i++){
    myProp.setSelectedAtKey(mySelectedKeys[i], false);
    }

     

    CharlesBandla
    Participating Frequently
    August 6, 2026

    Thanks again Dan. This was just the kind of response I needed. Reading through it answered many of the questions I had and provided useful information on structuring a script I was lacking. Thank you for sharing so generously.

    davidwarner11t
    Participating Frequently
    August 4, 2026

    This should be straightforward with an After Effects JavaScript ExtendScript. Select the keyframes loop through them from the last to the first, and delete any values between 0 and 100. Then set the first, second, and last keyframes to 0, 100, and 0. Working backward is important so deleting keyframes doesn't mess up the indexes.

    CharlesBandla
    Participating Frequently
    August 6, 2026

    Thanks so much for responding. My big disadvantage is that I don’t have the experience of writing scripts and my ignorance of javascript syntax and such.

    Dan Ebberts
    Community Expert
    Dan EbbertsCommunity ExpertCorrect answer
    Community Expert
    August 3, 2026

    This is pretty rough and could use some better error checking, but it should give you the idea:

    function processKeys(){
    var myProps = app.project.activeItem.selectedProperties;
    var myProp;
    var myKeys = [];
    var keysToRemove = [];
    app.beginUndoGroup("Prkocess Keyframes");
    for (var i = 0; i < myProps.length; i++){
    myProp = myProps[i];
    if (myProp.isTimeVarying){
    myKeys = myProp.selectedKeys;
    if (myKeys.length >= 3){
    for (var j = 0; j < myKeys.length; j++){
    if (j == 0){
    myProp.setValueAtKey(myKeys[0],0.0)
    }else if (j == 1){
    myProp.setValueAtKey(myKeys[1],100.0)
    }else if (j == myKeys.length - 1){
    myProp.setValueAtKey(myKeys[myKeys.length-1],0.0);
    }else{
    if (myProp.valueAtTime(myProp.keyTime(myKeys[j]),false) > 0.0 && myProp.valueAtTime(myProp.keyTime(myKeys[j]),false) < 100.0){
    keysToRemove.push(myKeys[j]);
    }
    }
    }
    while (keysToRemove.length > 0){
    myProp.removeKey(keysToRemove.pop());
    }
    }else{
    alert ("Less than 3 keys selected.");
    return;
    }
    }
    }
    app.endUndoGroup();
    }
    processKeys();

     

    CharlesBandla
    Participating Frequently
    August 6, 2026

    Thank you so much for such a detailed response. I tried this code and it did exactly what I need right out of the box. How can I repay you? I’ll certainly give you a technical assistance credit on the film (though that and 50 cents will leave you short for a cup of tea.😀