< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.MediaInfo.SubtitleDownloader
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 24
Coverable lines: 24
Total lines: 213
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
DownloadSubtitles(...)0%7280%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CA1002, CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Linq;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using MediaBrowser.Common.Extensions;
 11using MediaBrowser.Controller.Entities;
 12using MediaBrowser.Controller.Entities.Movies;
 13using MediaBrowser.Controller.Entities.TV;
 14using MediaBrowser.Controller.Providers;
 15using MediaBrowser.Controller.Subtitles;
 16using MediaBrowser.Model.Entities;
 17using Microsoft.Extensions.Logging;
 18
 19namespace MediaBrowser.Providers.MediaInfo
 20{
 21    public class SubtitleDownloader
 22    {
 23        private readonly ILogger _logger;
 24        private readonly ISubtitleManager _subtitleManager;
 25
 26        public SubtitleDownloader(ILogger logger, ISubtitleManager subtitleManager)
 27        {
 028            _logger = logger;
 029            _subtitleManager = subtitleManager;
 030        }
 31
 32        public async Task<List<string>> DownloadSubtitles(
 33            Video video,
 34            List<MediaStream> mediaStreams,
 35            bool skipIfEmbeddedSubtitlesPresent,
 36            bool skipIfAudioTrackMatches,
 37            bool requirePerfectMatch,
 38            IEnumerable<string> languages,
 39            string[] disabledSubtitleFetchers,
 40            string[] subtitleFetcherOrder,
 41            bool isAutomated,
 42            CancellationToken cancellationToken)
 43        {
 44            var downloadedLanguages = new List<string>();
 45
 46            foreach (var lang in languages)
 47            {
 48                var downloaded = await DownloadSubtitles(
 49                    video,
 50                    mediaStreams,
 51                    skipIfEmbeddedSubtitlesPresent,
 52                    skipIfAudioTrackMatches,
 53                    requirePerfectMatch,
 54                    lang,
 55                    disabledSubtitleFetchers,
 56                    subtitleFetcherOrder,
 57                    isAutomated,
 58                    cancellationToken).ConfigureAwait(false);
 59
 60                if (downloaded)
 61                {
 62                    downloadedLanguages.Add(lang);
 63                }
 64            }
 65
 66            return downloadedLanguages;
 67        }
 68
 69        public Task<bool> DownloadSubtitles(
 70            Video video,
 71            List<MediaStream> mediaStreams,
 72            bool skipIfEmbeddedSubtitlesPresent,
 73            bool skipIfAudioTrackMatches,
 74            bool requirePerfectMatch,
 75            string lang,
 76            string[] disabledSubtitleFetchers,
 77            string[] subtitleFetcherOrder,
 78            bool isAutomated,
 79            CancellationToken cancellationToken)
 80        {
 081            if (video.VideoType != VideoType.VideoFile)
 82            {
 083                return Task.FromResult(false);
 84            }
 85
 086            if (!video.IsCompleteMedia)
 87            {
 088                return Task.FromResult(false);
 89            }
 90
 91            VideoContentType mediaType;
 92
 093            if (video is Episode)
 94            {
 095                mediaType = VideoContentType.Episode;
 96            }
 097            else if (video is Movie)
 98            {
 099                mediaType = VideoContentType.Movie;
 100            }
 101            else
 102            {
 103                // These are the only supported types
 0104                return Task.FromResult(false);
 105            }
 106
 0107            return DownloadSubtitles(
 0108                video,
 0109                mediaStreams,
 0110                skipIfEmbeddedSubtitlesPresent,
 0111                skipIfAudioTrackMatches,
 0112                requirePerfectMatch,
 0113                lang,
 0114                disabledSubtitleFetchers,
 0115                subtitleFetcherOrder,
 0116                mediaType,
 0117                isAutomated,
 0118                cancellationToken);
 119        }
 120
 121        private async Task<bool> DownloadSubtitles(
 122            Video video,
 123            List<MediaStream> mediaStreams,
 124            bool skipIfEmbeddedSubtitlesPresent,
 125            bool skipIfAudioTrackMatches,
 126            bool requirePerfectMatch,
 127            string language,
 128            string[] disabledSubtitleFetchers,
 129            string[] subtitleFetcherOrder,
 130            VideoContentType mediaType,
 131            bool isAutomated,
 132            CancellationToken cancellationToken)
 133        {
 134            // There's already subtitles for this language
 135            if (mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && i.IsTextSubtitleStream && string.Equals(i.La
 136            {
 137                return false;
 138            }
 139
 140            var audioStreams = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList();
 141            var defaultAudioStreams = audioStreams.Where(i => i.IsDefault).ToList();
 142
 143            // If none are marked as default, just take a guess
 144            if (defaultAudioStreams.Count == 0)
 145            {
 146                defaultAudioStreams = audioStreams.Take(1).ToList();
 147            }
 148
 149            // There's already a default audio stream for this language
 150            if (skipIfAudioTrackMatches &&
 151                defaultAudioStreams.Any(i => string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
 152            {
 153                return false;
 154            }
 155
 156            // There's an internal subtitle stream for this language
 157            if (skipIfEmbeddedSubtitlesPresent &&
 158                mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal && string.Equals(i.Language, l
 159            {
 160                return false;
 161            }
 162
 163            var request = new SubtitleSearchRequest
 164            {
 165                ContentType = mediaType,
 166                IndexNumber = video.IndexNumber,
 167                Language = language,
 168                MediaPath = video.Path,
 169                Name = video.Name,
 170                ParentIndexNumber = video.ParentIndexNumber,
 171                ProductionYear = video.ProductionYear,
 172                ProviderIds = video.ProviderIds,
 173
 174                // Stop as soon as we find something
 175                SearchAllProviders = false,
 176
 177                IsPerfectMatch = requirePerfectMatch,
 178                DisabledSubtitleFetchers = disabledSubtitleFetchers,
 179                SubtitleFetcherOrder = subtitleFetcherOrder,
 180                IsAutomated = isAutomated
 181            };
 182
 183            if (video is Episode episode)
 184            {
 185                request.IndexNumberEnd = episode.IndexNumberEnd;
 186                request.SeriesName = episode.SeriesName;
 187            }
 188
 189            try
 190            {
 191                var searchResults = await _subtitleManager.SearchSubtitles(request, cancellationToken).ConfigureAwait(fa
 192
 193                var result = searchResults.FirstOrDefault();
 194
 195                if (result is not null)
 196                {
 197                    await _subtitleManager.DownloadSubtitles(video, result.Id, cancellationToken).ConfigureAwait(false);
 198
 199                    return true;
 200                }
 201            }
 202            catch (RateLimitExceededException)
 203            {
 204            }
 205            catch (Exception ex)
 206            {
 207                _logger.LogError(ex, "Error downloading subtitles");
 208            }
 209
 210            return false;
 211        }
 212    }
 213}