Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Script to move keyframes to markers

  • Script to move keyframes to markers

    Posted by Frederic Antoinette on November 24, 2016 at 10:11 pm

    I’ve been trying to do that for a while, and I realise it can only be done through script rather than expression.
    the main use is for lip syncing, have used several method including time remap to markers, haracter animator, and autoLipSync from mamo world. The two previous just jump to the shape, and the later uses deformation, but doesn’t do it by modifing the shape of a shape layer, and I want to do it with a shape layer, and make it morph towards the next shape instead of jump, or get deform likes its an image instead of a shape.

    I tryed to learn scripting but I got way over my head.

    So here here is my idea that could make it work:

    First I have a shape layer, with all the different mouth shape I want, keyframe and layer markers at each keyframe
    I then have a null object with markers labelled same as the shape layer, but the markers are set to where I want each different shape to come. Like that:

    Now the script should work like that.
    First I select the path property with all the keyframes, and then run the script
    The script then ask me which layer are the end results markers, in my case the Null layer

    the script then makes a copy of the shape layer,
    delete all the keyframes in the selected property, on that copied shape layer
    Reads the markers from the Null layer
    And copies the value equivalent to that marker from the original layer to the result layer.

    here is the result I expect, I’ve colored circled the keyframe to demonstrate which keyframe is reproduced where;

    I’m pretty sure that it can be done, and having the selected property as a variable this could work for any keyframable property, at least i think it should.

    I hope I makes sense.
    Is there already a script somewhere that can do that? Or can someone help me writing it.

    Thanks

    Frederic Antoinette replied 8 years ago 2 Members · 3 Replies
  • 3 Replies
  • Frederic Antoinette

    November 28, 2016 at 12:26 pm

    Wasn’t that easy after all,
    But spent the whole week end trying to figure it out. if any one is interested
    It works only for one property, if some one wants to enhance it to be able to select multiple properties you are welcome to do so.
    below is the code.
    Maybe someone can clean it up a little, this is the first time I write a script, and I’m pretty happy about the results.

    Works like that:
    Create your keyframes and add markers to what I call the origin layer.
    Create a null and place the markers with there corresponding comment to where you need them.
    Select the property from the origin layer and run the script

    Enjoy.

    var myComp = app.project.activeItem; // get the selected layer
    var layerIdx = myComp.selectedLayers[0].index; // grab index of selected layer
    var layer = myComp.layer(layerIdx); //set the selected layer
    var propIdx = layer.selectedProperties.length - 1; //Get how many properties are selected if more than one only the last one is retained, had to do this as for path it always select the group and the path
    var prop = layer.selectedProperties[propIdx]; // set variable to point to the last selected propertiies
    var oNumMarkers, origList, nL, layerList, mLayer, dupLayer;

    layerList = new Array();
    origList = new Array();

    dialog();

    function dialog(){

    // get how many layers there are in the composition
    nL = myComp.numLayers;

    // create a list of all the comp name for a drop down list
    for (var q = 1; q<=nL; q++) {

    layerList[layerList.length] = q + " - " + myComp.layer(q).name;
    }

    // create the popup window
    var myWin = new Window("palette","Select marked layer", undefined);
    var dd = myWin.add("dropdownlist",undefined,layerList) ;
    dd.selection =layerIdx - 2; // set selection to a layer higher than selected layer (assuming this is where you will placed your marked layer)
    var but = myWin.add("button",undefined,"Select Layer");
    but.onClick = function () {

    // This is where the fun starts
    app.beginUndoGroup ("Match keys to markers");

    mLayer = myComp.layer(dd.selection.index + 1); // set the layer continaing the final marker in position
    oNumMarkers = layer.property("Marker").numKeys; // get the total number of markers availble in the original layer

    // Create an array containing the value at each marker from the original layer
    for (var i = 1; i <=oNumMarkers; i++) {

    var name =layer.property("Marker").keyValue(i).comment;

    var time = layer.property("Marker").keyTime(i);

    var val = prop.valueAtTime(time,true);

    origList[origList.length] = {'name': name, 'time': time, 'value': val}

    }

    // Duplicate the selected layer, rename the duplicated layer same as original layer. and rename original layer to append Results at the end
    // Ended up to be easier to make a copy of the original layer, and then modify the original layer rather that modify the keys from the duplicated layer

    dupLayer = layer.duplicate();
    dupLayer.name = layer.name;
    layer.name = layer.name + "_Results";
    dupLayer.enabled = false; // Disable duplicated layer

    // Remove all markers and keyframes from the original layer, safe now since we have duplicated it and have already store all the data it contains in origList array
    for (var j = 1; j <=oNumMarkers; j ++){
    layer.property("Marker").removeKey(1);
    prop.removeKey(1);

    }
    //Place the correspondies keyframe to the corresponding markers by
    // Getting the first marker comment and time
    // then looping through origList to find the corresponding comment, and get its value
    // finally place that value on in the corresponding properties

    for (var k = 1; k <= mLayer.property("Marker").numKeys; k ++) {

    rName = mLayer.property("Marker").keyValue(k).comment;
    rTime = mLayer.property("Marker").keyTime(k);
    for (var r = 0; r < oNumMarkers; r++){
    if (rName == origList[r].name) {
    rVal = origList[r].value;
    }
    }
    prop.setValueAtTime(rTime,rVal);
    var mv = new MarkerValue(rName);
    layer.property("Marker").setValueAtTime(rTime,mv);
    }
    layer.moveBefore(mLayer); // move the result layer before the layer with the markers
    app.endUndoGroup();
    myWin.close();

    }
    myWin.center();
    myWin.show();
    }

  • Morris Parker

    April 2, 2018 at 2:58 am

    I realize that this is an old thread, but I’ve can’t found a similar topic anywhere else, and this issue is very important to me.

    When I run this script AE says: “property or method named ‘app’ is missing or doesnt exist”.

    My comp looks like that:

    What I’m doing wrong?

    Thanks.

  • Frederic Antoinette

    April 22, 2018 at 3:55 pm

    Hello, sorry its only now that I see you question.
    This a script not an expression.
    You should go to file->scripts->Open Scripts editor,
    and paste the code in there and run it.
    It is not a on the go continuous solution, every time you move the markers you have to rerun the script.

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy