Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Auto-scale text lines to same width on 1 layer

  • Auto-scale text lines to same width on 1 layer

    Posted by Julian Chojnacki on June 23, 2023 at 5:10 pm

    Hey champs!

    I’ve been working on this expression selector thingy that auto-scales every text line to the same width and got it to function decently. However, AE is acting up and refuses to render it consistently.

    Below I’ve attached a video (& project file) showing the problem and a weird little hack I found by accident that fixes the glitching sometimes. Any insight on what’s going on here would be interesting to hear.

    My theory is that sourceRectAtTime and the expression selector simply aren’t the best friends and need a little kick in the bum to get along again…

    I thought perhaps including posterizeTime(0) in the expression selector would be the logical solution, but that doesn’t do anything sadly.

    For a quick look, here’s the main code:

    maxWidth = effect("Custom Width")("Checkbox") == 1 ? effect("Max Width")("Slider") : sourceRectAtTime(-100).width; // Either based on a pixel value or the first line
    i = textIndex-1;
    lineWidths = sourceRectAtTime(-100-i).width; // Get all line widths
    scaleFactor = (maxWidth/lineWidths)*100; // Calculate a unique scaling factor for each line
    (scaleFactor-100)/9; // "Normalize" and divide by scaling % / 100 - 1

    Some context:

    • The code is affecting a scaling animator set to 1000%
    • I’m using @filipvandueren ‘s subSourceRect preset to isolate each line in negative time to get their widths for the necessary calculations. Line 1 sits in time -100, line 2 -101, line 3 -102, and so on

    Issues:

    • Weird glitching, inconsistency
    • For some reason, everything past the 4th line doesn’t scale anymore

    A potential workaround I tried was to avoid using sourceRectAtTime inside the expression selector and store the line widths in a slider at different times, to then recall them with valueAtTime, but so far I’ve failed and was hoping someone more qualified than me might be able to help or come up with another fix.

    Any smart thoughts to tame this little fella would be wonderful🙂

    Thanks!

    Julian Chojnacki replied 2 years, 10 months ago 2 Members · 6 Replies
  • 6 Replies
  • Filip Vandueren

    June 28, 2023 at 9:41 am

    Hmm. I’m stumped,

    the expression is correct, but there’s an error in how After effects sometimes does the calculations inside of the expression selector. The sourceRectAtTime is definitely not changing randomly, you can visualize those values via another textlayer, and the numbers stay consistent.

    I would perhaps do the calculations of the ratios once in a different textlayer, and get those values in the expression selector using split() or JSON.parse() of that result

  • Julian Chojnacki

    June 30, 2023 at 11:37 am

    Thanks for the suggestion, Filip!

    I tested the text layer method and it didn’t change much initially.

    Only when I ditched the line isolating range selector for an expression selector, it stabilized a bit. (wonder why)

    I noticed that now, glitching seems to mostly occur when hitting play at 0.

    Switching from full res to half res and vice versa, or updating the layer in another way seems to fix it.

    That said, when it catches some breath, playback is consistent now 👍

    Also, all lines are scaling as they should.

    Here are the updated expressions:

    Source text

    const widths = value.split("\r").map((_, i) => sourceRectAtTime(-1-i).width);

    if (time == -2){

    widths

    }else{

    value

    }

    Line Measurement:

    const t = -time;

    t == textIndex || time >= 0 ? 0 : 100;

    Expression selector

    const lW = text.sourceText.valueAtTime(-2).split(",").map(Number);

    const mW = effect("LineSizer")("Custom Width") == 1 ? effect("LineSizer")("Max Width") : lW[0]|1; // Fallback to 1 to ensure numeric value

    const i = textIndex-1;

    const s = (mW/(lW[i]|1))*100;

    time < 0 ? 0 : (s-100)/19; // Ternary to fix custom width not scaling as it should if there's only one line

    As you can see, I went the single-layer route because my goal for this is to work as an animation preset. Having a separate layer made no difference.

    Do you have any more thoughts on how to eliminate the glitching? I’ve experimented quite a lot and at this point, I’m running out of options.

    I could live with having to update the layer, but if anything else comes to your mind I’m listening 🙂

  • Julian Chojnacki

    June 30, 2023 at 6:04 pm

    Update: I just noticed that scrubbing through the timeline a bit before previewing prevents any glitches from happening! How’d I miss this… but there are still some bugged-out frames when using text animators.

  • Filip Vandueren

    July 1, 2023 at 1:24 pm

    Yes, I can’t consistently get it to stop from sometimes glitching either.

    So I think there’s no way to get some solution like this “production-ready” or fool-proof.

  • Julian Chojnacki

    July 5, 2023 at 11:20 am

    Bummer, but hey it works! Thanks anyway Filip 🙂

  • Julian Chojnacki

    July 5, 2023 at 8:32 pm

    Update: just found out that enabling motion blur or using the posterize time effect with a framerate other than the comps’ (could be 30.1 in a 30fps comp), fully eradicates glitched frames!

    Of course, there’s a little performance drop – a bit more for posterizeTime than MB which surprised me, but a working fix regardless. Case solved!

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