Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Expression to determine each value of next 100 frames

Explorer ,
Oct 04, 2023 Oct 04, 2023

I'm trying to write an expression that gets the value of a property for each of the next 100 frames and determine if they're all below a certain value. If they are, change a boolean to true and vice versa. Is this possible in the After Effects paradigm? Thanks. 

TOPICS
Audio , Expressions
2.2K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 04, 2023 Oct 04, 2023

Sure. A simple for() loop will do.

 

Mylenium

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 04, 2023 Oct 04, 2023

If you are trying to look forward from the current time to the next 100 frames, you are going to end up with a recursive expression that slows down the farther down the timeline you go. The slowdown can be exponential. You will have to take time and create a loop that looks forward 100 * thisComp.frameDuration and looks for your critical value. It can throw a switch or change a color if it finds it and returns a false value.

 

Add this expression to a text layer above a layer with an animated position property, and it will tell you whether the layer is above or below the center of the comp 100 frames ahead of the current time.

 

lookForward = 100 * thisComp.frameDuration;
v = thisComp.layer(index + 1).transform.position.valueAtTime(time + lookForward);
trgtVal = thisComp.height/2;
if (v[1] < trgtVal){
	p = ": Top"
}
else{
	p = ": Bottom"
}
"Position" + p

 

It won't compare all 100 frames, but it would look ahead to detect the change.

 

