From d7f199bb1c43b56cafe8876f620d7757da17d8cd Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Mon, 17 Feb 2020 14:56:31 +0100 Subject: [PATCH 01/16] #2407: Prefer MP4-Metadata for episodes --- .../Library/LibraryManager.cs | 25 +++++++++++++++++++ .../Probing/ProbeResultNormalizer.cs | 3 +++ .../Configuration/LibraryOptions.cs | 1 + MediaBrowser.Model/MediaInfo/MediaInfo.cs | 1 + 4 files changed, 30 insertions(+) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d983c1dc6..c390d2b82 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -29,11 +29,13 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; @@ -2387,6 +2389,7 @@ namespace Emby.Server.Implementations.Library public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh) { + var libraryOptions = GetLibraryOptions(episode); var series = episode.Series; bool? isAbsoluteNaming = series == null ? false : string.Equals(series.DisplayOrder, "absolute", StringComparison.OrdinalIgnoreCase); if (!isAbsoluteNaming.Value) @@ -2408,6 +2411,28 @@ namespace Emby.Server.Implementations.Library episodeInfo = new Naming.TV.EpisodeInfo(); } + if (libraryOptions.EnableEmbeddedEpisodeInfos && episodeInfo.Container.ToLowerInvariant() == "mp4") { + // Read from metadata + IMediaEncoder mediaEncoder = _appHost.Resolve(); + var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest + { + MediaSource = episode.GetMediaSources(false).First(), + MediaType = DlnaProfileType.Video, + ExtractChapters = false + + }, CancellationToken.None); + task.Wait(); + if (task.Result.ParentIndexNumber > 0) { + episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; + } + if (task.Result.IndexNumber > 0) { + episodeInfo.EpisodeNumber = task.Result.IndexNumber; + } + if (!string.IsNullOrEmpty(task.Result.ShowName)) { + episodeInfo.SeriesName = task.Result.ShowName; + } + } + var changed = false; if (episodeInfo.IsByDate) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index bd89c6cae..f8047af42 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -112,6 +112,9 @@ namespace MediaBrowser.MediaEncoding.Probing info.Name = title; } + info.IndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "episode_sort"); + info.ParentIndexNumber = FFProbeHelpers.GetDictionaryNumericValue(tags, "season_number"); + info.ShowName = FFProbeHelpers.GetDictionaryValue(tags, "show_name"); info.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date"); // Several different forms of retaildate diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 3c99f9bb5..9d5d2b869 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.Model.Configuration public bool ImportMissingEpisodes { get; set; } public bool EnableAutomaticSeriesGrouping { get; set; } public bool EnableEmbeddedTitles { get; set; } + public bool EnableEmbeddedEpisodeInfos { get; set; } public int AutomaticRefreshIntervalDays { get; set; } diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs index 6ad766d39..237a2b36c 100644 --- a/MediaBrowser.Model/MediaInfo/MediaInfo.cs +++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs @@ -36,6 +36,7 @@ namespace MediaBrowser.Model.MediaInfo /// The studios. public string[] Studios { get; set; } public string[] Genres { get; set; } + public string ShowName { get; set; } public int? IndexNumber { get; set; } public int? ParentIndexNumber { get; set; } public int? ProductionYear { get; set; } From 5fed4d10abde3c2c7d0567c81dfd535e5d15a0f3 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 08:39:01 +0100 Subject: [PATCH 02/16] Only reading the result of GetMediaInfo if it completed successfully --- .../Library/LibraryManager.cs | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index c390d2b82..b32e98863 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2389,7 +2389,6 @@ namespace Emby.Server.Implementations.Library public bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh) { - var libraryOptions = GetLibraryOptions(episode); var series = episode.Series; bool? isAbsoluteNaming = series == null ? false : string.Equals(series.DisplayOrder, "absolute", StringComparison.OrdinalIgnoreCase); if (!isAbsoluteNaming.Value) @@ -2411,27 +2410,37 @@ namespace Emby.Server.Implementations.Library episodeInfo = new Naming.TV.EpisodeInfo(); } - if (libraryOptions.EnableEmbeddedEpisodeInfos && episodeInfo.Container.ToLowerInvariant() == "mp4") { - // Read from metadata - IMediaEncoder mediaEncoder = _appHost.Resolve(); - var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest - { - MediaSource = episode.GetMediaSources(false).First(), - MediaType = DlnaProfileType.Video, - ExtractChapters = false + try + { + var libraryOptions = GetLibraryOptions(episode); + if (libraryOptions.EnableEmbeddedEpisodeInfos && episodeInfo.Container.ToLowerInvariant() == "mp4") { + // Read from metadata + IMediaEncoder mediaEncoder = _appHost.Resolve(); + var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest + { + MediaSource = episode.GetMediaSources(false).First(), + MediaType = DlnaProfileType.Video, + ExtractChapters = false - }, CancellationToken.None); - task.Wait(); - if (task.Result.ParentIndexNumber > 0) { - episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; - } - if (task.Result.IndexNumber > 0) { - episodeInfo.EpisodeNumber = task.Result.IndexNumber; - } - if (!string.IsNullOrEmpty(task.Result.ShowName)) { - episodeInfo.SeriesName = task.Result.ShowName; + }, CancellationToken.None); + task.Wait(); + if (task.IsCompletedSuccessfully) { + if (task.Result.ParentIndexNumber > 0) { + episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; + } + if (task.Result.IndexNumber > 0) { + episodeInfo.EpisodeNumber = task.Result.IndexNumber; + } + if (!string.IsNullOrEmpty(task.Result.ShowName)) { + episodeInfo.SeriesName = task.Result.ShowName; + } + } } } + catch (Exception ex) + { + _logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {episodeInfo}", episodeInfo.Path); + } var changed = false; From 39b6d6586f3a788860bf361dec0087ea35191687 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 13:37:36 +0100 Subject: [PATCH 03/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index b32e98863..a2d7f93c2 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2413,7 +2413,8 @@ namespace Emby.Server.Implementations.Library try { var libraryOptions = GetLibraryOptions(episode); - if (libraryOptions.EnableEmbeddedEpisodeInfos && episodeInfo.Container.ToLowerInvariant() == "mp4") { + if (libraryOptions.EnableEmbeddedEpisodeInfos && string.Equals(episodeInfo.Container, "mp4", StringComparison.OrdinalIgnoreCase)) + { // Read from metadata IMediaEncoder mediaEncoder = _appHost.Resolve(); var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest From 4d0ee3f6cc4657ce0acb707873c64b86416c8a56 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 13:39:51 +0100 Subject: [PATCH 04/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index a2d7f93c2..12e3c661e 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2429,6 +2429,7 @@ namespace Emby.Server.Implementations.Library if (task.Result.ParentIndexNumber > 0) { episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; } + if (task.Result.IndexNumber > 0) { episodeInfo.EpisodeNumber = task.Result.IndexNumber; } From 70053266855048deca0d8cefd2eaae020f7bbf95 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 13:40:06 +0100 Subject: [PATCH 05/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 12e3c661e..37bb6741d 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2433,6 +2433,7 @@ namespace Emby.Server.Implementations.Library if (task.Result.IndexNumber > 0) { episodeInfo.EpisodeNumber = task.Result.IndexNumber; } + if (!string.IsNullOrEmpty(task.Result.ShowName)) { episodeInfo.SeriesName = task.Result.ShowName; } From b16ba7d9854dbda4e908908d4790d68a05cd9453 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 13:40:27 +0100 Subject: [PATCH 06/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 37bb6741d..1f526ff1c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2422,7 +2422,6 @@ namespace Emby.Server.Implementations.Library MediaSource = episode.GetMediaSources(false).First(), MediaType = DlnaProfileType.Video, ExtractChapters = false - }, CancellationToken.None); task.Wait(); if (task.IsCompletedSuccessfully) { From 0f2ee2686da4b38496dcc9c0578c82849174b22b Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 16:06:30 +0100 Subject: [PATCH 07/16] Constructor of the LibraryManager takes the mediaEncoder as parameter --- .../ApplicationHost.cs | 24 +++++++-------- .../Library/LibraryManager.cs | 29 +++++++++---------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0837db251..ceec972e5 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -755,7 +755,18 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(UserManager); - LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager); + MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( + LoggerFactory.CreateLogger(), + ServerConfigurationManager, + FileSystemManager, + ProcessFactory, + LocalizationManager, + () => SubtitleEncoder, + _configuration, + StartupOptions.FFmpegPath); + serviceCollection.AddSingleton(MediaEncoder); + + LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager, MediaEncoder); serviceCollection.AddSingleton(LibraryManager); var musicManager = new MusicManager(LibraryManager); @@ -833,17 +844,6 @@ namespace Emby.Server.Implementations ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); serviceCollection.AddSingleton(ChapterManager); - MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - LoggerFactory.CreateLogger(), - ServerConfigurationManager, - FileSystemManager, - ProcessFactory, - LocalizationManager, - () => SubtitleEncoder, - _configuration, - StartupOptions.FFmpegPath); - serviceCollection.AddSingleton(MediaEncoder); - EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); serviceCollection.AddSingleton(EncodingManager); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1f526ff1c..cd098739f 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -143,6 +143,7 @@ namespace Emby.Server.Implementations.Library public bool IsScanRunning { get; private set; } private IServerApplicationHost _appHost; + private IMediaEncoder _mediaEncoder; /// /// The _library items cache @@ -176,7 +177,8 @@ namespace Emby.Server.Implementations.Library Func libraryMonitorFactory, IFileSystem fileSystem, Func providerManagerFactory, - Func userviewManager) + Func userviewManager, + IMediaEncoder mediaEncoder) { _appHost = appHost; _logger = loggerFactory.CreateLogger(nameof(LibraryManager)); @@ -188,6 +190,7 @@ namespace Emby.Server.Implementations.Library _fileSystem = fileSystem; _providerManagerFactory = providerManagerFactory; _userviewManager = userviewManager; + _mediaEncoder = mediaEncoder; _libraryItemsCache = new ConcurrentDictionary(); @@ -2416,26 +2419,22 @@ namespace Emby.Server.Implementations.Library if (libraryOptions.EnableEmbeddedEpisodeInfos && string.Equals(episodeInfo.Container, "mp4", StringComparison.OrdinalIgnoreCase)) { // Read from metadata - IMediaEncoder mediaEncoder = _appHost.Resolve(); - var task = mediaEncoder.GetMediaInfo(new MediaInfoRequest + var mediaInfo = _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaSource = episode.GetMediaSources(false).First(), MediaType = DlnaProfileType.Video, ExtractChapters = false - }, CancellationToken.None); - task.Wait(); - if (task.IsCompletedSuccessfully) { - if (task.Result.ParentIndexNumber > 0) { - episodeInfo.SeasonNumber = task.Result.ParentIndexNumber; - } + }, CancellationToken.None).GetAwaiter().GetResult(); + if (mediaInfo.ParentIndexNumber > 0) { + episodeInfo.SeasonNumber = mediaInfo.ParentIndexNumber; + } - if (task.Result.IndexNumber > 0) { - episodeInfo.EpisodeNumber = task.Result.IndexNumber; - } + if (mediaInfo.IndexNumber > 0) { + episodeInfo.EpisodeNumber = mediaInfo.IndexNumber; + } - if (!string.IsNullOrEmpty(task.Result.ShowName)) { - episodeInfo.SeriesName = task.Result.ShowName; - } + if (!string.IsNullOrEmpty(mediaInfo.ShowName)) { + episodeInfo.SeriesName = mediaInfo.ShowName; } } } From d6971581d6777ca2ac1f22a5d1e61ada65c76baf Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 17:46:50 +0100 Subject: [PATCH 08/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index cd098739f..e851998c2 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2421,7 +2421,7 @@ namespace Emby.Server.Implementations.Library // Read from metadata var mediaInfo = _mediaEncoder.GetMediaInfo(new MediaInfoRequest { - MediaSource = episode.GetMediaSources(false).First(), + MediaSource = episode.GetMediaSources(false)[0], MediaType = DlnaProfileType.Video, ExtractChapters = false }, CancellationToken.None).GetAwaiter().GetResult(); From f4d0fa8dc8bd1d027664b290d9924a7c80c66bf0 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 18:58:28 +0100 Subject: [PATCH 09/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index e851998c2..9a1a38365 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2440,7 +2440,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {episodeInfo}", episodeInfo.Path); + _logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path); } var changed = false; From 3d9dc595549d7b6b53d9aee716a83eaf59db5186 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 19:03:42 +0100 Subject: [PATCH 10/16] Omitting the parameter ExtraChapters --- Emby.Server.Implementations/Library/LibraryManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 9a1a38365..1fdf8887c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2422,8 +2422,7 @@ namespace Emby.Server.Implementations.Library var mediaInfo = _mediaEncoder.GetMediaInfo(new MediaInfoRequest { MediaSource = episode.GetMediaSources(false)[0], - MediaType = DlnaProfileType.Video, - ExtractChapters = false + MediaType = DlnaProfileType.Video }, CancellationToken.None).GetAwaiter().GetResult(); if (mediaInfo.ParentIndexNumber > 0) { episodeInfo.SeasonNumber = mediaInfo.ParentIndexNumber; From a9e744bea0af2578b79acbd96cd5f5f90fbfd9c4 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 19:41:10 +0100 Subject: [PATCH 11/16] Curly braces on new lines --- Emby.Server.Implementations/Library/LibraryManager.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1fdf8887c..841f6321a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2424,15 +2424,18 @@ namespace Emby.Server.Implementations.Library MediaSource = episode.GetMediaSources(false)[0], MediaType = DlnaProfileType.Video }, CancellationToken.None).GetAwaiter().GetResult(); - if (mediaInfo.ParentIndexNumber > 0) { + if (mediaInfo.ParentIndexNumber > 0) + { episodeInfo.SeasonNumber = mediaInfo.ParentIndexNumber; } - if (mediaInfo.IndexNumber > 0) { + if (mediaInfo.IndexNumber > 0) + { episodeInfo.EpisodeNumber = mediaInfo.IndexNumber; } - if (!string.IsNullOrEmpty(mediaInfo.ShowName)) { + if (!string.IsNullOrEmpty(mediaInfo.ShowName)) + { episodeInfo.SeriesName = mediaInfo.ShowName; } } From 3bd7633cbf451f4ab540229c72bf13b9433b7a45 Mon Sep 17 00:00:00 2001 From: Ulrich Wagner Date: Wed, 19 Feb 2020 19:47:03 +0100 Subject: [PATCH 12/16] Update Emby.Server.Implementations/Library/LibraryManager.cs Co-Authored-By: Bond-009 --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 841f6321a..55566ed51 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -143,7 +143,7 @@ namespace Emby.Server.Implementations.Library public bool IsScanRunning { get; private set; } private IServerApplicationHost _appHost; - private IMediaEncoder _mediaEncoder; + private readonly IMediaEncoder _mediaEncoder; /// /// The _library items cache From 107e43aaac07ff26f09f076d865abfcfe74a1a81 Mon Sep 17 00:00:00 2001 From: SleepyJesse Date: Wed, 19 Feb 2020 13:30:16 +0000 Subject: [PATCH 13/16] Translated using Weblate (Chinese (Simplified)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/ --- Emby.Server.Implementations/Localization/Core/zh-CN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index e0daac8a5..dd6168614 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -89,8 +89,8 @@ "UserOnlineFromDevice": "{0} 在线,来自 {1}", "UserPasswordChangedWithName": "已为用户 {0} 更改密码", "UserPolicyUpdatedWithName": "用户协议已经被更新为 {0}", - "UserStartedPlayingItemWithValues": "{0} 已开始播放 {1}", - "UserStoppedPlayingItemWithValues": "{0} 已停止播放 {1}", + "UserStartedPlayingItemWithValues": "{0} 已在 {2} 上开始播放 {1}", + "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}", "ValueHasBeenAddedToLibrary": "{0} 已添加至您的媒体库中", "ValueSpecialEpisodeName": "特典 - {0}", "VersionNumber": "版本 {0}" From b2bf0f1796a60462a532a9b7793b19571309a943 Mon Sep 17 00:00:00 2001 From: SleepyJesse Date: Wed, 19 Feb 2020 13:00:40 +0000 Subject: [PATCH 14/16] Translated using Weblate (Chinese (Hong Kong)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant_HK/ --- .../Localization/Core/zh-HK.json | 174 +++++++++--------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index 33fcb2d37..f3d9e5fce 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -1,97 +1,97 @@ { - "Albums": "Albums", - "AppDeviceValues": "App: {0}, Device: {1}", - "Application": "Application", + "Albums": "專輯", + "AppDeviceValues": "軟體: {0}, 設備: {1}", + "Application": "應用程式", "Artists": "藝人", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "Books": "Books", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", - "Channels": "Channels", - "ChapterNameValue": "Chapter {0}", - "Collections": "Collections", - "DeviceOfflineWithName": "{0} has disconnected", - "DeviceOnlineWithName": "{0} is connected", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "Favorites": "Favorites", - "Folders": "Folders", - "Genres": "Genres", - "HeaderAlbumArtists": "Album Artists", - "HeaderCameraUploads": "Camera Uploads", - "HeaderContinueWatching": "Continue Watching", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteArtists": "Favorite Artists", - "HeaderFavoriteEpisodes": "Favorite Episodes", - "HeaderFavoriteShows": "Favorite Shows", - "HeaderFavoriteSongs": "Favorite Songs", - "HeaderLiveTV": "Live TV", - "HeaderNextUp": "Next Up", - "HeaderRecordingGroups": "Recording Groups", - "HomeVideos": "Home videos", - "Inherit": "Inherit", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "LabelRunningTimeValue": "Running time: {0}", - "Latest": "Latest", - "MessageApplicationUpdated": "Jellyfin Server has been updated", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageServerConfigurationUpdated": "Server configuration has been updated", + "AuthenticationSucceededWithUserName": "{0} 授權成功", + "Books": "圖書", + "CameraImageUploadedFrom": "{0} 成功上傳一張新相片", + "Channels": "頻道", + "ChapterNameValue": "章節 {0}", + "Collections": "合輯", + "DeviceOfflineWithName": "{0} 已經斷開連結", + "DeviceOnlineWithName": "{0} 已經連接", + "FailedLoginAttemptWithUserName": "來自 {0} 的失敗登入嘗試", + "Favorites": "我的最愛", + "Folders": "檔案夾", + "Genres": "風格", + "HeaderAlbumArtists": "專輯藝術家", + "HeaderCameraUploads": "相機上載", + "HeaderContinueWatching": "繼續觀看", + "HeaderFavoriteAlbums": "最愛專輯", + "HeaderFavoriteArtists": "最愛藝術家", + "HeaderFavoriteEpisodes": "最愛的劇集", + "HeaderFavoriteShows": "最愛的節目", + "HeaderFavoriteSongs": "最愛的歌曲", + "HeaderLiveTV": "電視直播", + "HeaderNextUp": "接下來", + "HeaderRecordingGroups": "錄製組", + "HomeVideos": "家庭影片", + "Inherit": "繼承", + "ItemAddedWithName": "{0} 已添加至媒體庫", + "ItemRemovedWithName": "{0} 已從媒體庫移除", + "LabelIpAddressValue": "IP 地址: {0}", + "LabelRunningTimeValue": "運行時間: {0}", + "Latest": "最新", + "MessageApplicationUpdated": "Jellyfin Server 已更新", + "MessageApplicationUpdatedTo": "Jellyfin 伺服器已更新至 {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "伺服器設定 {0} 部分已更新", + "MessageServerConfigurationUpdated": "伺服器設定已經更新", "MixedContent": "Mixed content", - "Movies": "Movies", - "Music": "Music", - "MusicVideos": "Music videos", - "NameInstallFailed": "{0} installation failed", - "NameSeasonNumber": "Season {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionServerRestartRequired": "Server restart required", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "Photos": "Photos", - "Playlists": "Playlists", + "Movies": "電影", + "Music": "音樂", + "MusicVideos": "音樂MV", + "NameInstallFailed": "{0} 安裝失敗", + "NameSeasonNumber": "第 {0} 季", + "NameSeasonUnknown": "未知季數", + "NewVersionIsAvailable": "新版本的 Jellyfin 伺服器可供下載。", + "NotificationOptionApplicationUpdateAvailable": "有可用的應用程式更新", + "NotificationOptionApplicationUpdateInstalled": "應用程式已更新", + "NotificationOptionAudioPlayback": "開始播放音頻", + "NotificationOptionAudioPlaybackStopped": "已停止播放音頻", + "NotificationOptionCameraImageUploaded": "相機相片已上傳", + "NotificationOptionInstallationFailed": "安裝失敗", + "NotificationOptionNewLibraryContent": "已添加新内容", + "NotificationOptionPluginError": "擴充元件錯誤", + "NotificationOptionPluginInstalled": "擴充元件已安裝", + "NotificationOptionPluginUninstalled": "擴充元件已移除", + "NotificationOptionPluginUpdateInstalled": "擴充元件更新已安裝", + "NotificationOptionServerRestartRequired": "伺服器需要重啓", + "NotificationOptionTaskFailed": "計劃任務失敗", + "NotificationOptionUserLockedOut": "用家已鎖定", + "NotificationOptionVideoPlayback": "開始播放視頻", + "NotificationOptionVideoPlaybackStopped": "已停止播放視頻", + "Photos": "相片", + "Playlists": "播放清單", "Plugin": "Plugin", - "PluginInstalledWithName": "{0} was installed", - "PluginUninstalledWithName": "{0} was uninstalled", - "PluginUpdatedWithName": "{0} was updated", + "PluginInstalledWithName": "已安裝 {0}", + "PluginUninstalledWithName": "已移除 {0}", + "PluginUpdatedWithName": "已更新 {0}", "ProviderValue": "Provider: {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", - "Shows": "Shows", - "Songs": "Songs", - "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.", + "ScheduledTaskFailedWithName": "{0} 任務失敗", + "ScheduledTaskStartedWithName": "{0} 任務開始", + "ServerNameNeedsToBeRestarted": "{0} 需要重啓", + "Shows": "節目", + "Songs": "歌曲", + "StartupEmbyServerIsLoading": "Jellyfin 伺服器載入中,請稍後再試。", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "Sync": "Sync", + "SubtitleDownloadFailureFromForItem": "無法從 {0} 下載 {1} 的字幕", + "SubtitlesDownloadedForItem": "已為 {0} 下載了字幕", + "Sync": "同步", "System": "System", - "TvShows": "TV Shows", + "TvShows": "電視節目", "User": "User", - "UserCreatedWithName": "User {0} has been created", - "UserDeletedWithName": "User {0} has been deleted", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserOnlineFromDevice": "{0} is online from {1}", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}", - "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", - "ValueSpecialEpisodeName": "Special - {0}", + "UserCreatedWithName": "用家 {0} 已創建", + "UserDeletedWithName": "用家 {0} 已移除", + "UserDownloadingItemWithValues": "{0} 正在下載 {1}", + "UserLockedOutWithName": "用家 {0} 已被鎖定", + "UserOfflineFromDevice": "{0} 已從 {1} 斷開", + "UserOnlineFromDevice": "{0} 已連綫,來自 {1}", + "UserPasswordChangedWithName": "用家 {0} 的密碼已變更", + "UserPolicyUpdatedWithName": "用戶協議已被更新為 {0}", + "UserStartedPlayingItemWithValues": "{0} 正在 {2} 上播放 {1}", + "UserStoppedPlayingItemWithValues": "{0} 已在 {2} 上停止播放 {1}", + "ValueHasBeenAddedToLibrary": "{0} 已添加到你的媒體庫", + "ValueSpecialEpisodeName": "特典 - {0}", "VersionNumber": "版本{0}" } From d240321e8738f30a3638fe976a44b119b54f0ad1 Mon Sep 17 00:00:00 2001 From: SleepyJesse Date: Wed, 19 Feb 2020 13:17:25 +0000 Subject: [PATCH 15/16] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/ --- Emby.Server.Implementations/Localization/Core/zh-TW.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json index 3b0dc4ab2..acd211f22 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-TW.json +++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json @@ -50,7 +50,7 @@ "NotificationOptionCameraImageUploaded": "相機相片已上傳", "NotificationOptionInstallationFailed": "安裝失敗", "NotificationOptionNewLibraryContent": "已新增新內容", - "NotificationOptionPluginError": "擴充元件安裝失敗", + "NotificationOptionPluginError": "擴充元件錯誤", "NotificationOptionPluginInstalled": "擴充元件已安裝", "NotificationOptionPluginUninstalled": "擴充元件已移除", "NotificationOptionPluginUpdateInstalled": "已更新擴充元件", From 28cc210a5e8f6fc234178f2f667d8ce1f8596dec Mon Sep 17 00:00:00 2001 From: Daniel De Jesus Date: Wed, 19 Feb 2020 02:47:49 +0000 Subject: [PATCH 16/16] Translated using Weblate (Spanish (Dominican Republic)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_DO/ --- .../Localization/Core/es_DO.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/es_DO.json b/Emby.Server.Implementations/Localization/Core/es_DO.json index 0967ef424..1ac8d3ae4 100644 --- a/Emby.Server.Implementations/Localization/Core/es_DO.json +++ b/Emby.Server.Implementations/Localization/Core/es_DO.json @@ -1 +1,14 @@ -{} +{ + "Channels": "Canales", + "Books": "Libros", + "Albums": "Álbumes", + "Collections": "Colecciones", + "Artists": "Artistas", + "DeviceOnlineWithName": "{0} está conectado", + "DeviceOfflineWithName": "{0} ha desconectado", + "ChapterNameValue": "Capítulo {0}", + "CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}", + "AuthenticationSucceededWithUserName": "{0} autenticado con éxito", + "Application": "Aplicación", + "AppDeviceValues": "App: {0}, Dispositivo: {1}" +}