From a6d80f557df8587c178c1a65722c1aa968a051e7 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Fri, 31 Jul 2020 21:40:09 +0200 Subject: [PATCH 01/15] Add a much shorter timeout to the CollectArtifacts job --- .ci/azure-pipelines-package.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index 1677f71c75..10ce8508df 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -116,6 +116,7 @@ jobs: $(JellyfinVersion)-$(BuildConfiguration) - job: CollectArtifacts + timeoutInMinutes: 10 displayName: 'Collect Artifacts' dependsOn: - BuildPackage From 7c60510bc954c10792a10098f70c6db621a66188 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sat, 1 Aug 2020 00:20:47 +0200 Subject: [PATCH 02/15] Experiment for the SSH task. --- .ci/azure-pipelines-package.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index 10ce8508df..f64dc2ba98 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -132,11 +132,9 @@ jobs: condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master') inputs: sshEndpoint: repository - runOptions: 'inline' - inline: | - sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) unstable - rm $0 - exit + runOptions: 'commands' + commands: bash /srv/repository/collect-server.azure.sh + args: /srv/repository/incoming/azure $(Build.BuildNumber) unstable - task: SSH@0 displayName: 'Update Stable Repository' @@ -154,7 +152,7 @@ jobs: dependsOn: - BuildPackage condition: and(succeeded('BuildPackage'), startsWith(variables['Build.SourceBranch'], 'refs/tags')) - + pool: vmImage: 'ubuntu-latest' From 3ee28c016aa5e159c9b077a7d16a1e0fae7c2019 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sat, 1 Aug 2020 00:32:25 +0200 Subject: [PATCH 03/15] Switch to sudo -n --- .ci/azure-pipelines-package.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index f64dc2ba98..ab752d0d93 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -133,7 +133,7 @@ jobs: inputs: sshEndpoint: repository runOptions: 'commands' - commands: bash /srv/repository/collect-server.azure.sh + commands: sudo -n /srv/repository/collect-server.azure.sh args: /srv/repository/incoming/azure $(Build.BuildNumber) unstable - task: SSH@0 @@ -141,11 +141,9 @@ jobs: condition: startsWith(variables['Build.SourceBranch'], 'refs/tags') inputs: sshEndpoint: repository - runOptions: 'inline' - inline: | - sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) - rm $0 - exit + runOptions: 'commands' + commands: sudo -n /srv/repository/collect-server.azure.sh + args: /srv/repository/incoming/azure $(Build.BuildNumber) - job: PublishNuget displayName: 'Publish NuGet packages' From d191fec3ac46942b567f4fc2ce9a34ff64302320 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 1 Aug 2020 15:03:33 +0200 Subject: [PATCH 04/15] Minor fixes for websocket code --- .../HttpServer/HttpListenerHost.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 0d4a789b56..dafdd5b7bf 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -567,7 +567,7 @@ namespace Emby.Server.Implementations.HttpServer WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false); - var connection = new WebSocketConnection( + using var connection = new WebSocketConnection( _loggerFactory.CreateLogger(), webSocket, context.Connection.RemoteIpAddress, diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 316cd84cfa..d738047e07 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer /// /// Class WebSocketConnection. /// - public class WebSocketConnection : IWebSocketConnection + public class WebSocketConnection : IWebSocketConnection, IDisposable { /// /// The logger. @@ -119,7 +119,7 @@ namespace Emby.Server.Implementations.HttpServer Memory memory = writer.GetMemory(512); try { - receiveresult = await _socket.ReceiveAsync(memory, cancellationToken); + receiveresult = await _socket.ReceiveAsync(memory, cancellationToken).ConfigureAwait(false); } catch (WebSocketException ex) { @@ -137,7 +137,7 @@ namespace Emby.Server.Implementations.HttpServer writer.Advance(bytesRead); // Make the data available to the PipeReader - FlushResult flushResult = await writer.FlushAsync(); + FlushResult flushResult = await writer.FlushAsync().ConfigureAwait(false); if (flushResult.IsCompleted) { // The PipeReader stopped reading @@ -223,7 +223,7 @@ namespace Emby.Server.Implementations.HttpServer if (info.MessageType.Equals("KeepAlive", StringComparison.Ordinal)) { - await SendKeepAliveResponse(); + await SendKeepAliveResponse().ConfigureAwait(false); } else { From 6f306f0a17571eba7466a5f8bd591498d252e1be Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 1 Aug 2020 16:20:08 -0400 Subject: [PATCH 05/15] Minor fixes to ActivityManager --- Jellyfin.Server.Implementations/Activity/ActivityManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 65ceee32bf..2deefbe819 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -40,8 +40,9 @@ namespace Jellyfin.Server.Implementations.Activity /// public async Task CreateAsync(ActivityLog entry) { - using var dbContext = _provider.CreateContext(); - await dbContext.ActivityLogs.AddAsync(entry); + await using var dbContext = _provider.CreateContext(); + + dbContext.ActivityLogs.Add(entry); await dbContext.SaveChangesAsync().ConfigureAwait(false); EntryCreated?.Invoke(this, new GenericEventArgs(ConvertToOldModel(entry))); From e7af1185eb0ea404989c6adc7b595e6f7669e77e Mon Sep 17 00:00:00 2001 From: michael9dk <61046533+michael9dk@users.noreply.github.com> Date: Mon, 3 Aug 2020 13:21:44 +0200 Subject: [PATCH 06/15] Update README.md Fix broken link to Azure DevOps pipeline. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f1b5e5140..a41bfbca84 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Note that it is also possible to [host the web client separately](#hosting-the-w There are three options to get the files for the web client. -1. Download one of the finished builds from the [Azure DevOps pipeline](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=11). You can download the build for a specific release by looking at the [branches tab](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=11&_a=summary&repositoryFilter=6&view=branches) of the pipelines page. +1. Download one of the finished builds from the [Azure DevOps pipeline](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=27). You can download the build for a specific release by looking at the [branches tab](https://dev.azure.com/jellyfin-project/jellyfin/_build?definitionId=27&_a=summary&repositoryFilter=6&view=branches) of the pipelines page. 2. Build them from source following the instructions on the [jellyfin-web repository](https://github.com/jellyfin/jellyfin-web) 3. Get the pre-built files from an existing installation of the server. For example, with a Windows server installation the client files are located at `C:\Program Files\Jellyfin\Server\jellyfin-web` From b4c6ae9aba4153c042e6e98719b18c32abd608f7 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 4 Aug 2020 01:02:02 +0900 Subject: [PATCH 07/15] disable compatibility checks for now --- .ci/azure-pipelines-abi.yml | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/.ci/azure-pipelines-abi.yml b/.ci/azure-pipelines-abi.yml index 635aa759ca..b558d2a6f0 100644 --- a/.ci/azure-pipelines-abi.yml +++ b/.ci/azure-pipelines-abi.yml @@ -12,10 +12,12 @@ parameters: jobs: - job: CompatibilityCheck displayName: Compatibility Check + dependsOn: Build + condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber']) + pool: vmImage: "${{ parameters.LinuxImage }}" - # only execute for pull requests - condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber']) + strategy: matrix: ${{ each Package in parameters.Packages }}: @@ -23,7 +25,7 @@ jobs: NugetPackageName: ${{ Package.value.NugetPackageName }} AssemblyFileName: ${{ Package.value.AssemblyFileName }} maxParallel: 2 - dependsOn: Build + steps: - checkout: none @@ -34,32 +36,33 @@ jobs: version: ${{ parameters.DotNetSdkVersion }} - task: DotNetCoreCLI@2 - displayName: 'Install ABI CompatibilityChecker tool' + displayName: 'Install ABI CompatibilityChecker Tool' inputs: command: custom custom: tool arguments: 'update compatibilitychecker -g' - task: DownloadPipelineArtifact@2 - displayName: "Download New Assembly Build Artifact" + displayName: 'Download New Assembly Build Artifact' inputs: - source: "current" + source: 'current' artifact: "$(NugetPackageName)" path: "$(System.ArtifactsDirectory)/new-artifacts" runVersion: "latest" - task: CopyFiles@2 - displayName: "Copy New Assembly Build Artifact" + displayName: 'Copy New Assembly Build Artifact' inputs: sourceFolder: $(System.ArtifactsDirectory)/new-artifacts - contents: "**/*.dll" + contents: '**/*.dll' targetFolder: $(System.ArtifactsDirectory)/new-release cleanTargetFolder: true overWrite: true flattenFolders: true - task: DownloadPipelineArtifact@2 - displayName: "Download Reference Assembly Build Artifact" + displayName: 'Download Reference Assembly Build Artifact' + enabled: false inputs: source: "specific" artifact: "$(NugetPackageName)" @@ -70,18 +73,19 @@ jobs: runBranch: "refs/heads/$(System.PullRequest.TargetBranch)" - task: CopyFiles@2 - displayName: "Copy Reference Assembly Build Artifact" + displayName: 'Copy Reference Assembly Build Artifact' + enabled: false inputs: sourceFolder: $(System.ArtifactsDirectory)/current-artifacts - contents: "**/*.dll" + contents: '**/*.dll' targetFolder: $(System.ArtifactsDirectory)/current-release cleanTargetFolder: true overWrite: true flattenFolders: true - # The `--warnings-only` switch will swallow the return code and not emit any errors. - task: DotNetCoreCLI@2 displayName: 'Execute ABI Compatibility Check Tool' + enabled: false inputs: command: custom custom: compat From 2b355c36ff8328f962f607df4aa305e53f2e003e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 3 Aug 2020 20:32:45 +0200 Subject: [PATCH 08/15] Minor improvements OFC I reduced some allocations --- .../Data/SqliteItemRepository.cs | 58 ++++++++++--------- .../Playback/Hls/BaseHlsService.cs | 5 +- .../Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Api/Subtitles/SubtitleService.cs | 3 +- MediaBrowser.Model/Entities/MediaStream.cs | 4 +- MediaBrowser.Providers/Manager/ImageSaver.cs | 4 +- RSSDP/RSSDP.csproj | 2 - 7 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 1c6d3cb94e..a246416283 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -978,7 +978,10 @@ namespace Emby.Server.Implementations.Data continue; } - str.Append($"{i.Key}={i.Value}|"); + str.Append(i.Key) + .Append('=') + .Append(i.Value) + .Append('|'); } if (str.Length == 0) @@ -1032,8 +1035,8 @@ namespace Emby.Server.Implementations.Data continue; } - str.Append(ToValueString(i)) - .Append('|'); + AppendItemImageInfo(str, i); + str.Append('|'); } str.Length -= 1; // Remove last | @@ -1067,26 +1070,26 @@ namespace Emby.Server.Implementations.Data item.ImageInfos = list.ToArray(); } - public string ToValueString(ItemImageInfo image) + public void AppendItemImageInfo(StringBuilder bldr, ItemImageInfo image) { - const string Delimeter = "*"; + const char Delimeter = '*'; var path = image.Path ?? string.Empty; var hash = image.BlurHash ?? string.Empty; - return GetPathToSave(path) + - Delimeter + - image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + - Delimeter + - image.Type + - Delimeter + - image.Width.ToString(CultureInfo.InvariantCulture) + - Delimeter + - image.Height.ToString(CultureInfo.InvariantCulture) + - Delimeter + - // Replace delimiters with other characters. - // This can be removed when we migrate to a proper DB. - hash.Replace('*', '/').Replace('|', '\\'); + bldr.Append(GetPathToSave(path)) + .Append(Delimeter) + .Append(image.DateModified.Ticks) + .Append(Delimeter) + .Append(image.Type) + .Append(Delimeter) + .Append(image.Width) + .Append(Delimeter) + .Append(image.Height) + .Append(Delimeter) + // Replace delimiters with other characters. + // This can be removed when we migrate to a proper DB. + .Append(hash.Replace('*', '/').Replace('|', '\\')); } public ItemImageInfo ItemImageInfoFromValueString(string value) @@ -5659,10 +5662,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type const int Limit = 100; var startIndex = 0; + const string StartInsertText = "insert into ItemValues (ItemId, Type, Value, CleanValue) values "; + var insertText = new StringBuilder(StartInsertText); while (startIndex < values.Count) { - var insertText = new StringBuilder("insert into ItemValues (ItemId, Type, Value, CleanValue) values "); - var endIndex = Math.Min(values.Count, startIndex + Limit); for (var i = startIndex; i < endIndex; i++) @@ -5704,6 +5707,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } startIndex += Limit; + insertText.Length = StartInsertText.Length; } } @@ -5741,10 +5745,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var startIndex = 0; var listIndex = 0; + const string StartInsertText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values "; + var insertText = new StringBuilder(StartInsertText); while (startIndex < people.Count) { - var insertText = new StringBuilder("insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values "); - var endIndex = Math.Min(people.Count, startIndex + Limit); for (var i = startIndex; i < endIndex; i++) { @@ -5778,6 +5782,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } startIndex += Limit; + insertText.Length = StartInsertText.Length; } } @@ -5893,10 +5898,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type const int Limit = 10; var startIndex = 0; + var insertText = new StringBuilder(_mediaStreamSaveColumnsInsertQuery); while (startIndex < streams.Count) { - var insertText = new StringBuilder(_mediaStreamSaveColumnsInsertQuery); - var endIndex = Math.Min(streams.Count, startIndex + Limit); for (var i = startIndex; i < endIndex; i++) @@ -5979,6 +5983,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } startIndex += Limit; + insertText.Length = _mediaStreamSaveColumnsInsertQuery.Length; } } @@ -6230,10 +6235,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { const int InsertAtOnce = 10; + var insertText = new StringBuilder(_mediaAttachmentInsertPrefix); for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce) { - var insertText = new StringBuilder(_mediaAttachmentInsertPrefix); - var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce); for (var i = startIndex; i < endIndex; i++) @@ -6279,6 +6283,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.Reset(); statement.MoveNext(); } + + insertText.Length = _mediaAttachmentInsertPrefix.Length; } } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index c80e8e64f7..3cdd80fad3 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -195,8 +195,9 @@ namespace MediaBrowser.Api.Playback.Hls // Main stream builder.Append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=") - .AppendLine(paddedBitrate.ToString(CultureInfo.InvariantCulture)); - var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8"); + .AppendLine(paddedBitrate.ToString(CultureInfo.InvariantCulture)) + .Append("hls/"); + var playlistUrl = Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8"); builder.AppendLine(playlistUrl); return builder.ToString(); diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 661c1ba5f2..4d1473bdeb 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -1037,7 +1037,7 @@ namespace MediaBrowser.Api.Playback.Hls } audioTranscodeParams.Add("-vn"); - return string.Join(" ", audioTranscodeParams.ToArray()); + return string.Join(" ", audioTranscodeParams); } if (EncodingHelper.IsCopyCodec(audioCodec)) diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index 6a6196d8a3..8dd9ca4a8b 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -160,8 +160,6 @@ namespace MediaBrowser.Api.Subtitles var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false); - var builder = new StringBuilder(); - var runtime = mediaSource.RunTimeTicks ?? -1; if (runtime <= 0) @@ -175,6 +173,7 @@ namespace MediaBrowser.Api.Subtitles throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)"); } + var builder = new StringBuilder(); builder.AppendLine("#EXTM3U") .Append("#EXT-X-TARGETDURATION:") .AppendLine(request.SegmentLength.ToString(CultureInfo.InvariantCulture)) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 1b37cfc939..f9ec0d2388 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -233,7 +233,7 @@ namespace MediaBrowser.Model.Entities if (!string.IsNullOrEmpty(Title)) { - var result = new StringBuilder(Title); + var result = new StringBuilder(Title); foreach (var tag in attributes) { // Keep Tags that are not already in Title. @@ -246,7 +246,7 @@ namespace MediaBrowser.Model.Entities return result.ToString(); } - return string.Join(" - ", attributes.ToArray()); + return string.Join(" - ", attributes); } default: diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index f655b8edd2..32b543feff 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Manager // If there are more than one output paths, the stream will need to be seekable var memoryStream = new MemoryStream(); - using (source) + await using (source.ConfigureAwait(false)) { await source.CopyToAsync(memoryStream).ConfigureAwait(false); } @@ -138,7 +138,7 @@ namespace MediaBrowser.Providers.Manager var savedPaths = new List(); - await using (source) + await using (source.ConfigureAwait(false)) { var currentPathIndex = 0; diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj index 5536931717..664663bd76 100644 --- a/RSSDP/RSSDP.csproj +++ b/RSSDP/RSSDP.csproj @@ -6,9 +6,7 @@ - - From 4980db159489ce009845dd109cb4b91dc809c72c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 3 Aug 2020 20:42:01 +0200 Subject: [PATCH 09/15] Fix spelling --- .../Data/SqliteItemRepository.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index a246416283..d11e5e62e3 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1072,21 +1072,21 @@ namespace Emby.Server.Implementations.Data public void AppendItemImageInfo(StringBuilder bldr, ItemImageInfo image) { - const char Delimeter = '*'; + const char Delimiter = '*'; var path = image.Path ?? string.Empty; var hash = image.BlurHash ?? string.Empty; bldr.Append(GetPathToSave(path)) - .Append(Delimeter) + .Append(Delimiter) .Append(image.DateModified.Ticks) - .Append(Delimeter) + .Append(Delimiter) .Append(image.Type) - .Append(Delimeter) + .Append(Delimiter) .Append(image.Width) - .Append(Delimeter) + .Append(Delimiter) .Append(image.Height) - .Append(Delimeter) + .Append(Delimiter) // Replace delimiters with other characters. // This can be removed when we migrate to a proper DB. .Append(hash.Replace('*', '/').Replace('|', '\\')); From 52d409101bb0faf3f8cc5964bf9a4d4aa4c1cd7b Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 4 Aug 2020 09:05:51 +0200 Subject: [PATCH 10/15] Change OnRefreshStart and OnRefreshComplete logging levels to debug --- MediaBrowser.Providers/Manager/ProviderManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 9170c70025..2d6935a0b4 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -966,7 +966,7 @@ namespace MediaBrowser.Providers.Manager /// public void OnRefreshStart(BaseItem item) { - _logger.LogInformation("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); + _logger.LogDebug("OnRefreshStart {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); _activeRefreshes[item.Id] = 0; RefreshStarted?.Invoke(this, new GenericEventArgs(item)); } @@ -974,7 +974,7 @@ namespace MediaBrowser.Providers.Manager /// public void OnRefreshComplete(BaseItem item) { - _logger.LogInformation("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); + _logger.LogDebug("OnRefreshComplete {0}", item.Id.ToString("N", CultureInfo.InvariantCulture)); _activeRefreshes.Remove(item.Id, out _); From 18efa25a6fdcfab2326cb35bb5781138a83e9d56 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 4 Aug 2020 16:20:52 +0200 Subject: [PATCH 11/15] Enable TreatWarningsAsErrors for MediaBrowser.MediaEncoding --- .../Attachments/AttachmentExtractor.cs | 2 ++ MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs | 4 ++++ .../Configuration/EncodingConfigurationFactory.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs | 2 ++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 ++ .../MediaBrowser.MediaEncoding.csproj | 1 + MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs | 3 +++ MediaBrowser.MediaEncoding/Probing/MediaChapter.cs | 2 ++ MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 4 ++++ MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 ++ MediaBrowser.MediaEncoding/Subtitles/AssParser.cs | 3 +++ MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs | 2 ++ MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 6 +++--- 14 files changed, 34 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index f029993706..a8ebe6bc54 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Concurrent; using System.Diagnostics; diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs index ccfae2fa54..9108d96497 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoExaminer.cs @@ -15,6 +15,10 @@ namespace MediaBrowser.MediaEncoding.BdInfo { private readonly IFileSystem _fileSystem; + /// + /// Initializes a new instance of the class. + /// + /// The filesystem. public BdInfoExaminer(IFileSystem fileSystem) { _fileSystem = fileSystem; diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index 75534b5bdd..fea7ee6fed 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 5c43fdcfa9..1ac56f845f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index d4aede572b..7c2d9f1fd5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.MediaInfo; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62fdbc618a..0f0ae877fb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index aeb4dbe733..dab5f866cf 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -9,6 +9,7 @@ netstandard2.1 false true + true diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index 3aa296f7f5..b2d4db894d 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; namespace MediaBrowser.MediaEncoding.Probing { + /// + /// Class containing helper methods for working with FFprobe output. + /// public static class FFProbeHelpers { /// diff --git a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs index 6a45ccf495..de062d06b0 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaChapter.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.Collections.Generic; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index a2ea0766a8..93ef6f93e1 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -269,6 +269,10 @@ namespace MediaBrowser.MediaEncoding.Probing [JsonPropertyName("loro_surmixlev")] public string LoroSurmixlev { get; set; } + /// + /// Gets or sets the field_order. + /// + /// The loro_surmixlev. [JsonPropertyName("field_order")] public string FieldOrder { get; set; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 0b447e3e64..8aaaf4a09b 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index 43a45291cc..e6e21756ad 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.Globalization; @@ -13,6 +15,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + /// public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken) { var trackInfo = new SubtitleTrackInfo(); diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs index f0d1071967..c0023ebf24 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System.IO; using System.Threading; using MediaBrowser.Model.MediaInfo; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 2afa89cdab..7c0697279c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -380,6 +380,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Converts the text subtitle to SRT. /// /// The input path. + /// The language. /// The input protocol. /// The output path. /// The cancellation token. @@ -407,14 +408,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// Converts the text subtitle to SRT internal. /// /// The input path. + /// The language. /// The input protocol. /// The output path. /// The cancellation token. /// Task. /// - /// inputPath - /// or - /// outputPath + /// The inputPath or outputPath is null /// private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { From 53f99d5d4bdf3f2f5b65d53f9d84f1ea220e58e7 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 4 Aug 2020 17:08:09 +0200 Subject: [PATCH 12/15] Add some analyzers to MediaBrowser.MediaEncoding --- .../BdInfo/BdInfoDirectoryInfo.cs | 19 +++-- .../BdInfo/BdInfoFileInfo.cs | 19 +++-- .../EncodingConfigurationFactory.cs | 32 -------- .../EncodingConfigurationStore.cs | 38 ++++++++++ .../Encoder/EncoderValidator.cs | 30 ++++---- .../Encoder/MediaEncoder.cs | 74 +++++++++++-------- .../MediaBrowser.MediaEncoding.csproj | 12 +++ .../Probing/ProbeResultNormalizer.cs | 65 ++++++++-------- .../Subtitles/AssParser.cs | 18 ++--- .../Subtitles/SsaParser.cs | 14 ++-- .../Subtitles/SubtitleEncoder.cs | 58 +++++++-------- 11 files changed, 210 insertions(+), 169 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs index e040286ab9..4a54b677dd 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoDirectoryInfo.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using System; using System.Linq; using BDInfo.IO; @@ -5,7 +7,7 @@ using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { - class BdInfoDirectoryInfo : IDirectoryInfo + public class BdInfoDirectoryInfo : IDirectoryInfo { private readonly IFileSystem _fileSystem = null; @@ -43,25 +45,32 @@ namespace MediaBrowser.MediaEncoding.BdInfo public IDirectoryInfo[] GetDirectories() { - return Array.ConvertAll(_fileSystem.GetDirectories(_impl.FullName).ToArray(), + return Array.ConvertAll( + _fileSystem.GetDirectories(_impl.FullName).ToArray(), x => new BdInfoDirectoryInfo(_fileSystem, x)); } public IFileInfo[] GetFiles() { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName).ToArray(), + return Array.ConvertAll( + _fileSystem.GetFiles(_impl.FullName).ToArray(), x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern) { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), + return Array.ConvertAll( + _fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, false).ToArray(), x => new BdInfoFileInfo(x)); } public IFileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption) { - return Array.ConvertAll(_fileSystem.GetFiles(_impl.FullName, new[] { searchPattern }, false, + return Array.ConvertAll( + _fileSystem.GetFiles( + _impl.FullName, + new[] { searchPattern }, + false, searchOption.HasFlag(System.IO.SearchOption.AllDirectories)).ToArray(), x => new BdInfoFileInfo(x)); } diff --git a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs index a6ff4f7678..0a8af8e9c8 100644 --- a/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs +++ b/MediaBrowser.MediaEncoding/BdInfo/BdInfoFileInfo.cs @@ -1,11 +1,18 @@ +#pragma warning disable CS1591 + using System.IO; using MediaBrowser.Model.IO; namespace MediaBrowser.MediaEncoding.BdInfo { - class BdInfoFileInfo : BDInfo.IO.IFileInfo + public class BdInfoFileInfo : BDInfo.IO.IFileInfo { - FileSystemMetadata _impl = null; + private FileSystemMetadata _impl = null; + + public BdInfoFileInfo(FileSystemMetadata impl) + { + _impl = impl; + } public string Name => _impl.Name; @@ -17,14 +24,10 @@ namespace MediaBrowser.MediaEncoding.BdInfo public bool IsDir => _impl.IsDirectory; - public BdInfoFileInfo(FileSystemMetadata impl) - { - _impl = impl; - } - public System.IO.Stream OpenRead() { - return new FileStream(FullName, + return new FileStream( + FullName, FileMode.Open, FileAccess.Read, FileShare.Read); diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs index fea7ee6fed..f81a337dbb 100644 --- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs @@ -1,11 +1,7 @@ #pragma warning disable CS1591 -using System; using System.Collections.Generic; -using System.Globalization; -using System.IO; using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Configuration; namespace MediaBrowser.MediaEncoding.Configuration { @@ -19,32 +15,4 @@ namespace MediaBrowser.MediaEncoding.Configuration }; } } - - public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration - { - public EncodingConfigurationStore() - { - ConfigurationType = typeof(EncodingOptions); - Key = "encoding"; - } - - public void Validate(object oldConfig, object newConfig) - { - var newPath = ((EncodingOptions)newConfig).TranscodingTempPath; - - if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal)) - { - // Validate - if (!Directory.Exists(newPath)) - { - throw new DirectoryNotFoundException( - string.Format( - CultureInfo.InvariantCulture, - "{0} does not exist.", - newPath)); - } - } - } - } } diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs new file mode 100644 index 0000000000..2f158157e8 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationStore.cs @@ -0,0 +1,38 @@ +#pragma warning disable CS1591 + +using System; +using System.Globalization; +using System.IO; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Model.Configuration; + +namespace MediaBrowser.MediaEncoding.Configuration +{ + public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration + { + public EncodingConfigurationStore() + { + ConfigurationType = typeof(EncodingOptions); + Key = "encoding"; + } + + public void Validate(object oldConfig, object newConfig) + { + var newPath = ((EncodingOptions)newConfig).TranscodingTempPath; + + if (!string.IsNullOrWhiteSpace(newPath) + && !string.Equals(((EncodingOptions)oldConfig).TranscodingTempPath, newPath, StringComparison.Ordinal)) + { + // Validate + if (!Directory.Exists(newPath)) + { + throw new DirectoryNotFoundException( + string.Format( + CultureInfo.InvariantCulture, + "{0} does not exist.", + newPath)); + } + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 1ac56f845f..75123a843e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { private const string DefaultEncoderPath = "ffmpeg"; - private static readonly string[] requiredDecoders = new[] + private static readonly string[] _requiredDecoders = new[] { "h264", "hevc", @@ -57,7 +57,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "vc1_opencl" }; - private static readonly string[] requiredEncoders = new[] + private static readonly string[] _requiredEncoders = new[] { "libx264", "libx265", @@ -112,6 +112,12 @@ namespace MediaBrowser.MediaEncoding.Encoder _encoderPath = encoderPath; } + private enum Codec + { + Encoder, + Decoder + } + public static Version MinVersion { get; } = new Version(4, 0); public static Version MaxVersion { get; } = null; @@ -195,8 +201,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// If that fails then we use one of the main libraries to determine if it's new/older than the latest /// we have stored. /// - /// - /// + /// The output from "ffmpeg -version". + /// The FFmpeg version. internal static Version GetFFmpegVersion(string output) { // For pre-built binaries the FFmpeg version should be mentioned at the very start of the output @@ -218,10 +224,10 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output - /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc." + /// and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc.". /// - /// - /// + /// The 'ffmpeg -version' output. + /// The library names and major.minor version numbers. private static string GetLibrariesVersionString(string output) { var rc = new StringBuilder(144); @@ -241,12 +247,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return rc.Length == 0 ? null : rc.ToString(); } - private enum Codec - { - Encoder, - Decoder - } - private IEnumerable GetHwaccelTypes() { string output = null; @@ -264,7 +264,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty(); } - var found = output.Split(new char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries).Skip(1).Distinct().ToList(); + var found = output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Skip(1).Distinct().ToList(); _logger.LogInformation("Available hwaccel types: {Types}", found); return found; @@ -288,7 +288,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return Enumerable.Empty(); } - var required = codec == Codec.Encoder ? requiredEncoders : requiredDecoders; + var required = codec == Codec.Encoder ? _requiredEncoders : _requiredDecoders; var found = Regex .Matches(output, @"^\s\S{6}\s(?[\w|-]+)\s+.+$", RegexOptions.Multiline) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 0f0ae877fb..62e6e8e3c9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -21,9 +22,8 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; -using Microsoft.Extensions.Logging; -using System.Diagnostics; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace MediaBrowser.MediaEncoding.Encoder { @@ -37,6 +37,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// internal const int DefaultImageExtractionTimeout = 5000; + /// + /// The us culture. + /// + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly ILogger _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; @@ -49,6 +54,10 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); + private List _encoders = new List(); + private List _decoders = new List(); + private List _hwaccels = new List(); + private string _ffmpegPath = string.Empty; private string _ffprobePath; @@ -79,7 +88,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. - /// Precedence is: Config > CLI > $PATH + /// Precedence is: Config > CLI > $PATH. /// public void SetFFmpegPath() { @@ -124,8 +133,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Triggered from the Settings > Transcoding UI page when users submits Custom FFmpeg path to use. /// Only write the new path to xml if it exists. Do not perform validation checks on ffmpeg here. /// - /// - /// + /// The path. + /// The path type. public void UpdateEncoderPath(string path, string pathType) { string newPath; @@ -170,8 +179,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// If checks pass, global variable FFmpegPath and EncoderLocation are updated. /// /// FQPN to test. - /// Location (External, Custom, System) of tool - /// + /// Location (External, Custom, System) of tool. + /// true if the version validation succeeded; otherwise, false. private bool ValidatePath(string path, FFmpegLocation location) { bool rc = false; @@ -223,8 +232,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Search the system $PATH environment variable looking for given filename. /// - /// - /// + /// The filename. + /// The full path to the file. private string ExistsOnSystemPath(string fileName) { var inJellyfinPath = GetEncoderPathFromDirectory(AppContext.BaseDirectory, fileName, recursive: true); @@ -248,25 +257,19 @@ namespace MediaBrowser.MediaEncoding.Encoder return null; } - private List _encoders = new List(); public void SetAvailableEncoders(IEnumerable list) { _encoders = list.ToList(); - // _logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } - private List _decoders = new List(); public void SetAvailableDecoders(IEnumerable list) { _decoders = list.ToList(); - // _logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); } - private List _hwaccels = new List(); public void SetAvailableHwaccels(IEnumerable list) { _hwaccels = list.ToList(); - //_logger.Info("Supported hwaccels: {0}", string.Join(",", list.ToArray())); } public bool SupportsEncoder(string encoder) @@ -334,8 +337,16 @@ namespace MediaBrowser.MediaEncoding.Encoder var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; - return GetMediaInfoInternal(GetInputArgument(inputFiles, request.MediaSource.Protocol), request.MediaSource.Path, request.MediaSource.Protocol, extractChapters, - probeSize, request.MediaType == DlnaProfileType.Audio, request.MediaSource.VideoType, forceEnableLogging, cancellationToken); + return GetMediaInfoInternal( + GetInputArgument(inputFiles, request.MediaSource.Protocol), + request.MediaSource.Path, + request.MediaSource.Protocol, + extractChapters, + probeSize, + request.MediaType == DlnaProfileType.Audio, + request.MediaSource.VideoType, + forceEnableLogging, + cancellationToken); } /// @@ -344,7 +355,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The input files. /// The protocol. /// System.String. - /// Unrecognized InputType + /// Unrecognized InputType. public string GetInputArgument(IReadOnlyList inputFiles, MediaProtocol protocol) => EncodingUtils.GetInputArgument(inputFiles, protocol); @@ -352,7 +363,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets the media info internal. /// /// Task{MediaInfoResult}. - private async Task GetMediaInfoInternal(string inputPath, + private async Task GetMediaInfoInternal( + string inputPath, string primaryPath, MediaProtocol protocol, bool extractChapters, @@ -380,7 +392,6 @@ namespace MediaBrowser.MediaEncoding.Encoder FileName = _ffprobePath, Arguments = args, - WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, }, @@ -441,11 +452,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - /// - /// The us culture. - /// - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) { return ExtractImage(new[] { path }, null, null, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken); @@ -461,8 +467,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return ExtractImage(inputFiles, container, imageStream, imageStreamIndex, protocol, false, null, null, cancellationToken); } - private async Task ExtractImage(string[] inputFiles, string container, MediaStream videoStream, int? imageStreamIndex, MediaProtocol protocol, bool isAudio, - Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) + private async Task ExtractImage( + string[] inputFiles, + string container, + MediaStream videoStream, + int? imageStreamIndex, + MediaProtocol protocol, + bool isAudio, + Video3DFormat? threedFormat, + TimeSpan? offset, + CancellationToken cancellationToken) { var inputArgument = GetInputArgument(inputFiles, protocol); @@ -647,7 +661,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetTimeParameter(TimeSpan time) { - return time.ToString(@"hh\:mm\:ss\.fff", UsCulture); + return time.ToString(@"hh\:mm\:ss\.fff", _usCulture); } public async Task ExtractVideoImagesOnInterval( @@ -664,11 +678,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { var inputArgument = GetInputArgument(inputFiles, protocol); - var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture); + var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); if (maxWidth.HasValue) { - var maxWidthParam = maxWidth.Value.ToString(UsCulture); + var maxWidthParam = maxWidth.Value.ToString(_usCulture); vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index dab5f866cf..017f917e27 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -28,4 +28,16 @@ + + ../jellyfin.ruleset + + + + + + + + + + diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 8aaaf4a09b..19e3bd8e60 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -18,10 +18,19 @@ namespace MediaBrowser.MediaEncoding.Probing { public class ProbeResultNormalizer { + // When extracting subtitles, the maximum length to consider (to avoid invalid filenames) + private const int MaxSubtitleDescriptionExtractionLength = 100; + + private const string ArtistReplaceValue = " | "; + + private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; + private List _splitWhiteList = null; + public ProbeResultNormalizer(ILogger logger, ILocalizationManager localization) { _logger = logger; @@ -370,7 +379,6 @@ namespace MediaBrowser.MediaEncoding.Probing private List ReadValueArray(XmlReader reader) { - var pairs = new List(); reader.MoveToContent(); @@ -951,50 +959,46 @@ namespace MediaBrowser.MediaEncoding.Probing private void SetAudioInfoFromTags(MediaInfo audio, Dictionary tags) { + var peoples = new List(); var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); if (!string.IsNullOrWhiteSpace(composer)) { - var peoples = new List(); foreach (var person in Split(composer, false)) { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer }); } - - audio.People = peoples.ToArray(); } - // var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); - // if (!string.IsNullOrWhiteSpace(conductor)) - //{ - // foreach (var person in Split(conductor, false)) - // { - // audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); - // } - //} + var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); + if (!string.IsNullOrWhiteSpace(conductor)) + { + foreach (var person in Split(conductor, false)) + { + peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); + } + } - // var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); - // if (!string.IsNullOrWhiteSpace(lyricist)) - //{ - // foreach (var person in Split(lyricist, false)) - // { - // audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); - // } - //} + var lyricist = FFProbeHelpers.GetDictionaryValue(tags, "lyricist"); + if (!string.IsNullOrWhiteSpace(lyricist)) + { + foreach (var person in Split(lyricist, false)) + { + peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Lyricist }); + } + } // Check for writer some music is tagged that way as alternative to composer/lyricist var writer = FFProbeHelpers.GetDictionaryValue(tags, "writer"); if (!string.IsNullOrWhiteSpace(writer)) { - var peoples = new List(); foreach (var person in Split(writer, false)) { peoples.Add(new BaseItemPerson { Name = person, Type = PersonType.Writer }); } - - audio.People = peoples.ToArray(); } + audio.People = peoples.ToArray(); audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); @@ -1119,8 +1123,6 @@ namespace MediaBrowser.MediaEncoding.Probing .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } - private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; - /// /// Splits the specified val. /// @@ -1140,8 +1142,6 @@ namespace MediaBrowser.MediaEncoding.Probing .Select(i => i.Trim()); } - private const string ArtistReplaceValue = " | "; - private IEnumerable SplitArtists(string val, char[] delimiters, bool splitFeaturing) { if (splitFeaturing) @@ -1171,9 +1171,6 @@ namespace MediaBrowser.MediaEncoding.Probing return artistsFound; } - - private List _splitWhiteList = null; - private IEnumerable GetSplitWhitelist() { if (_splitWhiteList == null) @@ -1250,7 +1247,7 @@ namespace MediaBrowser.MediaEncoding.Probing } /// - /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3' + /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'. /// /// The tags. /// Name of the tag. @@ -1296,8 +1293,6 @@ namespace MediaBrowser.MediaEncoding.Probing return info; } - private const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames) - private void FetchWtvInfo(MediaInfo video, InternalMediaInfoResult data) { if (data.Format == null || data.Format.Tags == null) @@ -1382,8 +1377,8 @@ namespace MediaBrowser.MediaEncoding.Probing if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number { string[] numbers = subtitle.Split(' '); - video.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]); - int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", "").Split('/')[1]); + video.IndexNumber = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[0]); + int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[1]); description = string.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it } diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs index e6e21756ad..308b62886c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs @@ -25,7 +25,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles { string line; while (reader.ReadLine() != "[Events]") - { } + { + } var headers = ParseFieldHeaders(reader.ReadLine()); @@ -75,17 +76,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles { var fields = line.Substring(8).Split(',').Select(x => x.Trim()).ToList(); - var result = new Dictionary { - {"Start", fields.IndexOf("Start")}, - {"End", fields.IndexOf("End")}, - {"Text", fields.IndexOf("Text")} - }; - return result; + return new Dictionary + { + { "Start", fields.IndexOf("Start") }, + { "End", fields.IndexOf("End") }, + { "Text", fields.IndexOf("Text") } + }; } - /// - /// Credit: https://github.com/SubtitleEdit/subtitleedit/blob/master/src/Logic/SubtitleFormats/AdvancedSubStationAlpha.cs - /// private void RemoteNativeFormatting(SubtitleTrackEvent p) { int indexOfBegin = p.Text.IndexOf('{'); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs index bd330f568b..6b7a81e6eb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -8,7 +8,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { /// - /// Credit to https://github.com/SubtitleEdit/subtitleedit/blob/a299dc4407a31796364cc6ad83f0d3786194ba22/src/Logic/SubtitleFormats/SubStationAlpha.cs + /// Credit. /// public class SsaParser : ISubtitleParser { @@ -179,10 +179,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { // h:mm:ss.cc string[] timeCode = time.Split(':', '.'); - return new TimeSpan(0, int.Parse(timeCode[0]), - int.Parse(timeCode[1]), - int.Parse(timeCode[2]), - int.Parse(timeCode[3]) * 10).Ticks; + return new TimeSpan( + 0, + int.Parse(timeCode[0]), + int.Parse(timeCode[1]), + int.Parse(timeCode[2]), + int.Parse(timeCode[3]) * 10).Ticks; } private static string GetFormattedText(string text) @@ -282,6 +284,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { text = text.Insert(start, ""); } + int indexOfEndTag = text.IndexOf("{\\c}", start); if (indexOfEndTag > 0) { @@ -320,6 +323,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { text = text.Insert(start, ""); } + text += ""; } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 7c0697279c..374e35b969 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -34,6 +34,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; + /// + /// The _semaphoreLocks. + /// + private readonly ConcurrentDictionary _semaphoreLocks = + new ConcurrentDictionary(); + public SubtitleEncoder( ILibraryManager libraryManager, ILogger logger, @@ -269,25 +275,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new SubtitleInfo(subtitleStream.Path, protocol, currentFormat, true); } - private struct SubtitleInfo - { - public SubtitleInfo(string path, MediaProtocol protocol, string format, bool isExternal) - { - Path = path; - Protocol = protocol; - Format = format; - IsExternal = isExternal; - } - - public string Path { get; set; } - - public MediaProtocol Protocol { get; set; } - - public string Format { get; set; } - - public bool IsExternal { get; set; } - } - private ISubtitleParser GetReader(string format, bool throwIfMissing) { if (string.IsNullOrEmpty(format)) @@ -360,12 +347,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentException("Unsupported format: " + format); } - /// - /// The _semaphoreLocks. - /// - private readonly ConcurrentDictionary _semaphoreLocks = - new ConcurrentDictionary(); - /// /// Gets the lock. /// @@ -414,7 +395,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// The cancellation token. /// Task. /// - /// The inputPath or outputPath is null + /// The inputPath or outputPath is null. /// private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { @@ -438,7 +419,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles (encodingParam.Equals("UTF-16BE", StringComparison.OrdinalIgnoreCase) || encodingParam.Equals("UTF-16LE", StringComparison.OrdinalIgnoreCase))) { - encodingParam = ""; + encodingParam = string.Empty; } else if (!string.IsNullOrEmpty(encodingParam)) { @@ -540,7 +521,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// The output path. /// The cancellation token. /// Task. - /// Must use inputPath list overload + /// Must use inputPath list overload. private async Task ExtractTextSubtitle( string[] inputFiles, MediaProtocol protocol, @@ -759,7 +740,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase) || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase))) { - charset = ""; + charset = string.Empty; } _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); @@ -790,5 +771,24 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentOutOfRangeException(nameof(protocol)); } } + + private struct SubtitleInfo + { + public SubtitleInfo(string path, MediaProtocol protocol, string format, bool isExternal) + { + Path = path; + Protocol = protocol; + Format = format; + IsExternal = isExternal; + } + + public string Path { get; set; } + + public MediaProtocol Protocol { get; set; } + + public string Format { get; set; } + + public bool IsExternal { get; set; } + } } } From d9f6953416ace083e7356cdc20ab4a1bd91f09cd Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 4 Aug 2020 17:14:07 +0200 Subject: [PATCH 13/15] Minor fixes --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 + MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 62e6e8e3c9..778c0b18c2 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -875,6 +875,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (dispose) { StopProcesses(); + _thumbnailResourcePool.Dispose(); } } diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 93ef6f93e1..8996d3b098 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -272,7 +272,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// Gets or sets the field_order. /// - /// The loro_surmixlev. + /// The field_order. [JsonPropertyName("field_order")] public string FieldOrder { get; set; } From 25daa7db42906f715329d1f15938e51b0a397c54 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 4 Aug 2020 22:35:23 +0200 Subject: [PATCH 14/15] Merge the args and commands item for the artifact collection --- .ci/azure-pipelines-package.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index ab752d0d93..003d5baf04 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -133,8 +133,7 @@ jobs: inputs: sshEndpoint: repository runOptions: 'commands' - commands: sudo -n /srv/repository/collect-server.azure.sh - args: /srv/repository/incoming/azure $(Build.BuildNumber) unstable + commands: sudo -n /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) unstable - task: SSH@0 displayName: 'Update Stable Repository' @@ -142,9 +141,8 @@ jobs: inputs: sshEndpoint: repository runOptions: 'commands' - commands: sudo -n /srv/repository/collect-server.azure.sh - args: /srv/repository/incoming/azure $(Build.BuildNumber) - + commands: sudo -n /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) + - job: PublishNuget displayName: 'Publish NuGet packages' dependsOn: From 393666efcfa85e858857334b5cb5a3ec70586f20 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 4 Aug 2020 20:30:45 -0600 Subject: [PATCH 15/15] fix merge conflicts --- Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/SubtitleController.cs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index ec65cb95a2..f6f08e873c 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1828,7 +1828,7 @@ namespace Jellyfin.Api.Controllers } audioTranscodeParams.Add("-vn"); - return string.Join(" ", audioTranscodeParams.ToArray()); + return string.Join(' ', audioTranscodeParams); } if (EncodingHelper.IsCopyCodec(audioCodec)) diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 22144ab1af..d5633fba52 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -262,8 +262,6 @@ namespace Jellyfin.Api.Controllers var mediaSource = await _mediaSourceManager.GetMediaSource(item, mediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false); - var builder = new StringBuilder(); - var runtime = mediaSource.RunTimeTicks ?? -1; if (runtime <= 0) @@ -277,6 +275,7 @@ namespace Jellyfin.Api.Controllers throw new ArgumentException("segmentLength was not given, or it was given incorrectly. (It should be bigger than 0)"); } + var builder = new StringBuilder(); builder.AppendLine("#EXTM3U") .Append("#EXT-X-TARGETDURATION:") .AppendLine(segmentLength.ToString(CultureInfo.InvariantCulture))