Add bumper variant management: implement API endpoints for adding, updating, and removing bumper text variants, enhance data models to support variant details, and update scheduling logic to utilize variants. Refactor related components for improved bumper template handling and ensure proper error management for variant operations.

This commit is contained in:
Leonid Pershin
2026-07-25 13:24:11 +03:00
parent f640af1fc4
commit a65bcf4258
34 changed files with 2009 additions and 170 deletions
@@ -35,12 +35,14 @@ public sealed class FfmpegBumperRenderer(
Directory.Delete(assetDir, recursive: true);
Directory.CreateDirectory(assetDir);
// Динамический текст (названия шоу) пишем в файлы и читаем через textfile= с expansion=none —
// так произвольные символы/кириллица не ломают синтаксис фильтра.
// Динамический текст (названия шоу / свободные строки) пишем в файлы и читаем через textfile=
// с expansion=none — так произвольные символы/кириллица не ломают синтаксис фильтра.
var nowFile = Path.Combine(assetDir, "now.txt");
var nextFile = Path.Combine(assetDir, "next.txt");
await File.WriteAllTextAsync(nowFile, spec.NowTitle, new UTF8Encoding(false), cancellationToken);
await File.WriteAllTextAsync(nextFile, spec.NextTitle, new UTF8Encoding(false), cancellationToken);
var line1 = spec.FreeText ? spec.FreeLine1 : spec.NowTitle;
var line2 = spec.FreeText ? spec.FreeLine2 : spec.NextTitle;
await File.WriteAllTextAsync(nowFile, line1, new UTF8Encoding(false), cancellationToken);
await File.WriteAllTextAsync(nextFile, line2, new UTF8Encoding(false), cancellationToken);
try
{
@@ -156,10 +158,21 @@ public sealed class FfmpegBumperRenderer(
}
var vchain = new StringBuilder(videoPrefix);
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(DrawLabel(font, spec.NextLabel, spec.AccentColor, labelSize, nextLabelY, 1.0));
vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, titleSize, nextTitleY, 1.1));
if (spec.FreeText)
{
// Свободный текст: две центрированные строки (акцентная + основная).
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));
}
else
{
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(DrawLabel(font, spec.NextLabel, spec.AccentColor, labelSize, nextLabelY, 1.0));
vchain.Append(',').Append(DrawTitle(font, nextFile, spec.TextColor, titleSize, nextTitleY, 1.1));
}
vchain.Append("[v]");
var filterComplex = $"{vchain};{audioChain}";