From 5ca29f0fbace9f17f00e6683c2c08f1179865300 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 11:21:09 -0400 Subject: [PATCH 1/7] normalize subtitle names --- .../Probing/ProbeResultNormalizer.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 700af682bf..5805127e66 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -393,6 +393,20 @@ namespace MediaBrowser.MediaEncoding.Probing }; } + private string NormalizeSubtitleCodec(string codec) + { + if ((codec ?? string.Empty).IndexOf("PGS", StringComparison.OrdinalIgnoreCase) != -1) + { + codec = "PGSSUB"; + } + else if ((codec ?? string.Empty).IndexOf("DVD", StringComparison.OrdinalIgnoreCase) != -1) + { + codec = "DVDSUB"; + } + + return codec; + } + /// /// Converts ffprobe stream info to our MediaStream class /// @@ -474,6 +488,7 @@ namespace MediaBrowser.MediaEncoding.Probing else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase)) { stream.Type = MediaStreamType.Subtitle; + stream.Codec = NormalizeSubtitleCodec(stream.Codec); } else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase)) { From dd8601f515f2b306d9f656ba6de62652cccd685f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 11:21:44 -0400 Subject: [PATCH 2/7] update guide image quality --- .../LiveTv/Listings/SchedulesDirect.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index c302633889..0bc84a2e53 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings var data = images[imageIndex].data ?? new List(); data = data.OrderByDescending(GetSizeOrder).ToList(); - programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 1280); + programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 800); //programEntry.thumbImage = GetProgramImage(ApiUrl, data, "Iconic", false); //programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? @@ -536,7 +536,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings } return false; - }) ?? matches.FirstOrDefault(); + }); + + if (match == null) + { + // Get the second lowest quality image, when possible + if (matches.Count > 1) + { + match = matches[matches.Count - 2]; + } + else + { + match = matches.FirstOrDefault(); + } + } if (match == null) { From 55bbc051c2e5da93baef2efeb105684e4ff40c10 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 11:22:00 -0400 Subject: [PATCH 3/7] exclude backdrops from photos --- .../Library/Resolvers/PhotoResolver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 3f9475480a..d4ebb8457b 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -89,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers return false; } - if (IgnoreFiles.Any(i => filename.IndexOf("-" + i, StringComparison.OrdinalIgnoreCase) != -1)) + if (IgnoreFiles.Any(i => filename.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1)) { return false; } From 115b4b2c1b703f39efcaff81ab2ed8a2f947129f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 11:22:53 -0400 Subject: [PATCH 4/7] fix really high audio encoding bitrate --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index eee6bfb658..9a3659f07d 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1453,7 +1453,8 @@ namespace MediaBrowser.Api.Playback // Make sure we don't request a bitrate higher than the source var currentBitrate = audioStream == null ? request.AudioBitRate.Value : audioStream.BitRate ?? request.AudioBitRate.Value; - return request.AudioBitRate.Value; + // Don't encode any higher than this + return Math.Min(384000, request.AudioBitRate.Value); //return Math.Min(currentBitrate, request.AudioBitRate.Value); } From bcfef5dd8377879963abf28ff80ffcbc8eaf52bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 15:38:53 -0400 Subject: [PATCH 5/7] update recording nfo saving --- .../LiveTv/EmbyTV/EmbyTV.cs | 97 +++++++++++++++++-- .../LiveTv/EmbyTV/RecordingHelper.cs | 5 + 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index b508110cf9..2dd23857a7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -27,6 +27,7 @@ using System.Threading; using System.Threading.Tasks; using System.Xml; using CommonIO; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Configuration; @@ -1026,6 +1027,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV result.Item3.Release(); isResourceOpen = false; + + SaveNfo(timer, recordPath, seriesPath); }; var pathWithDuration = result.Item2.ApplyDuration(mediaStreamInfo.Path, duration); @@ -1071,7 +1074,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV timer.Status = RecordingStatus.Completed; _timerProvider.Delete(timer); - OnSuccessfulRecording(timer, recordPath, seriesPath); + OnSuccessfulRecording(timer, recordPath); } else if (DateTime.UtcNow < timer.EndDate) { @@ -1139,7 +1142,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return new DirectRecorder(_logger, _httpClient, _fileSystem); } - private async void OnSuccessfulRecording(TimerInfo timer, string path, string seriesPath) + private async void OnSuccessfulRecording(TimerInfo timer, string path) { if (timer.IsProgramSeries && GetConfiguration().EnableAutoOrganize) { @@ -1163,15 +1166,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _logger.ErrorException("Error processing new recording", ex); } } - - SaveNfo(timer, path, seriesPath); } private void SaveNfo(TimerInfo timer, string recordingPath, string seriesPath) { - if (timer.IsProgramSeries) + try + { + if (timer.IsProgramSeries) + { + SaveSeriesNfo(timer, recordingPath, seriesPath); + } + else if (!timer.IsMovie || timer.IsSports) + { + SaveVideoNfo(timer, recordingPath); + } + } + catch (Exception ex) { - SaveSeriesNfo(timer, recordingPath, seriesPath); + _logger.ErrorException("Error saving nfo", ex); } } @@ -1209,6 +1221,79 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } } + public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; + private void SaveVideoNfo(TimerInfo timer, string recordingPath) + { + var nfoPath = Path.ChangeExtension(recordingPath, ".nfo"); + + if (File.Exists(nfoPath)) + { + return; + } + + using (var stream = _fileSystem.GetFileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.Read)) + { + var settings = new XmlWriterSettings + { + Indent = true, + Encoding = Encoding.UTF8, + CloseOutput = false + }; + + using (XmlWriter writer = XmlWriter.Create(stream, settings)) + { + writer.WriteStartDocument(true); + writer.WriteStartElement("movie"); + + if (!string.IsNullOrWhiteSpace(timer.Name)) + { + writer.WriteElementString("title", timer.Name); + } + + writer.WriteElementString("dateadded", DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat)); + + if (timer.ProductionYear.HasValue) + { + writer.WriteElementString("year", timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)); + } + if (!string.IsNullOrEmpty(timer.OfficialRating)) + { + writer.WriteElementString("mpaa", timer.OfficialRating); + } + + var overview = (timer.Overview ?? string.Empty) + .StripHtml() + .Replace(""", "'"); + + writer.WriteElementString("plot", overview); + writer.WriteElementString("lockdata", true.ToString().ToLower()); + + if (timer.CommunityRating.HasValue) + { + writer.WriteElementString("rating", timer.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)); + } + + foreach (var genre in timer.Genres) + { + writer.WriteElementString("genre", genre); + } + + if (!string.IsNullOrWhiteSpace(timer.ShortOverview)) + { + writer.WriteElementString("outline", timer.ShortOverview); + } + + if (!string.IsNullOrWhiteSpace(timer.HomePageUrl)) + { + writer.WriteElementString("website", timer.HomePageUrl); + } + + writer.WriteEndElement(); + writer.WriteEndDocument(); + } + } + } + private ProgramInfo GetProgramInfoFromCache(string channelId, string programId) { var epgData = GetEpgDataForChannel(channelId); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 236439bc58..67356da2fe 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -46,6 +46,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV timerInfo.EpisodeTitle = programInfo.EpisodeTitle; timerInfo.OriginalAirDate = programInfo.OriginalAirDate; timerInfo.IsProgramSeries = programInfo.IsSeries; + + timerInfo.HomePageUrl = programInfo.HomePageUrl; + timerInfo.CommunityRating = programInfo.CommunityRating; + timerInfo.ShortOverview = programInfo.ShortOverview; + timerInfo.OfficialRating = programInfo.OfficialRating; } public static string GetRecordingName(TimerInfo info) From 97ea2ff43a4428e754e9ca67d977900eb0de88c8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 15:42:53 -0400 Subject: [PATCH 6/7] update live tv hls --- .../Playback/Hls/VideoHlsService.cs | 2 ++ MediaBrowser.Controller/LiveTv/TimerInfo.cs | 17 ++++++++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 33 ++++++++----------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 8a14948d21..c7258d72f7 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -113,6 +113,8 @@ namespace MediaBrowser.Api.Playback.Hls args += GetGraphicalSubtitleParam(state, codec); } + args += " -flags -global_header"; + return args; } diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index 94bc24b9ed..ea21ba46e5 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -1,10 +1,16 @@ using MediaBrowser.Model.LiveTv; using System; +using System.Collections.Generic; namespace MediaBrowser.Controller.LiveTv { public class TimerInfo { + public TimerInfo() + { + Genres = new List(); + } + /// /// Id of the recording. /// @@ -15,7 +21,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// The series timer identifier. public string SeriesTimerId { get; set; } - + /// /// ChannelId of the recording. /// @@ -26,7 +32,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// The program identifier. public string ProgramId { get; set; } - + /// /// Name of the recording. /// @@ -76,7 +82,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// true if this instance is post padding required; otherwise, false. public bool IsPostPaddingRequired { get; set; } - + /// /// Gets or sets the priority. /// @@ -98,5 +104,10 @@ namespace MediaBrowser.Controller.LiveTv public string EpisodeTitle { get; set; } public DateTime? OriginalAirDate { get; set; } public bool IsProgramSeries { get; set; } + public string HomePageUrl { get; set; } + public float? CommunityRating { get; set; } + public string ShortOverview { get; set; } + public string OfficialRating { get; set; } + public List Genres { get; set; } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 98bef334b7..30d1498bf6 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -609,26 +609,13 @@ namespace MediaBrowser.Model.Dlna defaultBitrate = StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3") ? 192000 : 128000; } - if (targetAudioChannels.HasValue) + if (StringHelper.EqualsIgnoreCase(subProtocol, "hls")) { - if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 1200000) - { - if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) - { - if (StringHelper.EqualsIgnoreCase(subProtocol, "hls")) - { - defaultBitrate = Math.Max(384000, defaultBitrate); - } - else - { - defaultBitrate = Math.Max(448000, defaultBitrate); - } - } - else - { - defaultBitrate = Math.Max(320000, defaultBitrate); - } - } + defaultBitrate = Math.Min(384000, defaultBitrate); + } + else + { + defaultBitrate = Math.Min(448000, defaultBitrate); } int encoderAudioBitrateLimit = int.MaxValue; @@ -647,6 +634,14 @@ namespace MediaBrowser.Model.Dlna } } + if (maxTotalBitrate.HasValue) + { + if (maxTotalBitrate.Value < 640000) + { + defaultBitrate = Math.Min(128000, defaultBitrate); + } + } + return Math.Min(defaultBitrate, encoderAudioBitrateLimit); } From 61ee765de96eeffa28b0042d633166ba5d214850 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 20 Sep 2016 15:43:27 -0400 Subject: [PATCH 7/7] update library monitor --- .../IO/FileRefresher.cs | 4 +++- .../IO/LibraryMonitor.cs | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs index 8e28aa2a0e..3df7a03d4c 100644 --- a/MediaBrowser.Server.Implementations/IO/FileRefresher.cs +++ b/MediaBrowser.Server.Implementations/IO/FileRefresher.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations.ScheduledTasks; +using MoreLinq; namespace MediaBrowser.Server.Implementations.IO { @@ -136,9 +137,10 @@ namespace MediaBrowser.Server.Implementations.IO private async Task ProcessPathChanges(List paths) { var itemsToRefresh = paths + .Distinct(StringComparer.OrdinalIgnoreCase) .Select(GetAffectedBaseItem) .Where(item => item != null) - .Distinct() + .DistinctBy(i => i.Id) .ToList(); foreach (var p in paths) diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 8bb40a00ea..6e0f9a3c48 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -404,7 +404,20 @@ namespace MediaBrowser.Server.Implementations.IO { Logger.Debug("Changed detected of type " + e.ChangeType + " to " + e.FullPath); - ReportFileSystemChanged(e.FullPath); + var path = e.FullPath; + + // For deletes, use the parent path + if (e.ChangeType == WatcherChangeTypes.Deleted) + { + var parentPath = Path.GetDirectoryName(path); + + if (!string.IsNullOrWhiteSpace(parentPath)) + { + path = parentPath; + } + } + + ReportFileSystemChanged(path); } catch (Exception ex) {