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.

This commit is contained in:
Leonid Pershin
2026-07-25 13:39:11 +03:00
parent 18325fdfcc
commit 358adbff21
@@ -98,6 +98,9 @@ public sealed class FfmpegBumperRenderer(
var labelSize = Math.Max(14, h / 22); var labelSize = Math.Max(14, h / 22);
var gap = (int)(labelSize * 1.4); var gap = (int)(labelSize * 1.4);
// Доступная ширина под текст (поля по 4% с каждой стороны) — под неё ужимаем длинные строки.
var textWidth = (int)(w * 0.92);
var nowLabelY = (int)(h * 0.22); var nowLabelY = (int)(h * 0.22);
var nowTitleY = nowLabelY + gap; var nowTitleY = nowLabelY + gap;
var nextLabelY = (int)(h * 0.60); var nextLabelY = (int)(h * 0.60);
@@ -160,18 +163,22 @@ public sealed class FfmpegBumperRenderer(
var vchain = new StringBuilder(videoPrefix); var vchain = new StringBuilder(videoPrefix);
if (spec.FreeText) 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 line1Y = (int)(h * 0.40);
var line2Y = line1Y + (int)(titleSize * 1.2); var line2Y = line1Y + (int)(line2Size * 1.2);
vchain.Append(',').Append(DrawTitle(font, nowFile, spec.AccentColor, labelSize + 4, line1Y, 0.2)); vchain.Append(',').Append(DrawTitle(font, nowFile, spec.AccentColor, line1Size, line1Y, 0.2));
vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, titleSize, line2Y, 0.5)); vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, line2Size, line2Y, 0.5));
} }
else 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(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(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]"); vchain.Append("[v]");
@@ -206,6 +213,18 @@ public sealed class FfmpegBumperRenderer(
return args; return args;
} }
/// <summary>
/// Подбирает размер шрифта так, чтобы строка влезла в <paramref name="maxWidth"/> по ширине:
/// drawtext не умеет авто-fit, поэтому оцениваем ширину как len × 0.62 × fontsize (кириллица
/// шире латиницы) и ужимаем базовый размер, но не мельче трети от него.
/// </summary>
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 readonly string[] ImageExtensions = [".jpg", ".jpeg", ".png", ".webp", ".bmp"];
private static bool IsImage(string path) => private static bool IsImage(string path) =>