If I get some free time later on, I will take a look at adding a loop operator to check if any frame is above the target value.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Something like this, probably (this example is for the layer's rotation property):

prop = rotation;
threshold = 20;
val = true;
for (i = 0; i < 100; i++){
  if (prop.valueAtTime(time + framesToTime(i)) >= threshold){
    val = false;
    break;
  }
}
val

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 05, 2023 Oct 05, 2023

Thank you for the help, Dan. This worked! Would you mind helping me with the second aspect of this project, which is rotating a camera 90º if the boolean is true, and back to 0º if the boolean is false, but using ease() to make the rotation happen over time? Is this possible? Here's what I've tried and ease() isn't kicking in:

t = timeToFrames(time);
tFor = t + 48;
startRot = 0;
endRot = 90;

if (val){
	ease(time,t,tFor,startRot,endRot);
	} else if (! val) {
	ease(time,t,tFor,endRot,startRot);	
	}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Paul, that changes things. In that case the expression needs to figure how far into the future the threshold crossing occurs and use that to drive the ease expression. So that's probably going to look somethng like this:

prop = rotation;
threshold = 20;
startRot = 0;
endRot = 90;

if (prop.value >= threshold){
  endRot;
}else{
  for (i = 1; i <= 100; i++){
    if (prop.valueAtTime(time + framesToTime(i)) >= threshold){
      break;
    }
  }
  ease(i,1,100,endRot,startRot);
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 05, 2023 Oct 05, 2023

Thank you for your help, Dan. If you wouldn't mind one more imposition, I was wondering if you could look at the entire expression in context and tell me where my logic is wrong. 

 

I've analyzed an audio file of two people talking and am using the amplitude keyframes of one of the channels to determine when to pan a 3D camera to a picture of the two speakers. This expression lies in the Y Rotation property of the 3D camera. The rotation value changes as expected, but the ease() functions don't work. Here is the expression:

//variables for determining if Jon is talking
jon = thisComp.layer("Audio Amplitude").effect("Jon Channel")("Slider");
threshold = 3;
jonHush = false;
lookAhead = 65;
counter = 0

//variables for rotation
startRot = 0;
endRot = 90;
durRot = 96;

//determines if Jon is talking
for (i = 0; i < lookAhead; i++){
	if (jon.valueAtTime(time + framesToTime(i)) < threshold){
		counter++;
		if (counter >= lookAhead){
			jonHush = true;
			}
	} else {
		jonHush = false; 
		counter = 0;
		break;
		}
	} 

//rotates camera on Y axis according to if Jon is talking
if (! jonHush){
	ease(time,timeToFrames(time),timeToFrames(time)+durRot,endRot,startRot);
	} else if (jonHush){
		ease(time,timeToFrames(time),timeToFrames(time)+durRot,startRot,endRot);
		}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

This is actually a pretty complex problem, but basically your expression needs to first determine the current speaker. Then use a loop to look ahead to see if the speaker changes within the next 65 frames. If so, ease the rotatation based on how many of the 65 frames have already elapsed. Your expression, is missing a number of pieces to make that happen (as is the last one that I provided, which didn't include the logic to ease back and forth between conditions). It's do-able, but a bit of work.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2023 Oct 06, 2023

Thinking about this some more--it's even more complex than I thought. If the expression wakes up in the middle of a gap of silence, it needs to first figure out if that gap is long enough to have triggered a rotation, which could require examining previous and future frames. All of this maneuvering is required because of the limitation that expressions have no memory--an expression can't set anything that it can detect at a future (or previous) frame. So an expression can't leave behind a flag that says "we're currently in a speech gap"--it has to figure that out on every frame.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 06, 2023 Oct 06, 2023
Thanks again for your time on this.

Would the logic of determining silence and also the rotation need to be
accomplished in the same for loop?

The reason for this task is to automate a back and forth podcast
discussion, usually about an hour. Perhaps an idea ahead of it’s time?
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2023 Oct 06, 2023

No, the expression would use different logic, depending on whether it wakes  up above or below the threshold. Abovc, it needs to look forward to see if there is a gap coming of such duration that it needs to be rotating. Below, it needs to look forward and backward to see if it's currently in a gap sufficient to ease to (or keep) max rotation, or if it's getting near the end of a gap and needs to be rotating back to the speaker. It's absolutely do-able, just tricky. There are a lot of cases it has to account for, like gaps not sufficient to cause rotation, or possibly short bursts of speech where there isn't really time to rotate back. I think you need to start with a good spec that covers what you want to happen in all situations.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Dan, how would you use a property in an array like Scale or Position? When I try position[0] instead of rotation I get an error. The only way to not break the expression is to create an array for threshold, but I only want to look at the Y position. 

 

Paul, you have to add an argument that does something when the val changes from true to false. Something like this;

You'll then need to work out a time when the "val" changes from true to false and use that to drive an interpolation method like ease(tome, time of the change, time of the change + duration, start value, end value).

 

Dan, you can see the problem in the threshold line of the expression. I only want to look at the Y value.

 

 

ref = thisComp.layer(index + 1);
prop = ref.position;
threshold = [700, 540];
val = true;
for (i = 0; i &lt; 100; i++){
  if (prop.valueAtTime(time + framesToTime(i)) &gt;= threshold){
    val = false;
    break;
  }
}
val

if (val == true){
	a = "Do Something"
}
else{
	a = "Do something else"
}

 

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Oct 05, 2023 Oct 05, 2023
quote

Paul, you have to add an argument that does something when the val changes from true to false. Something like this;

You'll then need to work out a time when the "val" changes from true to false and use that to drive an interpolation method like ease(tome, time of the change, time of the change + duration, start value, end value).

By @Rick Gerard

 

Hi, Rick. Thanks for the help. Have I not implemented what you suggested in the code in my last post?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Paul, You kind of have the if/else, but you have not supplied any time values for the ease interpolation. 

 

The for loop is also broken if there are more than 2 keyframes and the last one is greater than the threshold.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Rick, here's how I'd set it up for y position:

prop = position;
threshold = 540;
val = true;
for (i = 0; i < 100; i++){
  if (prop.valueAtTime(time + framesToTime(i))[1] >= threshold){
    val = false;
    break;
  }
}
a = val ? "Do Something" : "Do Something Else"
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

Thanks, Dan. I was fouling up the placement of the [1].

 

There's another problem. If the property is keyframed, the switch only occurs if the last value is less than the threshold. Only the last keyframe is used. If the last keyframe is greater than the threshold nothing changes.  I've tried adding OR arguments with no luck. 

RickGerard_0-1696534343499.gif

It doesn't matter what property. The switch is only thrown when the value decreases in the last keyframe.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

I think the issue is that it's always looking up to 100 frames (3.33 seconds) into the future. You'd need a stretch of longer than that where the threshold isn't reached to see any change.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2023 Oct 05, 2023

You got it, Dan. I have been at the computer for about 12 hours and thought my timeline was 8 minutes, not 8 seconds.

 

This expression is going to be useful in a bunch of MGRTS I have already created. Dan's the Man.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 06, 2023 Oct 06, 2023

Heya Dan! I think it'll work to just get the info as it without having to look forward. Once all the values have been captured, the user can timeoffset the required keyframes. Correct?

Very Advanced After Effects Training | Adaptive & Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2023 Oct 06, 2023

Hi Roland--sorry, I'm not tracking what you're suggesting. What do you mean, exactly?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 06, 2023 Oct 06, 2023

I THINK, the entire reason for looking ahead 100 frames is for the user to move/rotate the camera into position and the target is the audio/voice file. The Look-Ahead is to know when to more the camera and to which speaker. So, all the required keyframes can be captured in current time with AE. When the capture is done, the user can move the cam keyframes earlier in time; mimicking the desired result of the Look-Ahead. 

Very Advanced After Effects Training | Adaptive & Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2023 Oct 06, 2023

The keyframes you're talking about are the audio-converted-to-keyframes, is that correct? I think the expression looking at those has to make some decisions, based on the duration of any silent or sound patches, compared to what's happened recently and what's coming up. I don't see any way around that, but I may be missing something obvious (wouldn't be the first time).

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 06, 2023 Oct 06, 2023

My thoughts are to capture something 100 frames ahead in time is the same as capturing at current time and then moving these keyframes back in time by 100 frames. 

Sense Make?

Very Advanced After Effects Training | Adaptive & Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2023 Oct 06, 2023

No man, I'm sorry, I don't get it. If the expression is looking at a copy of the keyframes shifted in time by 100 frames, I don't see how that would change the quantity of frames that it would have to examine, at all. It would just have to adjust all its valueAtTime() queries by 100 frames.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 06, 2023 Oct 06, 2023

I'm looking at simplifying the problem. So, everything gets captured at current time instead of 100 frames ahead. Then after capturing the values and the keyframes are created, one can manually move these keyframes earlier in time or use valueAtTime. The result should be the same but a lot quicker to process the initial expressions if the created keyframes are manually moved 100 frames earlier in time. 

Very Advanced After Effects Training | Adaptive & Responsive Toolkits | Intelligent Design Assets (IDAs) | MoGraph Design System DEV
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines