FFProbeProvider.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using MediaBrowser.Common.Configuration;
  2. using MediaBrowser.Controller.Chapters;
  3. using MediaBrowser.Controller.Configuration;
  4. using MediaBrowser.Controller.Entities;
  5. using MediaBrowser.Controller.Entities.Audio;
  6. using MediaBrowser.Controller.Entities.Movies;
  7. using MediaBrowser.Controller.Entities.TV;
  8. using MediaBrowser.Controller.Library;
  9. using MediaBrowser.Controller.LiveTv;
  10. using MediaBrowser.Controller.MediaEncoding;
  11. using MediaBrowser.Controller.Persistence;
  12. using MediaBrowser.Controller.Providers;
  13. using MediaBrowser.Controller.Subtitles;
  14. using MediaBrowser.Model.Entities;
  15. using MediaBrowser.Model.IO;
  16. using Microsoft.Extensions.Logging;
  17. using MediaBrowser.Model.MediaInfo;
  18. using MediaBrowser.Model.Serialization;
  19. using System;
  20. using System.Linq;
  21. using System.Threading;
  22. using System.Threading.Tasks;
  23. using MediaBrowser.Model.Globalization;
  24. using MediaBrowser.Controller.Channels;
  25. namespace MediaBrowser.Providers.MediaInfo
  26. {
  27. public class FFProbeProvider : ICustomMetadataProvider<Episode>,
  28. ICustomMetadataProvider<MusicVideo>,
  29. ICustomMetadataProvider<Movie>,
  30. ICustomMetadataProvider<Trailer>,
  31. ICustomMetadataProvider<Video>,
  32. ICustomMetadataProvider<Audio>,
  33. ICustomMetadataProvider<AudioBook>,
  34. IHasOrder,
  35. IForcedProvider,
  36. IPreRefreshProvider,
  37. IHasItemChangeMonitor
  38. {
  39. private readonly ILogger _logger;
  40. private readonly IIsoManager _isoManager;
  41. private readonly IMediaEncoder _mediaEncoder;
  42. private readonly IItemRepository _itemRepo;
  43. private readonly IBlurayExaminer _blurayExaminer;
  44. private readonly ILocalizationManager _localization;
  45. private readonly IApplicationPaths _appPaths;
  46. private readonly IJsonSerializer _json;
  47. private readonly IEncodingManager _encodingManager;
  48. private readonly IFileSystem _fileSystem;
  49. private readonly IServerConfigurationManager _config;
  50. private readonly ISubtitleManager _subtitleManager;
  51. private readonly IChapterManager _chapterManager;
  52. private readonly ILibraryManager _libraryManager;
  53. private readonly IChannelManager _channelManager;
  54. private readonly IMediaSourceManager _mediaSourceManager;
  55. public string Name
  56. {
  57. get { return "ffprobe"; }
  58. }
  59. public bool HasChanged(BaseItem item, IDirectoryService directoryService)
  60. {
  61. var video = item as Video;
  62. if (video == null || video.VideoType == VideoType.VideoFile || video.VideoType == VideoType.Iso)
  63. {
  64. var path = item.Path;
  65. if (!string.IsNullOrWhiteSpace(path) && item.IsFileProtocol)
  66. {
  67. var file = directoryService.GetFile(path);
  68. if (file != null && file.LastWriteTimeUtc != item.DateModified)
  69. {
  70. _logger.LogDebug("Refreshing {0} due to date modified timestamp change.", path);
  71. return true;
  72. }
  73. }
  74. }
  75. if (item.SupportsLocalMetadata)
  76. {
  77. if (video != null && !video.IsPlaceHolder)
  78. {
  79. if (!video.SubtitleFiles
  80. .SequenceEqual(_subtitleResolver.GetExternalSubtitleFiles(video, directoryService, false), StringComparer.Ordinal))
  81. {
  82. _logger.LogDebug("Refreshing {0} due to external subtitles change.", item.Path);
  83. return true;
  84. }
  85. }
  86. }
  87. return false;
  88. }
  89. public Task<ItemUpdateType> FetchAsync(Episode item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  90. {
  91. return FetchVideoInfo(item, options, cancellationToken);
  92. }
  93. public Task<ItemUpdateType> FetchAsync(MusicVideo item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  94. {
  95. return FetchVideoInfo(item, options, cancellationToken);
  96. }
  97. public Task<ItemUpdateType> FetchAsync(Movie item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  98. {
  99. return FetchVideoInfo(item, options, cancellationToken);
  100. }
  101. public Task<ItemUpdateType> FetchAsync(Trailer item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  102. {
  103. return FetchVideoInfo(item, options, cancellationToken);
  104. }
  105. public Task<ItemUpdateType> FetchAsync(Video item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  106. {
  107. return FetchVideoInfo(item, options, cancellationToken);
  108. }
  109. public Task<ItemUpdateType> FetchAsync(Audio item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  110. {
  111. return FetchAudioInfo(item, options, cancellationToken);
  112. }
  113. public Task<ItemUpdateType> FetchAsync(AudioBook item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  114. {
  115. return FetchAudioInfo(item, options, cancellationToken);
  116. }
  117. private SubtitleResolver _subtitleResolver;
  118. public FFProbeProvider(ILogger logger, IMediaSourceManager mediaSourceManager, IChannelManager channelManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, ILibraryManager libraryManager)
  119. {
  120. _logger = logger;
  121. _isoManager = isoManager;
  122. _mediaEncoder = mediaEncoder;
  123. _itemRepo = itemRepo;
  124. _blurayExaminer = blurayExaminer;
  125. _localization = localization;
  126. _appPaths = appPaths;
  127. _json = json;
  128. _encodingManager = encodingManager;
  129. _fileSystem = fileSystem;
  130. _config = config;
  131. _subtitleManager = subtitleManager;
  132. _chapterManager = chapterManager;
  133. _libraryManager = libraryManager;
  134. _channelManager = channelManager;
  135. _mediaSourceManager = mediaSourceManager;
  136. _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager, fileSystem);
  137. }
  138. private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
  139. public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  140. where T : Video
  141. {
  142. if (item.VideoType == VideoType.Iso)
  143. {
  144. return _cachedTask;
  145. }
  146. if (item.IsPlaceHolder)
  147. {
  148. return _cachedTask;
  149. }
  150. if (!item.IsCompleteMedia)
  151. {
  152. return _cachedTask;
  153. }
  154. if (item.IsVirtualItem)
  155. {
  156. return _cachedTask;
  157. }
  158. if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
  159. {
  160. return _cachedTask;
  161. }
  162. if (item.IsShortcut)
  163. {
  164. FetchShortcutInfo(item);
  165. }
  166. var prober = new FFProbeVideoInfo(_logger, _mediaSourceManager, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager, _chapterManager, _libraryManager);
  167. return prober.ProbeVideo(item, options, cancellationToken);
  168. }
  169. private string NormalizeStrmLine(string line)
  170. {
  171. return line.Replace("\t", string.Empty)
  172. .Replace("\r", string.Empty)
  173. .Replace("\n", string.Empty)
  174. .Trim();
  175. }
  176. private void FetchShortcutInfo(BaseItem item)
  177. {
  178. item.ShortcutPath = _fileSystem.ReadAllLines(item.Path)
  179. .Select(NormalizeStrmLine)
  180. .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith("#", StringComparison.OrdinalIgnoreCase));
  181. }
  182. public Task<ItemUpdateType> FetchAudioInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
  183. where T : Audio
  184. {
  185. if (item.IsVirtualItem)
  186. {
  187. return _cachedTask;
  188. }
  189. if (!options.EnableRemoteContentProbe && !item.IsFileProtocol)
  190. {
  191. return _cachedTask;
  192. }
  193. if (item.IsShortcut)
  194. {
  195. FetchShortcutInfo(item);
  196. }
  197. var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _appPaths, _json, _libraryManager);
  198. return prober.Probe(item, options, cancellationToken);
  199. }
  200. public int Order
  201. {
  202. get
  203. {
  204. // Run last
  205. return 100;
  206. }
  207. }
  208. }
  209. }