43 lines
1.7 KiB
C#
43 lines
1.7 KiB
C#
using System.Text;
|
||
|
||
namespace EmbyToolbox.Services;
|
||
|
||
public sealed class ChapterBuilderService
|
||
{
|
||
public string BuildFfmetadata(IReadOnlyList<string> chapterTitles, IReadOnlyList<double> durationsSeconds)
|
||
{
|
||
if (chapterTitles.Count != durationsSeconds.Count)
|
||
{
|
||
throw new ArgumentException("Количество глав не совпадает с количеством длительностей.");
|
||
}
|
||
|
||
var sb = new StringBuilder();
|
||
sb.AppendLine(";FFMETADATA1");
|
||
long currentStartMs = 0;
|
||
for (var i = 0; i < chapterTitles.Count; i++)
|
||
{
|
||
var durationMs = Math.Max(1L, (long)Math.Round(Math.Max(0.001, durationsSeconds[i]) * 1000.0, MidpointRounding.AwayFromZero));
|
||
var endMs = currentStartMs + durationMs - 1;
|
||
var title = string.IsNullOrWhiteSpace(chapterTitles[i]) ? $"Часть {i + 1}" : chapterTitles[i].Trim();
|
||
sb.AppendLine("[CHAPTER]");
|
||
sb.AppendLine("TIMEBASE=1/1000");
|
||
sb.AppendLine($"START={currentStartMs}");
|
||
sb.AppendLine($"END={endMs}");
|
||
sb.AppendLine($"title={EscapeMetadataValue(title)}");
|
||
currentStartMs += durationMs;
|
||
}
|
||
|
||
return sb.ToString();
|
||
}
|
||
|
||
private static string EscapeMetadataValue(string value) =>
|
||
value
|
||
.Replace("\\", "\\\\", StringComparison.Ordinal)
|
||
.Replace("=", "\\=", StringComparison.Ordinal)
|
||
.Replace(";", "\\;", StringComparison.Ordinal)
|
||
.Replace("#", "\\#", StringComparison.Ordinal)
|
||
.Replace(Environment.NewLine, " ", StringComparison.Ordinal)
|
||
.Replace("\n", " ", StringComparison.Ordinal)
|
||
.Replace("\r", " ", StringComparison.Ordinal);
|
||
}
|