Activity › Forums › Adobe After Effects Expressions › Need to trigger animation any time there is a marker.
-
Need to trigger animation any time there is a marker.
Julian Chojnacki replied 3 years, 8 months ago 6 Members · 20 Replies
-
Julian Chojnacki
October 24, 2022 at 2:26 amThank 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 amIn 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 amHey 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 amOkay, 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 amI 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 amAaah, 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 amIt 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 amThanks, 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 amScratch 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 amHi 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);
Reply to this Discussion! Login or Sign Up