Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Need to trigger animation any time there is a marker.

  • Julian Chojnacki

    October 24, 2022 at 2:26 am

    Thank you, Dan! This does the job brilliantly.

    Now, I’ve hit another roadblock when trying to apply this concept to an expression selector in order to animate the words individually, so that they’re truly synced to the audio.

    My idea is to combine your expression (the previous t+.5 version) with the expression below that uses layer markers to animate text on a per-word basis. I just can’t wrap my head around how to stack the if/else conditions. How would you approach this?

    anim = thisProperty;

    delayDur = framesToTime(effect("Delay Duration")("Slider").value);

    numMarkers = marker.numKeys;

    delay = (textIndex - 1)*delayDur;

    if (numMarkers > 0)

    {delay = textIndex <= numMarkers ? marker.key(textIndex).time : marker.key(numMarkers).time;}

    anim.valueAtTime(time - delay);

    Best
    Julian

  • Paul Ducco

    October 24, 2022 at 4:27 am

    In a related question…but not wanting to hijack the thread.

    How does one create a series of animations that are triggered with markers (or another form of script)?

    The specific example I’m trying to currently build out, is used in a recreated interface setting…whereby a single comp controls a whole bunch of variables (through Essential Graphics) of a specific cursor. What I’m hoping to also “automate” is the use of a marker (or Essential Graphics track) keyframe to trigger an animation which ‘clicks’ the placed cursor, i.e, scales down and then back up.

    I’ve had success with scaling down (with a liner, or ease based process) …but how do I trigger another/return animation to scale the item back to its original spot?

  • Carter Lilley

    November 8, 2022 at 1:07 am

    Hey all, trying to solve the same exact problem here. The goal: keyframe a text property with new sentences throughout (in my case) a music track. Then, retime each word of each phrase with markers – essentially creating a lyric video generator on one track and applying a flexible text animator to every word of every phrase. Seems extremely powerful.

    I’ve messed around with your code a lot and am close, but just hoping for a little further guidance.

    I have just about every variable I think I would need for this, I’m just not sure how to plug them in. I know how many words (and markers) are in each phrase. When each phrase begins and ends, and how to pair text to markers.

    In bold below is the problem area, however. TextIndex is very confusing to me – I’m not sure how to appropriately “step” through the text index on a “per phrase” basis, so it goes 0-X for each phrase, X being the number of words in the phrase.

    Any help would be appreciated!!

    anim = thisProperty; //this property

    m = text.sourceText; //text property

    if (m.numKeys > 0){

    n = m.nearestKey(time).index; //this is the current phrase index

    if (m.key(n).time > time) n--;

    }

    if (n > 0){

    t1 = m.key(n).time; //this is the current phrase starting time

    if (n < m.numKeys){

    t2 = m.key(n+1).time; //this is the next phrase starting time

    }else{

    t2 = t1 + .5;

    }


    numWords = text.sourceText.valueAtTime(t1).split(/ ,| | \./).length; //number of words in the current phrase

    nextPhrasemarkerID = marker.nearestKey(t2).index; //ID of next phrase's FIRST marker

    currPhrasemarkerID = marker.nearestKey(t1).index; //ID of current phrase's FIRST marker

    numMarkersperPhrase = (nextPhrasemarkerID - currPhrasemarkerID); //number of markers in the current phrase


    }

    delay = marker.key(textIndex).time;

    //this is the time of the marker index which matches the text index. first marker, first word, second marker, second word - etc.


    anim.valueAtTime(time - delay)



  • Carter Lilley

    November 8, 2022 at 3:45 am

    Okay, some further refinement here shows me that I just need to add the total number of words from the previous phrase to the textIndex at the begging of each phrase. So let’s say the first phrase has eight words – starting at zero – you’d run through the textIndex normally, and then when the new phrase begins, you would simply add “textIndex+8” to the running tally, so the text index “begins again” on word 8.

    I’m so close I can taste it! Unfortunately, I am at a loss as to how to properly “store” and increment variables in AE as it’s independent of time. (Say updating the running total word tally every time I keyframe the text property) Any clarity as to how I can do this?

  • Dan Ebberts

    November 8, 2022 at 3:54 am

    I think textIndex starts over at each keyframe, so, assuming you have “Based On” set to Words, textIndex == 1 will refer the the first word of each keyframed phrase.

  • Carter Lilley

    November 8, 2022 at 4:34 am

    Aaah, but unfortunately I am tying the marker timings to the text index from 0-X on each phrase in this part – marker.key(textindex).time

    All I need to do is offset it by the number of words in each phrase every time there’s a new keyframe, but I cant seem to figure out how to properly store and increment that variable, if that makes sense.

    Unless there’s a simpler way that I’m not seeing!

  • Dan Ebberts

    November 8, 2022 at 7:16 am

    It looks like you’re calculating the first marker index of the current phrase, so it seems like the marker index for each word in the phrase would be currPhrasemarkerID + (textIndex-1)

  • Carter Lilley

    November 8, 2022 at 7:40 am

    Thanks, messing around with this now.

    Maybe this is sailing way over my head – but how do I derive and pass the time for those indexes? I understand that “marker.key(textindex).time” when subtracted from time will always give me the starting points of identical textindex and marker pairs…which is why I was attempting to offset it by “numWords” each time there’s a phrase change. (This does work if I do it manually by adding a keyframed value equal to the total number of accumulated words so far to textIndex, but requires me to manually keyframe this value as in increments. As stated above not sure how to “store” this variable for use over time as it gets bigger).

    We might be getting crossed wires here because there are two approaches to this – one based on the number of markers per phrase, and one based on the number of words per phrase (which will break if there isn’t a “correct” amount of markers.)

    I was attempting to figure out the (hopefully) easier way of doing it based on the number of words in the phrase, making the number of markers irrelevant so long as they are the same as the number of words.

    Does any of this make sense? I’ve been staring at this code a while and my head is starting to hurt haha. Expression selectors are incredibly powerful but I feel like they are not well documented.

  • Carter Lilley

    November 8, 2022 at 7:46 am

    Scratch that – you gave me exactly what I needed.

    I’ll clean this up and post the full script at some point Julian Chojnacki!

  • Julian Chojnacki

    November 8, 2022 at 11:11 am

    Hi Carter,

    very much looking forward to your approach!

    In the meantime, enjoy @filipvandueren ‘s solution:

    anim = thisProperty;
    delayDur = framesToTime(effect("Delay Duration")("Slider").value);
    numMarkers = marker.numKeys;
    txt = text.sourceText;
    delay = (textIndex - 1) * delayDur;
    
    
    for (i = 0;
        (i < txt.numKeys && txt.key(i + 1).time <= time); i++) {
        // dummy loop, i counts # of sourceText Keys that we have passed
    };
    for (j = 0;
        (i > 0 && j < marker.numKeys && marker.key(j + 1).time < txt.key(i).time); j++) {
        // dummy loop, j counts # of markers that have occured before the current sourceText Keyframe.
    }
    
    textIndex += j; // offset the textIndex so we relatively start counting from 1 after each txt keyFrame
    
    if (numMarkers > 0) {
        delay = textIndex <= numMarkers ? marker.key(textIndex).time : marker.key(numMarkers).time;
    }
    anim.valueAtTime(time - delay);
Page 2 of 2

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