using System.IO; using EmbyToolbox.Models; namespace EmbyToolbox.Services; /// MPEG-TS remux: генерация PTS и fallback при ошибках mux. public static class MpegTsTimestampHelpers { /// Входной файл распознан как MPEG Transport Stream (.ts / m2ts или format_name mpegts). public static bool IsMpegTsInput(MediaAnalysisResult? media, string? fileName) { if (media is null) { return false; } var blob = ((media.ContainerFormat ?? string.Empty) + "," + (media.FormatName ?? string.Empty)).ToLowerInvariant(); if (blob.Contains("mpegts", StringComparison.Ordinal) || blob.Contains("mpeg-ts", StringComparison.Ordinal) || blob.Contains("m2ts", StringComparison.Ordinal)) { return true; } if (!string.IsNullOrEmpty(fileName)) { var ext = Path.GetExtension(fileName); if (ext.Equals(".ts", StringComparison.OrdinalIgnoreCase) || ext.Equals(".m2ts", StringComparison.OrdinalIgnoreCase) || ext.Equals(".mts", StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } /// Сообщения ffmpeg при copy/remux без валидных PTS. public static bool LooksLikeTimestampMuxFailure(string? stderr) { if (string.IsNullOrWhiteSpace(stderr)) { return false; } var s = stderr.AsSpan(); return ContainsLoose(s, "unknown timestamp") || ContainsLoose(s, "Timestamps are unset") || ContainsLoose(s, "unset in a packet") || ContainsLoose(s, "Can't write packet with unknown timestamp"); } private static bool ContainsLoose(ReadOnlySpan haystack, string needle) { return haystack.Contains(needle, StringComparison.OrdinalIgnoreCase); } }