From 358adbff214424eeb2d0f4ead1c5a973f78677e2 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sat, 25 Jul 2026 13:39:11 +0300 Subject: [PATCH] Enhance FfmpegBumperRenderer: introduce text width adjustment for dynamic font sizing, ensuring proper fitting of free text and titles within the specified width. Add FitSize method to calculate optimal font size based on text length and maximum width constraints. --- .../Media/FfmpegBumperRenderer.cs | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/backend/src/TeleWave.Infrastructure/Media/FfmpegBumperRenderer.cs b/backend/src/TeleWave.Infrastructure/Media/FfmpegBumperRenderer.cs index 446308e..dac0726 100644 --- a/backend/src/TeleWave.Infrastructure/Media/FfmpegBumperRenderer.cs +++ b/backend/src/TeleWave.Infrastructure/Media/FfmpegBumperRenderer.cs @@ -98,6 +98,9 @@ public sealed class FfmpegBumperRenderer( var labelSize = Math.Max(14, h / 22); var gap = (int)(labelSize * 1.4); + // Доступная ширина под текст (поля по 4% с каждой стороны) — под неё ужимаем длинные строки. + var textWidth = (int)(w * 0.92); + var nowLabelY = (int)(h * 0.22); var nowTitleY = nowLabelY + gap; var nextLabelY = (int)(h * 0.60); @@ -160,18 +163,22 @@ public sealed class FfmpegBumperRenderer( var vchain = new StringBuilder(videoPrefix); if (spec.FreeText) { - // Свободный текст: две центрированные строки (акцентная + основная). + // Свободный текст: две центрированные строки (акцентная + основная), ужатые под ширину кадра. + var line1Size = FitSize(spec.FreeLine1, labelSize + 4, textWidth); + var line2Size = FitSize(spec.FreeLine2, titleSize, textWidth); var line1Y = (int)(h * 0.40); - var line2Y = line1Y + (int)(titleSize * 1.2); - vchain.Append(',').Append(DrawTitle(font, nowFile, spec.AccentColor, labelSize + 4, line1Y, 0.2)); - vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, titleSize, line2Y, 0.5)); + var line2Y = line1Y + (int)(line2Size * 1.2); + vchain.Append(',').Append(DrawTitle(font, nowFile, spec.AccentColor, line1Size, line1Y, 0.2)); + vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, line2Size, line2Y, 0.5)); } else { + var nowSize = FitSize(spec.NowTitle, titleSize, textWidth); + var nextSize = FitSize(spec.NextTitle, titleSize, textWidth); vchain.Append(',').Append(DrawLabel(font, spec.NowLabel, spec.AccentColor, labelSize, nowLabelY, 0.2)); - vchain.Append(',').Append(DrawTitle(font, nowFile, spec.TextColor, titleSize, nowTitleY, 0.3)); + vchain.Append(',').Append(DrawTitle(font, nowFile, spec.TextColor, nowSize, nowTitleY, 0.3)); vchain.Append(',').Append(DrawLabel(font, spec.NextLabel, spec.AccentColor, labelSize, nextLabelY, 1.0)); - vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, titleSize, nextTitleY, 1.1)); + vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, nextSize, nextTitleY, 1.1)); } vchain.Append("[v]"); @@ -206,6 +213,18 @@ public sealed class FfmpegBumperRenderer( return args; } + /// + /// Подбирает размер шрифта так, чтобы строка влезла в по ширине: + /// drawtext не умеет авто-fit, поэтому оцениваем ширину как len × 0.62 × fontsize (кириллица + /// шире латиницы) и ужимаем базовый размер, но не мельче трети от него. + /// + private static int FitSize(string text, int baseSize, int maxWidth) + { + var len = string.IsNullOrEmpty(text) ? 1 : text.Length; + var fit = (int)(maxWidth / (len * 0.62)); + return Math.Clamp(fit, Math.Max(12, baseSize / 3), baseSize); + } + private static readonly string[] ImageExtensions = [".jpg", ".jpeg", ".png", ".webp", ".bmp"]; private static bool IsImage(string path) =>