Skip to main content
Participating Frequently
February 22, 2016
Answered

Trim layer to last keyframe

  • February 22, 2016
  • 3 replies
  • 2428 views

I want to create a script that finds the last keyframe on selected layers (for various properties) and then cuts the clip at the last keyframe's time. How would I go about doing this? I'm just starting out scripting so I'm not sure if this is even feasible. Any help/pointers would be greatly appreciated!

This topic has been closed for replies.
Correct answer UQg

Hi filkinsteez,


the code below should work (havent tested much).

If you are really starting from 0, it might not be easy to understand, but it can give you something to start with.

The difficulty in your problem is to tell the script to visit every property with keys on a layer. This is what the aux function does in the code below.



// aux function to find 1st and last key times on a layer

// group: a property group

// keyTimes : [current first key time, current last key time]

function refineKeyTimes(group, keyTimes){

  

    var n, N=group.numProperties, p;

  

    for (n=1; n<=N; n++){

        p=group.property(n);

        if (p instanceof Property){

            if (p.numKeys>0){

                keyTimes[0] = Math.min(keyTimes[0], p.keyTime(1));

                keyTimes[1] = Math.max(keyTimes[1], p.keyTime(p.numKeys));

                };

            }

        else{

            refineKeyTimes(p, keyTimes);

            };

        };

    return;

    };

      

// main function

function f(){

    var comp = app.project.activeItem;

    if (comp==null || comp.typeName!=="Composition" || comp.selectedLayers.length===0) return; // wrong selection

  

    var sel = comp.selectedLayers;

    var n, N=sel.length, layer;

    var keyTimes;

    for (n=0; n<N; n++){

      

        // start with times that will be overwritten for sure when a key is found

        layer = sel;

        keyTimes= [+1000000, -1000000];

        refineKeyTimes(layer, keyTimes);

      

        // trim if a key was found

        if (keyTimes[1]>-1000000){

            // found a key

            if (keyTimes[1]<layer.outPoint){

                // trim

                layer.outPoint = keyTimes[1] + comp.frameDuration;

                };

            };

        };

    return;

    };

f();

Xavier

3 replies

Participating Frequently
February 24, 2016

Thanks so much for the reply! I tested this out and it does exactly what I was looking for. I'm relatively new to scripting so some things are a little foreign to me, but am going to try and go through it as best as I can. Thanks again!

Participant
February 7, 2022

Hi Filkin,

 

Trying to use this script but havent been able to get it to work. Could you maybe guide me on how to correctly install this?

I created a new .jsx file and added it to my ScriptUI Panel folder. When I select the script though I get an error "Adobe effects warning: error reading past end of file" Could you maybe please help me? Thank you very much.

UQg
UQgCorrect answer
Legend
February 22, 2016

Hi filkinsteez,


the code below should work (havent tested much).

If you are really starting from 0, it might not be easy to understand, but it can give you something to start with.

The difficulty in your problem is to tell the script to visit every property with keys on a layer. This is what the aux function does in the code below.



// aux function to find 1st and last key times on a layer

// group: a property group

// keyTimes : [current first key time, current last key time]

function refineKeyTimes(group, keyTimes){

  

    var n, N=group.numProperties, p;

  

    for (n=1; n<=N; n++){

        p=group.property(n);

        if (p instanceof Property){

            if (p.numKeys>0){

                keyTimes[0] = Math.min(keyTimes[0], p.keyTime(1));

                keyTimes[1] = Math.max(keyTimes[1], p.keyTime(p.numKeys));

                };

            }

        else{

            refineKeyTimes(p, keyTimes);

            };

        };

    return;

    };

      

// main function

function f(){

    var comp = app.project.activeItem;

    if (comp==null || comp.typeName!=="Composition" || comp.selectedLayers.length===0) return; // wrong selection

  

    var sel = comp.selectedLayers;

    var n, N=sel.length, layer;

    var keyTimes;

    for (n=0; n<N; n++){

      

        // start with times that will be overwritten for sure when a key is found

        layer = sel;

        keyTimes= [+1000000, -1000000];

        refineKeyTimes(layer, keyTimes);

      

        // trim if a key was found

        if (keyTimes[1]>-1000000){

            // found a key

            if (keyTimes[1]<layer.outPoint){

                // trim

                layer.outPoint = keyTimes[1] + comp.frameDuration;

                };

            };

        };

    return;

    };

f();

Xavier

Participant
February 7, 2022

Hi Xavier,

 

Trying to use this script but havent been able to get it to work. Could you maybe guide me on how to correctly install this?

I created a new .jsx file and added it to my ScriptUI Panel folder. When I select the script though I get an error "Adobe effects warning: error reading past end of file" Could you maybe please help me? Thank you very much.

Mathias Moehl
Community Expert
Community Expert
February 22, 2016

Yes, it is feasible. For each property you want to consider, check how many keyframes it has with the property's numKeys attribute. Then get the time of the last one with keyTime() method of the property to get its time.

If you are just getting started with scripting, a good way to learn all this is the (paid) course that I am currently doing at FXPhd:
Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects
Participating Frequently
February 24, 2016

Thanks for the reply Mathias! This project was actually inspired by your talk from AVW, so I'll definitely be checking out your course.