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);
}
}