TextSize Approximation with TextScaled Enabled

Oh, my bad on number 2, In the video you kept creating params when you were changing your viewport size, but silly me, anyways, I refactored your code, here you are:

local TextService = game:GetService("TextService")

local TextSizeEstimator = {}
TextSizeEstimator.__index = TextSizeEstimator

function TextSizeEstimator.new(label)
    assert(label:IsA("TextLabel"), "TextSizeEstimator expects a TextLabel")
    local self = setmetatable({}, TextSizeEstimator)
    self.Label = label
    self.Params = Instance.new("GetTextBoundsParams")
    self.Params.Font = label.FontFace
    self.Params.Width = math.huge
    self.Params.Text = label.Text
    self.Params.RichText = label.RichText
    return self
end

function TextSizeEstimator:GetBounds(size)
    self.Params.Size = size
    return TextService:GetTextBoundsAsync(self.Params)
end

function TextSizeEstimator:Estimate()
    if not self.Label.TextScaled then
        return self.Label.TextSize
    end

    if not self.Label.Text or self.Label.Text == "" then
        return 0
    end

    local smallSize, largeSize = 1, 100
    local boundsSmall = self:GetBounds(smallSize)
    local boundsLarge = self:GetBounds(largeSize)

    local actualBounds = self.Label.TextBounds
    local volume = actualBounds.X * actualBounds.Y

    local volumeSmall = boundsSmall.X * boundsSmall.Y
    local volumeLarge = boundsLarge.X * boundsLarge.Y

    local scaleSmall = math.sqrt(volumeSmall / volume)
    local scaleLarge = math.sqrt(volumeLarge / volume)

    local estimatedSize = smallSize + (1 - scaleSmall) * (largeSize - smallSize) / (scaleLarge - scaleSmall)
    local rows = math.max(1, math.round(actualBounds.Y / estimatedSize))

    return math.floor(actualBounds.Y / rows)
end

return TextSizeEstimator

also, I made a little helper for input Tired of Rewriting Keybind Logic? InputManager Handles It All—Context, Debounce, Gamepad, Touch - Resources / Community Resources - Developer Forum | Roblox