Updated MediaInfo schema and revised logic that Formats it. Also added logic to log events to Sentry.

Taloth Saldono 7 years ago
parent 94f2473fbb
commit 27dca830cc

@ -78,6 +78,16 @@ namespace NzbDrone.Common.Extensions
return !string.IsNullOrWhiteSpace(text); 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) public static bool ContainsIgnoreCase(this string text, string contains)
{ {
return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1; return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1;
@ -118,4 +128,4 @@ namespace NzbDrone.Common.Extensions
return Encoding.ASCII.GetString(new [] { byteResult }); return Encoding.ASCII.GetString(new [] { byteResult });
} }
} }
} }

@ -1,4 +1,5 @@
using NLog; using NLog;
using NLog.Fluent;
namespace NzbDrone.Common.Instrumentation.Extensions 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}" 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.AddTarget("sentryTarget", target);
LogManager.Configuration.LoggingRules.Add(loggingRule); 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() private static void RegisterDebugger()

@ -71,6 +71,11 @@ namespace NzbDrone.Common.Instrumentation.Sentry
private static List<string> GetFingerPrint(LogEventInfo logEvent) private static List<string> GetFingerPrint(LogEventInfo logEvent)
{ {
if (logEvent.Properties.ContainsKey("Sentry"))
{
return ((string[])logEvent.Properties["Sentry"]).ToList();
}
var fingerPrint = new List<string> var fingerPrint = new List<string>
{ {
logEvent.Level.Ordinal.ToString(), logEvent.Level.Ordinal.ToString(),
@ -94,13 +99,33 @@ namespace NzbDrone.Common.Instrumentation.Sentry
return fingerPrint; 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) protected override void Write(LogEventInfo logEvent)
{ {
if (_unauthorized)
{
return;
}
try try
{ {
// don't report non-critical events without exceptions // don't report non-critical events without exceptions
if (logEvent.Exception == null || _unauthorized) if (!IsSentryMessage(logEvent))
{ {
return; return;
} }
@ -112,6 +137,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
} }
var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString()); var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
extras.Remove("Sentry");
_client.Logger = logEvent.LoggerName; _client.Logger = logEvent.LoggerName;
var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters); var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters);
@ -134,11 +160,16 @@ namespace NzbDrone.Common.Instrumentation.Sentry
sentryEvent.Fingerprint.Add(logEvent.Exception.GetType().FullName); 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 osName = Environment.GetEnvironmentVariable("OS_NAME");
var osVersion = Environment.GetEnvironmentVariable("OS_VERSION"); var osVersion = Environment.GetEnvironmentVariable("OS_VERSION");
var runTimeVersion = Environment.GetEnvironmentVariable("RUNTIME_VERSION"); var runTimeVersion = Environment.GetEnvironmentVariable("RUNTIME_VERSION");
sentryEvent.Tags.Add("os_name", osName); sentryEvent.Tags.Add("os_name", osName);
sentryEvent.Tags.Add("os_version", $"{osName} {osVersion}"); sentryEvent.Tags.Add("os_version", $"{osName} {osVersion}");
sentryEvent.Tags.Add("runtime_version", $"{PlatformInfo.PlatformName} {runTimeVersion}"); sentryEvent.Tags.Add("runtime_version", $"{PlatformInfo.PlatformName} {runTimeVersion}");

@ -177,7 +177,8 @@
<Compile Include="Http\UserAgentBuilder.cs" /> <Compile Include="Http\UserAgentBuilder.cs" />
<Compile Include="Instrumentation\CleanseLogMessage.cs" /> <Compile Include="Instrumentation\CleanseLogMessage.cs" />
<Compile Include="Instrumentation\CleansingJsonVisitor.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\GlobalExceptionHandlers.cs" />
<Compile Include="Instrumentation\LogEventExtensions.cs" /> <Compile Include="Instrumentation\LogEventExtensions.cs" />
<Compile Include="Instrumentation\NzbDroneFileTarget.cs" /> <Compile Include="Instrumentation\NzbDroneFileTarget.cs" />

@ -41,11 +41,12 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{ {
var mediaInfoModel = new MediaInfoModel var mediaInfoModel = new MediaInfoModel
{ {
AudioFormat = "Other Audio Format" AudioFormat = "Other Audio Format",
AudioCodecID = "Other Audio Codec"
}; };
MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).Should().Be(mediaInfoModel.AudioFormat); 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] [Test]
public void should_return_VideoCodec_by_default() public void should_return_VideoFormat_by_default()
{ {
var mediaInfoModel = new MediaInfoModel var mediaInfoModel = new MediaInfoModel
{ {
VideoCodec = "VideoCodec" VideoFormat = "VideoCodec"
}; };
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoCodec); MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoFormat);
ExceptionVerification.ExpectedErrors(1); ExceptionVerification.ExpectedWarns(1);
} }
} }
} }

