mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-10-30 07:22:35 +01:00
Updated MediaInfo schema and revised logic that Formats it. Also added logic to log events to Sentry.
This commit is contained in:
parent
94f2473fbb
commit
27dca830cc
@ -78,6 +78,16 @@ namespace NzbDrone.Common.Extensions
|
||||
return !string.IsNullOrWhiteSpace(text);
|
||||
}
|
||||
|
||||
public static bool StartsWithIgnoreCase(this string text, string startsWith)
|
||||
{
|
||||
return text.StartsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool EqualsIgnoreCase(this string text, string equals)
|
||||
{
|
||||
return text.Equals(equals, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool ContainsIgnoreCase(this string text, string contains)
|
||||
{
|
||||
return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1;
|
||||
@ -118,4 +128,4 @@ namespace NzbDrone.Common.Extensions
|
||||
return Encoding.ASCII.GetString(new [] { byteResult });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
|
||||
namespace NzbDrone.Common.Instrumentation.Extensions
|
||||
{
|
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
|
||||
namespace NzbDrone.Common.Instrumentation.Extensions
|
||||
{
|
||||
public static class SentryLoggerExtensions
|
||||
{
|
||||
public static readonly Logger SentryLogger = LogManager.GetLogger("Sentry");
|
||||
|
||||
public static LogBuilder SentryFingerprint(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return logBuilder.Property("Sentry", fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryDebug(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Debug, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryInfo(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Info, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryWarn(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Warn, fingerprint);
|
||||
}
|
||||
|
||||
public static LogBuilder WriteSentryError(this LogBuilder logBuilder, params string[] fingerprint)
|
||||
{
|
||||
return LogSentryMessage(logBuilder, LogLevel.Error, fingerprint);
|
||||
}
|
||||
|
||||
private static LogBuilder LogSentryMessage(LogBuilder logBuilder, LogLevel level, string[] fingerprint)
|
||||
{
|
||||
SentryLogger.Log(level)
|
||||
.CopyLogEvent(logBuilder.LogEventInfo)
|
||||
.SentryFingerprint(fingerprint)
|
||||
.Write();
|
||||
|
||||
return logBuilder.Property("Sentry", null);
|
||||
}
|
||||
|
||||
private static LogBuilder CopyLogEvent(this LogBuilder logBuilder, LogEventInfo logEvent)
|
||||
{
|
||||
return logBuilder.LoggerName(logEvent.LoggerName)
|
||||
.TimeStamp(logEvent.TimeStamp)
|
||||
.Message(logEvent.Message, logEvent.Parameters)
|
||||
.Properties((Dictionary<object, object>)logEvent.Properties)
|
||||
.Exception(logEvent.Exception);
|
||||
}
|
||||
}
|
||||
}
|
@ -109,9 +109,13 @@ namespace NzbDrone.Common.Instrumentation
|
||||
Layout = "${message}"
|
||||
};
|
||||
|
||||
var loggingRule = new LoggingRule("*", updateClient ? LogLevel.Trace : LogLevel.Error, target);
|
||||
var loggingRule = new LoggingRule("*", updateClient ? LogLevel.Trace : LogLevel.Warn, target);
|
||||
LogManager.Configuration.AddTarget("sentryTarget", target);
|
||||
LogManager.Configuration.LoggingRules.Add(loggingRule);
|
||||
|
||||
// Events logged to Sentry go only to Sentry.
|
||||
var loggingRuleSentry = new LoggingRule("Sentry", LogLevel.Debug, target) { Final = true };
|
||||
LogManager.Configuration.LoggingRules.Insert(0, loggingRuleSentry);
|
||||
}
|
||||
|
||||
private static void RegisterDebugger()
|
||||
|
@ -71,6 +71,11 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
|
||||
private static List<string> GetFingerPrint(LogEventInfo logEvent)
|
||||
{
|
||||
if (logEvent.Properties.ContainsKey("Sentry"))
|
||||
{
|
||||
return ((string[])logEvent.Properties["Sentry"]).ToList();
|
||||
}
|
||||
|
||||
var fingerPrint = new List<string>
|
||||
{
|
||||
logEvent.Level.Ordinal.ToString(),
|
||||
@ -94,13 +99,33 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
return fingerPrint;
|
||||
}
|
||||
|
||||
private bool IsSentryMessage(LogEventInfo logEvent)
|
||||
{
|
||||
if (logEvent.Properties.ContainsKey("Sentry"))
|
||||
{
|
||||
return logEvent.Properties["Sentry"] != null;
|
||||
}
|
||||
|
||||
if (logEvent.Level >= LogLevel.Error && logEvent.Exception != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected override void Write(LogEventInfo logEvent)
|
||||
{
|
||||
if (_unauthorized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// don't report non-critical events without exceptions
|
||||
if (logEvent.Exception == null || _unauthorized)
|
||||
if (!IsSentryMessage(logEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -112,6 +137,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
}
|
||||
|
||||
var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
|
||||
extras.Remove("Sentry");
|
||||
_client.Logger = logEvent.LoggerName;
|
||||
|
||||
var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters);
|
||||
@ -134,11 +160,16 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
sentryEvent.Fingerprint.Add(logEvent.Exception.GetType().FullName);
|
||||
}
|
||||
|
||||
if (logEvent.Properties.ContainsKey("Sentry"))
|
||||
{
|
||||
sentryEvent.Fingerprint.Clear();
|
||||
Array.ForEach((string[])logEvent.Properties["Sentry"], sentryEvent.Fingerprint.Add);
|
||||
}
|
||||
|
||||
var osName = Environment.GetEnvironmentVariable("OS_NAME");
|
||||
var osVersion = Environment.GetEnvironmentVariable("OS_VERSION");
|
||||
var runTimeVersion = Environment.GetEnvironmentVariable("RUNTIME_VERSION");
|
||||
|
||||
|
||||
sentryEvent.Tags.Add("os_name", osName);
|
||||
sentryEvent.Tags.Add("os_version", $"{osName} {osVersion}");
|
||||
sentryEvent.Tags.Add("runtime_version", $"{PlatformInfo.PlatformName} {runTimeVersion}");
|
||||
|
@ -177,7 +177,8 @@
|
||||
<Compile Include="Http\UserAgentBuilder.cs" />
|
||||
<Compile Include="Instrumentation\CleanseLogMessage.cs" />
|
||||
<Compile Include="Instrumentation\CleansingJsonVisitor.cs" />
|
||||
<Compile Include="Instrumentation\Extensions\LoggerProgressExtensions.cs" />
|
||||
<Compile Include="Instrumentation\Extensions\LoggerExtensions.cs" />
|
||||
<Compile Include="Instrumentation\Extensions\SentryLoggerExtensions.cs" />
|
||||
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
|
||||
<Compile Include="Instrumentation\LogEventExtensions.cs" />
|
||||
<Compile Include="Instrumentation\NzbDroneFileTarget.cs" />
|
||||
|
@ -41,11 +41,12 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
|
||||
{
|
||||
var mediaInfoModel = new MediaInfoModel
|
||||
{
|
||||
AudioFormat = "Other Audio Format"
|
||||
AudioFormat = "Other Audio Format",
|
||||
AudioCodecID = "Other Audio Codec"
|
||||
};
|
||||
|
||||
MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).Should().Be(mediaInfoModel.AudioFormat);
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,15 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_VideoCodec_by_default()
|
||||
public void should_return_VideoFormat_by_default()
|
||||
{
|
||||
var mediaInfoModel = new MediaInfoModel
|
||||
{
|
||||
VideoCodec = "VideoCodec"
|
||||
VideoFormat = "VideoCodec"
|
||||
};
|
||||
|
||||
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoCodec);
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoFormat);
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,33 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
|
||||
.All()
|
||||
.With(v => v.RelativePath = "media.mkv")
|
||||
.TheFirst(1)
|
||||
.With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = 3 })
|
||||
.With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = UpdateMediaInfoService.CURRENT_MEDIA_INFO_SCHEMA_REVISION })
|
||||
.BuildList();
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(v => v.GetFilesBySeries(1))
|
||||
.Returns(episodeFiles);
|
||||
|
||||
GivenFileExists();
|
||||
GivenSuccessfulScan();
|
||||
|
||||
Subject.Handle(new SeriesScannedEvent(_series));
|
||||
|
||||
Mocker.GetMock<IVideoFileInfoReader>()
|
||||
.Verify(v => v.GetMediaInfo(Path.Combine(_series.Path, "media.mkv")), Times.Exactly(2));
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Verify(v => v.Update(It.IsAny<EpisodeFile>()), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_skip_not_yet_date_media_info()
|
||||
{
|
||||
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(3)
|
||||
.All()
|
||||
.With(v => v.RelativePath = "media.mkv")
|
||||
.TheFirst(1)
|
||||
.With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = UpdateMediaInfoService.MINIMUM_MEDIA_INFO_SCHEMA_REVISION })
|
||||
.BuildList();
|
||||
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
|
@ -3,8 +3,10 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NLog.Fluent;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
{
|
||||
@ -41,6 +43,74 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
}
|
||||
|
||||
public static string FormatAudioCodec(MediaInfoModel mediaInfo, string sceneName)
|
||||
{
|
||||
if (mediaInfo.AudioCodecID == null)
|
||||
{
|
||||
return FormatAudioCodecLegacy(mediaInfo, sceneName);
|
||||
}
|
||||
|
||||
var audioFormat = mediaInfo.AudioFormat;
|
||||
var audioCodecID = mediaInfo.AudioCodecID ?? string.Empty;
|
||||
var audioProfile = mediaInfo.AudioProfile ?? string.Empty;
|
||||
var audioCodecLibrary = mediaInfo.AudioCodecLibrary ?? string.Empty;
|
||||
|
||||
if (audioFormat.IsNullOrWhiteSpace())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("AC-3"))
|
||||
{
|
||||
return "AC3";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("E-AC-3"))
|
||||
{
|
||||
return "EAC3";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("AAC"))
|
||||
{
|
||||
if (audioCodecID == "A_AAC/MPEG4/LC/SBR")
|
||||
{
|
||||
return "HE-AAC";
|
||||
}
|
||||
|
||||
return "AAC";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("DTS"))
|
||||
{
|
||||
return "DTS";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("FLAC"))
|
||||
{
|
||||
return "FLAC";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("MPEG Audio"))
|
||||
{
|
||||
if (mediaInfo.AudioCodecID == "55" || mediaInfo.AudioCodecID == "A_MPEG/L3" || mediaInfo.AudioProfile == "Layer 3")
|
||||
{
|
||||
return "MP3";
|
||||
}
|
||||
|
||||
if (mediaInfo.AudioProfile == "Layer 2")
|
||||
{
|
||||
return "MP2";
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Debug()
|
||||
.Message("Unknown audio format: '{0}' in '{1}'.", string.Join(", ", audioFormat, audioCodecID, audioProfile, audioCodecLibrary), sceneName)
|
||||
.WriteSentryWarn("UnknownAudioFormat", mediaInfo.ContainerFormat, audioFormat, audioCodecID)
|
||||
.Write();
|
||||
|
||||
return audioFormat;
|
||||
}
|
||||
|
||||
public static string FormatAudioCodecLegacy(MediaInfoModel mediaInfo, string sceneName)
|
||||
{
|
||||
var audioFormat = mediaInfo.AudioFormat;
|
||||
|
||||
@ -49,51 +119,120 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
return audioFormat;
|
||||
}
|
||||
|
||||
if (audioFormat == "AC-3")
|
||||
if (audioFormat.EqualsIgnoreCase("AC-3"))
|
||||
{
|
||||
return "AC3";
|
||||
}
|
||||
|
||||
if (audioFormat == "E-AC-3")
|
||||
if (audioFormat.EqualsIgnoreCase("E-AC-3"))
|
||||
{
|
||||
return "EAC3";
|
||||
}
|
||||
|
||||
if (audioFormat == "AAC")
|
||||
if (audioFormat.EqualsIgnoreCase("AAC"))
|
||||
{
|
||||
return "AAC";
|
||||
}
|
||||
|
||||
if (audioFormat == "MPEG Audio")
|
||||
if (audioFormat.EqualsIgnoreCase("MPEG Audio") && mediaInfo.AudioProfile == "Layer 3")
|
||||
{
|
||||
return mediaInfo.AudioProfile == "Layer 3" ? "MP3" : audioFormat;
|
||||
return "MP3";
|
||||
}
|
||||
|
||||
if (audioFormat == "DTS")
|
||||
if (audioFormat.EqualsIgnoreCase("DTS"))
|
||||
{
|
||||
return "DTS";
|
||||
}
|
||||
|
||||
if (audioFormat.Equals("FLAC", StringComparison.OrdinalIgnoreCase))
|
||||
if (audioFormat.EqualsIgnoreCase("TrueHD"))
|
||||
{
|
||||
return "TrueHD";
|
||||
}
|
||||
|
||||
if (audioFormat.EqualsIgnoreCase("FLAC"))
|
||||
{
|
||||
return "FLAC";
|
||||
}
|
||||
|
||||
if (audioFormat.Equals("Vorbis", StringComparison.OrdinalIgnoreCase))
|
||||
if (audioFormat.EqualsIgnoreCase("Vorbis"))
|
||||
{
|
||||
return "Vorbis";
|
||||
}
|
||||
|
||||
if (audioFormat.Equals("Opus", StringComparison.OrdinalIgnoreCase))
|
||||
if (audioFormat.EqualsIgnoreCase("Opus"))
|
||||
{
|
||||
return "Opus";
|
||||
}
|
||||
|
||||
Logger.Error(new UnknownCodecException(audioFormat, sceneName), "Unknown audio format: {0} in '{1}'. Please notify Sonarr developers.", audioFormat, sceneName);
|
||||
return audioFormat;
|
||||
}
|
||||
|
||||
public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName)
|
||||
{
|
||||
if (mediaInfo.VideoFormat == null)
|
||||
{
|
||||
return FormatVideoCodecLegacy(mediaInfo, sceneName);
|
||||
}
|
||||
|
||||
var videoFormat = mediaInfo.VideoFormat;
|
||||
var videoCodecID = mediaInfo.VideoCodecID ?? string.Empty;
|
||||
var videoProfile = mediaInfo.VideoProfile ?? string.Empty;
|
||||
var videoCodecLibrary = mediaInfo.VideoCodecLibrary ?? string.Empty;
|
||||
|
||||
if (videoFormat.IsNullOrWhiteSpace())
|
||||
{
|
||||
return videoFormat;
|
||||
}
|
||||
|
||||
if (videoFormat == "AVC")
|
||||
{
|
||||
if (videoCodecLibrary.StartsWithIgnoreCase("x264"))
|
||||
{
|
||||
return "x264";
|
||||
}
|
||||
|
||||
return GetSceneNameMatch(sceneName, "AVC", "h264");
|
||||
}
|
||||
|
||||
if (videoFormat == "HEVC")
|
||||
{
|
||||
if (videoCodecLibrary.StartsWithIgnoreCase("x265"))
|
||||
{
|
||||
return "x265";
|
||||
}
|
||||
|
||||
return GetSceneNameMatch(sceneName, "HEVC", "h265");
|
||||
}
|
||||
|
||||
if (videoFormat == "MPEG-2 Video")
|
||||
{
|
||||
return "MPEG2";
|
||||
}
|
||||
|
||||
if (videoFormat == "MPEG-4 Visual")
|
||||
{
|
||||
if (videoCodecID.ContainsIgnoreCase("XVID"))
|
||||
{
|
||||
return "XviD";
|
||||
}
|
||||
|
||||
if (videoCodecID.ContainsIgnoreCase("DIV3") ||
|
||||
videoCodecID.ContainsIgnoreCase("DIVX") ||
|
||||
videoCodecID.ContainsIgnoreCase("DX50"))
|
||||
{
|
||||
return "DivX";
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Debug()
|
||||
.Message("Unknown video format: '{0}' in '{1}'.", string.Join(", ", videoFormat, videoCodecID, videoProfile, videoCodecLibrary), sceneName)
|
||||
.WriteSentryWarn("UnknownVideoFormat", mediaInfo.ContainerFormat, videoFormat, videoCodecID)
|
||||
.Write();
|
||||
|
||||
return videoFormat;
|
||||
}
|
||||
|
||||
public static string FormatVideoCodecLegacy(MediaInfoModel mediaInfo, string sceneName)
|
||||
{
|
||||
var videoCodec = mediaInfo.VideoCodec;
|
||||
|
||||
@ -104,16 +243,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
|
||||
if (videoCodec == "AVC")
|
||||
{
|
||||
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).Contains("h264")
|
||||
? "h264"
|
||||
: "x264";
|
||||
return GetSceneNameMatch(sceneName, "AVC", "h264", "x264");
|
||||
}
|
||||
|
||||
if (videoCodec == "V_MPEGH/ISO/HEVC" || videoCodec == "HEVC")
|
||||
{
|
||||
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("h265")
|
||||
? "h265"
|
||||
: "x265";
|
||||
return GetSceneNameMatch(sceneName, "HEVC", "h265", "x265");
|
||||
}
|
||||
|
||||
if (videoCodec == "MPEG-2 Video")
|
||||
@ -123,28 +258,41 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
|
||||
if (videoCodec == "MPEG-4 Visual")
|
||||
{
|
||||
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("DivX")
|
||||
? "DivX"
|
||||
: "XviD";
|
||||
return GetSceneNameMatch(sceneName, "DivX", "XviD");
|
||||
}
|
||||
|
||||
if (videoCodec.StartsWith("XviD", StringComparison.OrdinalIgnoreCase))
|
||||
if (videoCodec.StartsWithIgnoreCase("XviD"))
|
||||
{
|
||||
return "XviD";
|
||||
}
|
||||
|
||||
if (videoCodec.StartsWith("DivX", StringComparison.OrdinalIgnoreCase))
|
||||
if (videoCodec.StartsWithIgnoreCase("DivX"))
|
||||
{
|
||||
return "DivX";
|
||||
}
|
||||
|
||||
if (videoCodec.Equals("VC-1", StringComparison.OrdinalIgnoreCase))
|
||||
if (videoCodec.EqualsIgnoreCase("VC-1"))
|
||||
{
|
||||
return "VC1";
|
||||
}
|
||||
|
||||
Logger.Error(new UnknownCodecException(videoCodec, sceneName), "Unknown video codec: {0} in '{1}'. Please notify Sonarr developers.", videoCodec, sceneName);
|
||||
return videoCodec;
|
||||
}
|
||||
|
||||
private static string GetSceneNameMatch(string sceneName, params string[] tokens)
|
||||
{
|
||||
sceneName = sceneName.IsNotNullOrWhiteSpace() ? Path.GetFileNameWithoutExtension(sceneName) : string.Empty;
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (sceneName.ContainsIgnoreCase(token))
|
||||
{
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
// Last token is the default.
|
||||
return tokens.Last();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,20 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
{
|
||||
public class MediaInfoModel : IEmbeddedDocument
|
||||
{
|
||||
public string ContainerFormat { get; set; }
|
||||
// Deprecated according to MediaInfo
|
||||
public string VideoCodec { get; set; }
|
||||
public string VideoFormat { get; set; }
|
||||
public string VideoCodecID { get; set; }
|
||||
public string VideoProfile { get; set; }
|
||||
public string VideoCodecLibrary { get; set; }
|
||||
public int VideoBitrate { get; set; }
|
||||
public int VideoBitDepth { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public string AudioFormat { get; set; }
|
||||
public string AudioCodecID { get; set; }
|
||||
public string AudioCodecLibrary { get; set; }
|
||||
public int AudioBitrate { get; set; }
|
||||
public TimeSpan RunTime { get; set; }
|
||||
public int AudioStreamCount { get; set; }
|
||||
|
@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
{
|
||||
public class UnknownCodecException : Exception
|
||||
{
|
||||
public string Codec { get; set; }
|
||||
public string SceneName { get; set; }
|
||||
|
||||
public UnknownCodecException(string codec, string sceneName)
|
||||
: base($"Unknown codec {codec}")
|
||||
{
|
||||
Codec = codec;
|
||||
SceneName = sceneName;
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,8 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 3;
|
||||
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 3;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 4;
|
||||
|
||||
public UpdateMediaInfoService(IDiskProvider diskProvider,
|
||||
IMediaFileService mediaFileService,
|
||||
@ -65,7 +66,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
}
|
||||
|
||||
var allMediaFiles = _mediaFileService.GetFilesBySeries(message.Series.Id);
|
||||
var filteredMediaFiles = allMediaFiles.Where(c => c.MediaInfo == null || c.MediaInfo.SchemaRevision < CURRENT_MEDIA_INFO_SCHEMA_REVISION).ToList();
|
||||
var filteredMediaFiles = allMediaFiles.Where(c => c.MediaInfo == null || c.MediaInfo.SchemaRevision < MINIMUM_MEDIA_INFO_SCHEMA_REVISION).ToList();
|
||||
|
||||
UpdateMediaInfo(message.Series, filteredMediaFiles);
|
||||
}
|
||||
|
@ -104,54 +104,44 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "PlayTime"), out audioRuntime);
|
||||
int.TryParse(mediaInfo.Get(StreamKind.General, 0, "PlayTime"), out generalRuntime);
|
||||
|
||||
string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate");
|
||||
int aBindex = aBitRate.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (aBindex > 0)
|
||||
{
|
||||
aBitRate = aBitRate.Remove(aBindex);
|
||||
}
|
||||
string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
|
||||
|
||||
int.TryParse(aBitRate, out audioBitRate);
|
||||
int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount);
|
||||
|
||||
|
||||
string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)");
|
||||
int aCindex = audioChannelsStr.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (aCindex > 0)
|
||||
{
|
||||
audioChannelsStr = audioChannelsStr.Remove(aCindex);
|
||||
}
|
||||
string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
|
||||
|
||||
var audioChannelPositions = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions/String2");
|
||||
var audioChannelPositionsText = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions");
|
||||
|
||||
string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List");
|
||||
string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile");
|
||||
|
||||
int aPindex = audioProfile.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (aPindex > 0)
|
||||
{
|
||||
audioProfile = audioProfile.Remove(aPindex);
|
||||
}
|
||||
string videoProfile = mediaInfo.Get(StreamKind.Video, 0, "Format_Profile").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
|
||||
string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
|
||||
|
||||
int.TryParse(audioChannelsStr, out audioChannels);
|
||||
var mediaInfoModel = new MediaInfoModel
|
||||
{
|
||||
VideoCodec = mediaInfo.Get(StreamKind.Video, 0, "Codec/String"),
|
||||
ContainerFormat = mediaInfo.Get(StreamKind.General, 0, "Format"),
|
||||
VideoFormat = mediaInfo.Get(StreamKind.Video, 0, "Format"),
|
||||
VideoCodecID = mediaInfo.Get(StreamKind.Video, 0, "CodecID"),
|
||||
VideoProfile = videoProfile,
|
||||
VideoCodecLibrary = mediaInfo.Get(StreamKind.Video, 0, "Encoded_Library"),
|
||||
VideoBitrate = videoBitRate,
|
||||
VideoBitDepth = videoBitDepth,
|
||||
Height = height,
|
||||
Width = width,
|
||||
AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"),
|
||||
AudioCodecID = mediaInfo.Get(StreamKind.Audio, 0, "CodecID"),
|
||||
AudioProfile = audioProfile,
|
||||
AudioCodecLibrary = mediaInfo.Get(StreamKind.Audio, 0, "Encoded_Library"),
|
||||
AudioBitrate = audioBitRate,
|
||||
RunTime = GetBestRuntime(audioRuntime, videoRuntime, generalRuntime),
|
||||
AudioStreamCount = streamCount,
|
||||
AudioChannels = audioChannels,
|
||||
AudioChannelPositions = audioChannelPositions,
|
||||
AudioChannelPositionsText = audioChannelPositionsText,
|
||||
AudioProfile = audioProfile.Trim(),
|
||||
VideoFps = videoFrameRate,
|
||||
AudioLanguages = audioLanguages,
|
||||
Subtitles = subtitles,
|
||||
|
@ -807,7 +807,6 @@
|
||||
<Compile Include="MediaFiles\MediaInfo\MediaInfoFormatter.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\MediaInfoLib.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\MediaInfoModel.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\UnknownCodecException.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\UpdateMediaInfoService.cs" />
|
||||
<Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" />
|
||||
<Compile Include="MediaFiles\RecycleBinProvider.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user