1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-25 22:37:27 -04:00

New: Use MediaInfo on File Parsing

This commit is contained in:
Qstick
2019-07-15 22:27:35 -04:00
parent ada9b944dc
commit bfc467dd96
51 changed files with 1092 additions and 689 deletions
@@ -0,0 +1,24 @@
using System;
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation
{
public class AugmentingFailedException : NzbDroneException
{
public AugmentingFailedException(string message, params object[] args) : base(message, args)
{
}
public AugmentingFailedException(string message) : base(message)
{
}
public AugmentingFailedException(string message, Exception innerException, params object[] args) : base(message, innerException, args)
{
}
public AugmentingFailedException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation
{
public interface IAggregationService
{
LocalMovie Augment(LocalMovie localMovie, bool otherFiles);
}
public class AggregationService : IAggregationService
{
private readonly IEnumerable<IAggregateLocalMovie> _augmenters;
private readonly IDiskProvider _diskProvider;
private readonly IVideoFileInfoReader _videoFileInfoReader;
private readonly IConfigService _configService;
private readonly Logger _logger;
public AggregationService(IEnumerable<IAggregateLocalMovie> augmenters,
IDiskProvider diskProvider,
IVideoFileInfoReader videoFileInfoReader,
IConfigService configService,
Logger logger)
{
_augmenters = augmenters;
_diskProvider = diskProvider;
_videoFileInfoReader = videoFileInfoReader;
_configService = configService;
_logger = logger;
}
public LocalMovie Augment(LocalMovie localMovie, bool otherFiles)
{
var isMediaFile = MediaFileExtensions.Extensions.Contains(Path.GetExtension(localMovie.Path));
if (localMovie.DownloadClientMovieInfo == null &&
localMovie.FolderMovieInfo == null &&
localMovie.FileMovieInfo == null)
{
if (isMediaFile)
{
throw new AugmentingFailedException("Unable to parse movie info from path: {0}", localMovie.Path);
}
}
localMovie.Size = _diskProvider.GetFileSize(localMovie.Path);
if (isMediaFile && (!localMovie.ExistingFile || _configService.EnableMediaInfo))
{
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(localMovie.Path);
}
foreach (var augmenter in _augmenters)
{
try
{
augmenter.Aggregate(localMovie, otherFiles);
}
catch (Exception ex)
{
_logger.Warn(ex, ex.Message);
}
}
return localMovie;
}
}
}
@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
{
public class AggregateLanguage : IAggregateLocalMovie
{
private readonly Logger _logger;
public AggregateLanguage(Logger logger)
{
_logger = logger;
}
public LocalMovie Aggregate(LocalMovie localMovie, bool otherFiles)
{
// Get languages in preferred order, download client item, folder and finally file.
// Non-English languages will be preferred later, in the event there is a conflict
// between parsed languages the more preferred item will be used.
var languages = new List<Language>();
languages.AddRange(GetLanguage(localMovie.DownloadClientMovieInfo));
languages.AddRange(GetLanguage(localMovie.FolderMovieInfo));
languages.AddRange(GetLanguage(localMovie.FileMovieInfo));
var language = new List<Language> { languages.FirstOrDefault(l => l != Language.English) ?? Language.English };
_logger.Debug("Using language: {0}", language.First());
localMovie.Languages = language;
return localMovie;
}
private List<Language> GetLanguage(ParsedMovieInfo parsedMovieInfo)
{
if (parsedMovieInfo == null)
{
// English is the default language when otherwise unknown
return new List<Language> { Language.English };
}
return parsedMovieInfo.Languages;
}
}
}
@@ -0,0 +1,81 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
{
public class AggregateQuality : IAggregateLocalMovie
{
private readonly IEnumerable<IAugmentQuality> _augmentQualities;
private readonly Logger _logger;
public AggregateQuality(IEnumerable<IAugmentQuality> augmentQualities,
Logger logger)
{
_augmentQualities = augmentQualities;
_logger = logger;
}
public LocalMovie Aggregate(LocalMovie localMovie, bool otherFiles)
{
var augmentedQualities = _augmentQualities.Select(a => a.AugmentQuality(localMovie))
.Where(a => a != null)
.OrderBy(a => a.SourceConfidence);
var source = Source.UNKNOWN;
var sourceConfidence = Confidence.Default;
var resolution = Resolution.Unknown;
var resolutionConfidence = Confidence.Default;
var revison = new Revision();
foreach (var augmentedQuality in augmentedQualities)
{
if (augmentedQuality.Source > source ||
augmentedQuality.SourceConfidence > sourceConfidence && augmentedQuality.Source != Source.UNKNOWN)
{
source = augmentedQuality.Source;
sourceConfidence = augmentedQuality.SourceConfidence;
}
if (augmentedQuality.Resolution > resolution ||
augmentedQuality.ResolutionConfidence > resolutionConfidence && augmentedQuality.Resolution > 0)
{
resolution = augmentedQuality.Resolution;
resolutionConfidence = augmentedQuality.ResolutionConfidence;
}
if (augmentedQuality.Revision != null && augmentedQuality.Revision > revison)
{
revison = augmentedQuality.Revision;
}
}
_logger.Trace("Finding quality. Source: {0}. Resolution: {1}", source, resolution);
var quality = new QualityModel(QualityFinder.FindBySourceAndResolution(source, resolution), revison);
if (resolutionConfidence == Confidence.MediaInfo)
{
quality.QualityDetectionSource = QualityDetectionSource.MediaInfo;
}
else if (sourceConfidence == Confidence.Fallback || resolutionConfidence == Confidence.Fallback)
{
quality.QualityDetectionSource = QualityDetectionSource.Extension;
}
else
{
quality.QualityDetectionSource = QualityDetectionSource.Name;
}
_logger.Debug("Using quality: {0}", quality);
localMovie.Quality = quality;
return localMovie;
}
}
}
@@ -0,0 +1,27 @@
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
{
public class AggregateReleaseGroup : IAggregateLocalMovie
{
public LocalMovie Aggregate(LocalMovie localMovie, bool otherFiles)
{
var releaseGroup = localMovie.DownloadClientMovieInfo?.ReleaseGroup;
if (releaseGroup.IsNullOrWhiteSpace())
{
releaseGroup = localMovie.FolderMovieInfo?.ReleaseGroup;
}
if (releaseGroup.IsNullOrWhiteSpace())
{
releaseGroup = localMovie.FileMovieInfo?.ReleaseGroup;
}
localMovie.ReleaseGroup = releaseGroup;
return localMovie;
}
}
}
@@ -0,0 +1,23 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public class AugmentQualityFromDownloadClientItem : IAugmentQuality
{
public AugmentQualityResult AugmentQuality(LocalMovie localMovie)
{
var quality = localMovie.DownloadClientMovieInfo?.Quality;
if (quality == null)
{
return null;
}
return new AugmentQualityResult(quality.Quality.Source,
Confidence.Tag,
quality.Quality.Resolution,
Confidence.Tag,
quality.Revision);
}
}
}
@@ -0,0 +1,28 @@
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public class AugmentQualityFromFileName : IAugmentQuality
{
public AugmentQualityResult AugmentQuality(LocalMovie localMovie)
{
var quality = localMovie.FileMovieInfo?.Quality;
if (quality == null)
{
return null;
}
var confidence = quality.QualityDetectionSource == QualityDetectionSource.Extension
? Confidence.Fallback
: Confidence.Tag;
return new AugmentQualityResult(quality.Quality.Source,
confidence,
quality.Quality.Resolution,
confidence,
quality.Revision);
}
}
}
@@ -0,0 +1,23 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public class AugmentQualityFromFolder : IAugmentQuality
{
public AugmentQualityResult AugmentQuality(LocalMovie localMovie)
{
var quality = localMovie.FolderMovieInfo?.Quality;
if (quality == null)
{
return null;
}
return new AugmentQualityResult(quality.Quality.Source,
Confidence.Tag,
quality.Quality.Resolution,
Confidence.Tag,
quality.Revision);
}
}
}
@@ -0,0 +1,40 @@
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public class AugmentQualityFromMediaInfo : IAugmentQuality
{
public AugmentQualityResult AugmentQuality(LocalMovie localMovie)
{
if (localMovie.MediaInfo == null)
{
return null;
}
var width = localMovie.MediaInfo.Width;
if (width >= 3200)
{
return AugmentQualityResult.ResolutionOnly(Resolution.R2160P, Confidence.MediaInfo);
}
if (width >= 1800)
{
return AugmentQualityResult.ResolutionOnly(Resolution.R1080P, Confidence.MediaInfo);
}
if (width >= 1200)
{
return AugmentQualityResult.ResolutionOnly(Resolution.R720P, Confidence.MediaInfo);
}
if (width > 0)
{
return AugmentQualityResult.ResolutionOnly(Resolution.R480P, Confidence.MediaInfo);
}
return null;
}
}
}
@@ -0,0 +1,37 @@
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public class AugmentQualityResult
{
public Source Source { get; set; }
public Confidence SourceConfidence { get; set; }
public Resolution Resolution { get; set; }
public Confidence ResolutionConfidence { get; set; }
public Revision Revision { get; set; }
public AugmentQualityResult(Source source,
Confidence sourceConfidence,
Resolution resolution,
Confidence resolutionConfidence,
Revision revision)
{
Source = source;
SourceConfidence = sourceConfidence;
Resolution = resolution;
ResolutionConfidence = resolutionConfidence;
Revision = revision;
}
public static AugmentQualityResult SourceOnly(Source source, Confidence sourceConfidence)
{
return new AugmentQualityResult(source, sourceConfidence, 0, Confidence.Default, null);
}
public static AugmentQualityResult ResolutionOnly(Resolution resolution, Confidence resolutionConfidence)
{
return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, resolution, resolutionConfidence, null);
}
}
}
@@ -0,0 +1,10 @@
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public enum Confidence
{
Fallback,
Default,
Tag,
MediaInfo
}
}
@@ -0,0 +1,9 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality
{
public interface IAugmentQuality
{
AugmentQualityResult AugmentQuality(LocalMovie localMovie);
}
}
@@ -0,0 +1,9 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
{
public interface IAggregateLocalMovie
{
LocalMovie Aggregate(LocalMovie localMovie, bool otherFiles);
}
}