@ -60,7 +60,33 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
.All() .All()
.With(v => v.RelativePath = "media.mkv") .With(v => v.RelativePath = "media.mkv")
.TheFirst(1) .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(); .BuildList();
Mocker.GetMock<IMediaFileService>() Mocker.GetMock<IMediaFileService>()

@ -3,8 +3,10 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NLog.Fluent;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation;
using NzbDrone.Common.Instrumentation.Extensions;
namespace NzbDrone.Core.MediaFiles.MediaInfo namespace NzbDrone.Core.MediaFiles.MediaInfo
{ {
@ -41,6 +43,74 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
} }
public static string FormatAudioCodec(MediaInfoModel mediaInfo, string sceneName) 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; var audioFormat = mediaInfo.AudioFormat;
@ -49,51 +119,120 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return audioFormat; return audioFormat;
} }
if (audioFormat == "AC-3") if (audioFormat.EqualsIgnoreCase("AC-3"))
{ {
return "AC3"; return "AC3";
} }
if (audioFormat == "E-AC-3") if (audioFormat.EqualsIgnoreCase("E-AC-3"))
{ {
return "EAC3"; return "EAC3";
} }
if (audioFormat == "AAC") if (audioFormat.EqualsIgnoreCase("AAC"))
{ {
return "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"; return "DTS";
} }
if (audioFormat.Equals("FLAC", StringComparison.OrdinalIgnoreCase)) if (audioFormat.EqualsIgnoreCase("TrueHD"))
{
return "TrueHD";
}
if (audioFormat.EqualsIgnoreCase("FLAC"))
{ {
return "FLAC"; return "FLAC";
} }
if (audioFormat.Equals("Vorbis", StringComparison.OrdinalIgnoreCase)) if (audioFormat.EqualsIgnoreCase("Vorbis"))
{ {
return "Vorbis"; return "Vorbis";
} }
if (audioFormat.Equals("Opus", StringComparison.OrdinalIgnoreCase)) if (audioFormat.EqualsIgnoreCase("Opus"))
{ {
return "Opus"; return "Opus";
} }
Logger.Error(new UnknownCodecException(audioFormat, sceneName), "Unknown audio format: {0} in '{1}'. Please notify Sonarr developers.", audioFormat, sceneName);
return audioFormat; return audioFormat;
} }
public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName) 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; var videoCodec = mediaInfo.VideoCodec;
@ -104,16 +243,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
if (videoCodec == "AVC") if (videoCodec == "AVC")
{ {
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).Contains("h264") return GetSceneNameMatch(sceneName, "AVC", "h264", "x264");
? "h264"
: "x264";
} }
if (videoCodec == "V_MPEGH/ISO/HEVC" || videoCodec == "HEVC") if (videoCodec == "V_MPEGH/ISO/HEVC" || videoCodec == "HEVC")
{ {
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("h265") return GetSceneNameMatch(sceneName, "HEVC", "h265", "x265");
? "h265"
: "x265";
} }
if (videoCodec == "MPEG-2 Video") if (videoCodec == "MPEG-2 Video")
@ -123,28 +258,41 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
if (videoCodec == "MPEG-4 Visual") if (videoCodec == "MPEG-4 Visual")
{ {
return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("DivX") return GetSceneNameMatch(sceneName, "DivX", "XviD");
? "DivX"
: "XviD";
} }
if (videoCodec.StartsWith("XviD", StringComparison.OrdinalIgnoreCase)) if (videoCodec.StartsWithIgnoreCase("XviD"))
{ {
return "XviD"; return "XviD";
} }
if (videoCodec.StartsWith("DivX", StringComparison.OrdinalIgnoreCase)) if (videoCodec.StartsWithIgnoreCase("DivX"))
{ {
return "DivX"; return "DivX";
} }
if (videoCodec.Equals("VC-1", StringComparison.OrdinalIgnoreCase)) if (videoCodec.EqualsIgnoreCase("VC-1"))
{ {
return "VC1"; return "VC1";
} }
Logger.Error(new UnknownCodecException(videoCodec, sceneName), "Unknown video codec: {0} in '{1}'. Please notify Sonarr developers.", videoCodec, sceneName);
return videoCodec; 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 class MediaInfoModel : IEmbeddedDocument
{ {
public string ContainerFormat { get; set; }
// Deprecated according to MediaInfo
public string VideoCodec { get; set; } 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 VideoBitrate { get; set; }
public int VideoBitDepth { get; set; } public int VideoBitDepth { get; set; }
public int Width { get; set; } public int Width { get; set; }
public int Height { get; set; } public int Height { get; set; }
public string AudioFormat { get; set; } public string AudioFormat { get; set; }
public string AudioCodecID { get; set; }
public string AudioCodecLibrary { get; set; }
public int AudioBitrate { get; set; } public int AudioBitrate { get; set; }
public TimeSpan RunTime { get; set; } public TimeSpan RunTime { get; set; }
public int AudioStreamCount { 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 IConfigService _configService;
private readonly Logger _logger; 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, public UpdateMediaInfoService(IDiskProvider diskProvider,
IMediaFileService mediaFileService, IMediaFileService mediaFileService,
@ -65,7 +66,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
} }
var allMediaFiles = _mediaFileService.GetFilesBySeries(message.Series.Id); 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); 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.Audio, 0, "PlayTime"), out audioRuntime);
int.TryParse(mediaInfo.Get(StreamKind.General, 0, "PlayTime"), out generalRuntime); int.TryParse(mediaInfo.Get(StreamKind.General, 0, "PlayTime"), out generalRuntime);
string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate"); string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
int aBindex = aBitRate.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
if (aBindex > 0)
{
aBitRate = aBitRate.Remove(aBindex);
}
int.TryParse(aBitRate, out audioBitRate); int.TryParse(aBitRate, out audioBitRate);
int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount); int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount);
string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)"); string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim();
int aCindex = audioChannelsStr.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
if (aCindex > 0)
{
audioChannelsStr = audioChannelsStr.Remove(aCindex);
}
var audioChannelPositions = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions/String2"); var audioChannelPositions = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions/String2");
var audioChannelPositionsText = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions"); var audioChannelPositionsText = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions");
string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List"); 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) 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();
audioProfile = audioProfile.Remove(aPindex);
}
int.TryParse(audioChannelsStr, out audioChannels); int.TryParse(audioChannelsStr, out audioChannels);
var mediaInfoModel = new MediaInfoModel 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, VideoBitrate = videoBitRate,
VideoBitDepth = videoBitDepth, VideoBitDepth = videoBitDepth,
Height = height, Height = height,
Width = width, Width = width,
AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"), 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, AudioBitrate = audioBitRate,
RunTime = GetBestRuntime(audioRuntime, videoRuntime, generalRuntime), RunTime = GetBestRuntime(audioRuntime, videoRuntime, generalRuntime),
AudioStreamCount = streamCount, AudioStreamCount = streamCount,
AudioChannels = audioChannels, AudioChannels = audioChannels,
AudioChannelPositions = audioChannelPositions, AudioChannelPositions = audioChannelPositions,
AudioChannelPositionsText = audioChannelPositionsText, AudioChannelPositionsText = audioChannelPositionsText,
AudioProfile = audioProfile.Trim(),
VideoFps = videoFrameRate, VideoFps = videoFrameRate,
AudioLanguages = audioLanguages, AudioLanguages = audioLanguages,
Subtitles = subtitles, Subtitles = subtitles,

@ -807,7 +807,6 @@
<Compile Include="MediaFiles\MediaInfo\MediaInfoFormatter.cs" /> <Compile Include="MediaFiles\MediaInfo\MediaInfoFormatter.cs" />
<Compile Include="MediaFiles\MediaInfo\MediaInfoLib.cs" /> <Compile Include="MediaFiles\MediaInfo\MediaInfoLib.cs" />
<Compile Include="MediaFiles\MediaInfo\MediaInfoModel.cs" /> <Compile Include="MediaFiles\MediaInfo\MediaInfoModel.cs" />
<Compile Include="MediaFiles\MediaInfo\UnknownCodecException.cs" />
<Compile Include="MediaFiles\MediaInfo\UpdateMediaInfoService.cs" /> <Compile Include="MediaFiles\MediaInfo\UpdateMediaInfoService.cs" />
<Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" /> <Compile Include="MediaFiles\MediaInfo\VideoFileInfoReader.cs" />
<Compile Include="MediaFiles\RecycleBinProvider.cs" /> <Compile Include="MediaFiles\RecycleBinProvider.cs" />

Loading…
Cancel
Save