2021-10-26 13:49:01 +00:00
|
|
|
#nullable disable
|
|
|
|
|
2020-06-19 18:24:13 +00:00
|
|
|
#pragma warning disable CS1591
|
|
|
|
|
2019-01-13 20:03:10 +00:00
|
|
|
using System;
|
2019-01-26 21:31:59 +00:00
|
|
|
using System.IO;
|
2019-01-13 19:26:31 +00:00
|
|
|
using System.Linq;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
2014-06-09 19:16:14 +00:00
|
|
|
using MediaBrowser.Controller.Chapters;
|
2014-05-07 02:28:19 +00:00
|
|
|
using MediaBrowser.Controller.Configuration;
|
2014-02-09 21:11:11 +00:00
|
|
|
using MediaBrowser.Controller.Entities;
|
2014-02-06 04:39:16 +00:00
|
|
|
using MediaBrowser.Controller.Entities.Audio;
|
2014-02-04 20:19:29 +00:00
|
|
|
using MediaBrowser.Controller.Entities.Movies;
|
|
|
|
using MediaBrowser.Controller.Entities.TV;
|
|
|
|
using MediaBrowser.Controller.Library;
|
2014-02-20 16:37:41 +00:00
|
|
|
using MediaBrowser.Controller.MediaEncoding;
|
2014-02-04 20:19:29 +00:00
|
|
|
using MediaBrowser.Controller.Persistence;
|
|
|
|
using MediaBrowser.Controller.Providers;
|
2014-05-07 02:28:19 +00:00
|
|
|
using MediaBrowser.Controller.Subtitles;
|
2014-02-04 20:19:29 +00:00
|
|
|
using MediaBrowser.Model.Entities;
|
2019-01-13 19:26:31 +00:00
|
|
|
using MediaBrowser.Model.Globalization;
|
2014-02-04 20:19:29 +00:00
|
|
|
using MediaBrowser.Model.MediaInfo;
|
2019-01-13 19:26:31 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
2014-02-04 20:19:29 +00:00
|
|
|
|
|
|
|
namespace MediaBrowser.Providers.MediaInfo
|
|
|
|
{
|
|
|
|
public class FFProbeProvider : ICustomMetadataProvider<Episode>,
|
2014-02-06 04:39:16 +00:00
|
|
|
ICustomMetadataProvider<MusicVideo>,
|
|
|
|
ICustomMetadataProvider<Movie>,
|
2016-05-07 21:01:21 +00:00
|
|
|
ICustomMetadataProvider<Trailer>,
|
2014-02-06 04:39:16 +00:00
|
|
|
ICustomMetadataProvider<Video>,
|
|
|
|
ICustomMetadataProvider<Audio>,
|
2017-01-07 20:52:56 +00:00
|
|
|
ICustomMetadataProvider<AudioBook>,
|
2014-02-19 05:21:03 +00:00
|
|
|
IHasOrder,
|
2015-03-05 06:34:36 +00:00
|
|
|
IForcedProvider,
|
2018-09-12 17:26:21 +00:00
|
|
|
IPreRefreshProvider,
|
|
|
|
IHasItemChangeMonitor
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
2020-06-06 00:15:56 +00:00
|
|
|
private readonly ILogger<FFProbeProvider> _logger;
|
2014-02-04 20:19:29 +00:00
|
|
|
private readonly IMediaEncoder _mediaEncoder;
|
|
|
|
private readonly IItemRepository _itemRepo;
|
|
|
|
private readonly IBlurayExaminer _blurayExaminer;
|
|
|
|
private readonly ILocalizationManager _localization;
|
2014-02-20 16:37:41 +00:00
|
|
|
private readonly IEncodingManager _encodingManager;
|
2014-05-07 02:28:19 +00:00
|
|
|
private readonly IServerConfigurationManager _config;
|
|
|
|
private readonly ISubtitleManager _subtitleManager;
|
2014-06-09 19:16:14 +00:00
|
|
|
private readonly IChapterManager _chapterManager;
|
2015-06-29 01:10:45 +00:00
|
|
|
private readonly ILibraryManager _libraryManager;
|
2018-09-12 17:26:21 +00:00
|
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
2020-09-07 11:20:39 +00:00
|
|
|
private readonly SubtitleResolver _subtitleResolver;
|
|
|
|
|
|
|
|
private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
|
|
|
|
|
|
|
|
public FFProbeProvider(
|
|
|
|
ILogger<FFProbeProvider> logger,
|
|
|
|
IMediaSourceManager mediaSourceManager,
|
|
|
|
IMediaEncoder mediaEncoder,
|
|
|
|
IItemRepository itemRepo,
|
|
|
|
IBlurayExaminer blurayExaminer,
|
|
|
|
ILocalizationManager localization,
|
|
|
|
IEncodingManager encodingManager,
|
|
|
|
IServerConfigurationManager config,
|
|
|
|
ISubtitleManager subtitleManager,
|
|
|
|
IChapterManager chapterManager,
|
|
|
|
ILibraryManager libraryManager)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_mediaEncoder = mediaEncoder;
|
|
|
|
_itemRepo = itemRepo;
|
|
|
|
_blurayExaminer = blurayExaminer;
|
|
|
|
_localization = localization;
|
|
|
|
_encodingManager = encodingManager;
|
|
|
|
_config = config;
|
|
|
|
_subtitleManager = subtitleManager;
|
|
|
|
_chapterManager = chapterManager;
|
|
|
|
_libraryManager = libraryManager;
|
|
|
|
_mediaSourceManager = mediaSourceManager;
|
|
|
|
|
|
|
|
_subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager);
|
|
|
|
}
|
2014-02-06 04:39:16 +00:00
|
|
|
|
2019-01-13 20:31:14 +00:00
|
|
|
public string Name => "ffprobe";
|
2014-02-04 20:19:29 +00:00
|
|
|
|
2020-09-07 11:20:39 +00:00
|
|
|
// Run last
|
|
|
|
public int Order => 100;
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
public bool HasChanged(BaseItem item, IDirectoryService directoryService)
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
2018-09-12 17:26:21 +00:00
|
|
|
var video = item as Video;
|
|
|
|
if (video == null || video.VideoType == VideoType.VideoFile || video.VideoType == VideoType.Iso)
|
|
|
|
{
|
|
|
|
var path = item.Path;
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(path) && item.IsFileProtocol)
|
|
|
|
{
|
|
|
|
var file = directoryService.GetFile(path);
|
|
|
|
if (file != null && file.LastWriteTimeUtc != item.DateModified)
|
|
|
|
{
|
2018-12-13 13:18:25 +00:00
|
|
|
_logger.LogDebug("Refreshing {0} due to date modified timestamp change.", path);
|
2018-09-12 17:26:21 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-27 09:20:05 +00:00
|
|
|
if (item.SupportsLocalMetadata && video != null && !video.IsPlaceHolder
|
|
|
|
&& !video.SubtitleFiles.SequenceEqual(
|
|
|
|
_subtitleResolver.GetExternalSubtitleFiles(video, directoryService, false), StringComparer.Ordinal))
|
2018-09-12 17:26:21 +00:00
|
|
|
{
|
2019-01-27 09:20:05 +00:00
|
|
|
_logger.LogDebug("Refreshing {0} due to external subtitles change.", item.Path);
|
|
|
|
return true;
|
2018-09-12 17:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(Episode item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
2014-06-09 19:16:14 +00:00
|
|
|
return FetchVideoInfo(item, options, cancellationToken);
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(MusicVideo item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
2014-06-09 19:16:14 +00:00
|
|
|
return FetchVideoInfo(item, options, cancellationToken);
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(Movie item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
2014-06-09 19:16:14 +00:00
|
|
|
return FetchVideoInfo(item, options, cancellationToken);
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2016-05-07 21:01:21 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(Trailer item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
return FetchVideoInfo(item, options, cancellationToken);
|
|
|
|
}
|
|
|
|
|
2014-06-09 19:16:14 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(Video item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-06 04:39:16 +00:00
|
|
|
{
|
2014-06-09 19:16:14 +00:00
|
|
|
return FetchVideoInfo(item, options, cancellationToken);
|
2014-02-06 04:39:16 +00:00
|
|
|
}
|
|
|
|
|
2014-06-09 19:16:14 +00:00
|
|
|
public Task<ItemUpdateType> FetchAsync(Audio item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-06 04:39:16 +00:00
|
|
|
{
|
2018-09-12 17:26:21 +00:00
|
|
|
return FetchAudioInfo(item, options, cancellationToken);
|
2017-01-07 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Task<ItemUpdateType> FetchAsync(AudioBook item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-06 04:39:16 +00:00
|
|
|
{
|
2018-09-12 17:26:21 +00:00
|
|
|
return FetchAudioInfo(item, options, cancellationToken);
|
2014-02-06 04:39:16 +00:00
|
|
|
}
|
|
|
|
|
2014-06-09 19:16:14 +00:00
|
|
|
public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-04 20:19:29 +00:00
|
|
|
where T : Video
|
|
|
|
{
|
2018-09-12 17:26:21 +00:00
|
|
|
if (item.IsPlaceHolder)
|
2014-02-04 20:19:29 +00:00
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
if (!item.IsCompleteMedia)
|
2014-03-03 05:11:03 +00:00
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
if (item.IsVirtualItem)
|
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
|
2017-09-18 16:52:22 +00:00
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
2014-10-15 00:05:09 +00:00
|
|
|
if (item.IsShortcut)
|
|
|
|
{
|
|
|
|
FetchShortcutInfo(item);
|
|
|
|
}
|
2015-06-29 01:10:45 +00:00
|
|
|
|
2020-02-23 09:53:51 +00:00
|
|
|
var prober = new FFProbeVideoInfo(
|
|
|
|
_logger,
|
|
|
|
_mediaSourceManager,
|
|
|
|
_mediaEncoder,
|
|
|
|
_itemRepo,
|
|
|
|
_blurayExaminer,
|
|
|
|
_localization,
|
|
|
|
_encodingManager,
|
|
|
|
_config,
|
|
|
|
_subtitleManager,
|
|
|
|
_chapterManager,
|
|
|
|
_libraryManager);
|
2014-02-04 20:19:29 +00:00
|
|
|
|
2014-06-09 19:16:14 +00:00
|
|
|
return prober.ProbeVideo(item, options, cancellationToken);
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
private string NormalizeStrmLine(string line)
|
2014-10-15 00:05:09 +00:00
|
|
|
{
|
2020-08-07 17:26:28 +00:00
|
|
|
return line.Replace("\t", string.Empty, StringComparison.Ordinal)
|
|
|
|
.Replace("\r", string.Empty, StringComparison.Ordinal)
|
|
|
|
.Replace("\n", string.Empty, StringComparison.Ordinal)
|
2017-11-01 19:50:16 +00:00
|
|
|
.Trim();
|
2014-10-15 00:05:09 +00:00
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
private void FetchShortcutInfo(BaseItem item)
|
|
|
|
{
|
2019-01-26 21:31:59 +00:00
|
|
|
item.ShortcutPath = File.ReadAllLines(item.Path)
|
2018-09-12 17:26:21 +00:00
|
|
|
.Select(NormalizeStrmLine)
|
2020-12-02 14:38:52 +00:00
|
|
|
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith('#'));
|
2018-09-12 17:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Task<ItemUpdateType> FetchAudioInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
2014-02-06 04:39:16 +00:00
|
|
|
where T : Audio
|
|
|
|
{
|
2018-09-12 17:26:21 +00:00
|
|
|
if (item.IsVirtualItem)
|
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
|
2014-02-06 04:39:16 +00:00
|
|
|
{
|
|
|
|
return _cachedTask;
|
|
|
|
}
|
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
if (item.IsShortcut)
|
|
|
|
{
|
|
|
|
FetchShortcutInfo(item);
|
|
|
|
}
|
|
|
|
|
2020-08-07 17:26:28 +00:00
|
|
|
var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _libraryManager);
|
2014-02-06 04:39:16 +00:00
|
|
|
|
2018-09-12 17:26:21 +00:00
|
|
|
return prober.Probe(item, options, cancellationToken);
|
2014-02-06 04:39:16 +00:00
|
|
|
}
|
2014-02-04 20:19:29 +00:00
|
|
|
}
|
|
|
|
}
|