## using a script to loop a randomly selected part of a composition

Community Beginner ,
Sep 08, 2020

Copied

I've got a composition which I can loop just fine with loopOut()  expression just dandy.

The composition is 4 seconds long (at 30 fps = 120 frames) but what I want to do is as follow: At the end of the first 4 seconds, I want to select any random 24 frame sequence from the original 120 frames (i.e. start from frame 0 to frame 96 and play the next 24 frames).

In Time Remap, I've tried doing things like creating a keyframe every 12 frames (close enough) and generating a random integer and giving it to loopOut("cycle", rand) but this produces a ridiculously random series of frames (or just freezes on the first or last frame depending on how i've set up the random value and how I'm processing it). I also tried doing the same sort of thing with loopOutDuration() with largely the same results.

I'm a programmer by trade so Javascript doesn't scare me in the least. I can see how I would do this in pseudo-code:

``````int startFrame = randomValue between 0 and 120;
int endFrame = startFrame + 24;
timeRemap = framesToDuration(startFrame);
if (currentTime !== framesToDuration(endFrame)) {
// play the frames
} else {
// we are at the end, recursively call the function
}``````

Does anyone have any good pointers as to how to do this sort of thing? I've looked at the Expressions reference and I can't find anything obvious there.

I'd try something like this:

``````seed = 1103; // change this to get different result
f = timeToFrames(time);
if (f >= 120){
seg = Math.floor((f - 120)/24);
ph = (f - 120)%24;
seedRandom(seed+seg,true);
fStart = Math.floor(random(96));
f = fStart+ph;
}
framesToTime(f)``````
TOPICS
Expressions, Scripting

Views

68

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

## using a script to loop a randomly selected part of a composition

Community Beginner ,
Sep 08, 2020

Copied

I've got a composition which I can loop just fine with loopOut()  expression just dandy.

The composition is 4 seconds long (at 30 fps = 120 frames) but what I want to do is as follow: At the end of the first 4 seconds, I want to select any random 24 frame sequence from the original 120 frames (i.e. start from frame 0 to frame 96 and play the next 24 frames).

In Time Remap, I've tried doing things like creating a keyframe every 12 frames (close enough) and generating a random integer and giving it to loopOut("cycle", rand) but this produces a ridiculously random series of frames (or just freezes on the first or last frame depending on how i've set up the random value and how I'm processing it). I also tried doing the same sort of thing with loopOutDuration() with largely the same results.

I'm a programmer by trade so Javascript doesn't scare me in the least. I can see how I would do this in pseudo-code:

``````int startFrame = randomValue between 0 and 120;
int endFrame = startFrame + 24;
timeRemap = framesToDuration(startFrame);
if (currentTime !== framesToDuration(endFrame)) {
// play the frames
} else {
// we are at the end, recursively call the function
}``````

Does anyone have any good pointers as to how to do this sort of thing? I've looked at the Expressions reference and I can't find anything obvious there.

I'd try something like this:

``````seed = 1103; // change this to get different result
f = timeToFrames(time);
if (f >= 120){
seg = Math.floor((f - 120)/24);
ph = (f - 120)%24;
seedRandom(seed+seg,true);
fStart = Math.floor(random(96));
f = fStart+ph;
}
framesToTime(f)``````
TOPICS
Expressions, Scripting

Views

69

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 08, 2020 0
6 Replies 6
Most Valuable Participant ,
Sep 09, 2020

Copied

You need to pin the random seed with seedRandom() to make it less arbitrary and of course you will have to add some extra code to actually make sure the duration is within a usabel range and if not, re-seed the random function until it hits the right area. That and you may need to add some marker or keyframe on the time-remapping itself to latch on to as an anchor for the 4 second mark. No point in re-creating a ton of functionality in code that can be had easier.

Mylenium

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 1
Community Beginner ,
Sep 09, 2020

Copied

Thanks I'll have a look!

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 0
Guide ,
Sep 09, 2020

Copied

Have a look at the random expressions on http://www.motionscript.com/

This is a create ressource for inspiration.

On your code, I would outsource the random and posterize it. This code is for a slider on a layer called "Random":

posterizeTime(1); // code will be executed once a frame - set the value to your needs

Math.round(random(0,96)); // not 120!

You can pick the slider value in another expressions:

startFrame = thisComp.layer("Random").effect("Slider Control")("Slider");

Make sure the code just kicks in after 4 sec and take care of the else-case:

if (time >= 4){...} else {value};

Convert time to a modulo time to create 24f segments:

t = time - 4; // remove 4 sec preroll

tFrames = t / thisComp.frameDuration;

tMod = Math.round(tFrames % 24);

And just drive time remap with simple math, all mapped against time:

startFrame + tMod;

And all puzzle pieces together:

Code for slider on layer "Random":

``````posterizeTime(1);
Math.round(random(0,96));``````

Code for layer with animation:

``````startFrame = thisComp.layer("Random").effect("Slider Control")("Slider");

if (time >= 4){
t = time - 4;
tFrames = t / thisComp.frameDuration;
tMod = Math.round(tFrames % 24);
startFrame + tMod
} else {
value;
};``````

This works best if all layers start at the begining of the comp. You can add thisLayer.inPoint and do math to compensate offsets, but this usual make things very complicated.

*Martin

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 1
Guide ,
Sep 09, 2020

Copied

I'd try something like this:

``````seed = 1103; // change this to get different result
f = timeToFrames(time);
if (f >= 120){
seg = Math.floor((f - 120)/24);
ph = (f - 120)%24;
seedRandom(seed+seg,true);
fStart = Math.floor(random(96));
f = fStart+ph;
}
framesToTime(f)``````

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 2
Guide ,
Sep 09, 2020

Copied

... and I was so proud of my solution 🙂

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 1
LATEST
Community Beginner ,
Sep 09, 2020

Copied

Thank you very much! This seems to work as intended. Sorry Martin I did not get to try your solution as well!

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Sep 09, 2020 0
Resources
Troubleshooting FAQs
After Effects Community Recap
Getting started with After Effects