jellyfin/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs

214 lines
7 KiB
C#
Raw Normal View History

#nullable disable
#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities;
2014-05-07 04:28:19 +02:00
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
2014-05-12 00:38:10 +02:00
using MediaBrowser.Controller.Providers;
2014-05-07 04:28:19 +02:00
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
2014-05-07 04:28:19 +02:00
namespace MediaBrowser.Providers.MediaInfo
{
public class SubtitleDownloader
{
private readonly ILogger _logger;
private readonly ISubtitleManager _subtitleManager;
public SubtitleDownloader(ILogger logger, ISubtitleManager subtitleManager)
{
_logger = logger;
_subtitleManager = subtitleManager;
}
2020-06-06 02:15:56 +02:00
public async Task<List<string>> DownloadSubtitles(
Video video,
List<MediaStream> mediaStreams,
2016-03-19 23:31:00 +01:00
bool skipIfEmbeddedSubtitlesPresent,
2014-05-08 04:16:11 +02:00
bool skipIfAudioTrackMatches,
bool requirePerfectMatch,
2014-05-07 04:28:19 +02:00
IEnumerable<string> languages,
2018-09-12 19:26:21 +02:00
string[] disabledSubtitleFetchers,
string[] subtitleFetcherOrder,
bool isAutomated,
2014-05-07 04:28:19 +02:00
CancellationToken cancellationToken)
2017-09-10 05:18:23 +02:00
{
var downloadedLanguages = new List<string>();
foreach (var lang in languages)
{
2020-09-07 13:20:39 +02:00
var downloaded = await DownloadSubtitles(
video,
mediaStreams,
skipIfEmbeddedSubtitlesPresent,
skipIfAudioTrackMatches,
requirePerfectMatch,
lang,
disabledSubtitleFetchers,
subtitleFetcherOrder,
isAutomated,
2020-09-07 13:20:39 +02:00
cancellationToken).ConfigureAwait(false);
2017-09-10 05:18:23 +02:00
if (downloaded)
{
downloadedLanguages.Add(lang);
}
}
return downloadedLanguages;
}
2020-09-07 13:20:39 +02:00
public Task<bool> DownloadSubtitles(
Video video,
2017-09-10 05:18:23 +02:00
List<MediaStream> mediaStreams,
bool skipIfEmbeddedSubtitlesPresent,
bool skipIfAudioTrackMatches,
bool requirePerfectMatch,
string lang,
2018-09-12 19:26:21 +02:00
string[] disabledSubtitleFetchers,
string[] subtitleFetcherOrder,
bool isAutomated,
2017-09-10 05:18:23 +02:00
CancellationToken cancellationToken)
2014-05-07 04:28:19 +02:00
{
2018-09-12 19:26:21 +02:00
if (video.VideoType != VideoType.VideoFile)
2014-05-07 04:28:19 +02:00
{
2017-09-10 05:18:23 +02:00
return Task.FromResult(false);
2014-05-07 04:28:19 +02:00
}
2017-08-26 21:50:02 +02:00
if (!video.IsCompleteMedia)
{
2017-09-10 05:18:23 +02:00
return Task.FromResult(false);
2017-08-26 21:50:02 +02:00
}
2014-05-12 00:38:10 +02:00
VideoContentType mediaType;
2014-05-07 04:28:19 +02:00
if (video is Episode)
{
2014-05-12 00:38:10 +02:00
mediaType = VideoContentType.Episode;
2014-05-07 04:28:19 +02:00
}
else if (video is Movie)
{
2014-05-12 00:38:10 +02:00
mediaType = VideoContentType.Movie;
2014-05-07 04:28:19 +02:00
}
else
{
// These are the only supported types
2017-09-10 05:18:23 +02:00
return Task.FromResult(false);
2014-05-07 04:28:19 +02:00
}
2020-09-07 13:20:39 +02:00
return DownloadSubtitles(
video,
mediaStreams,
skipIfEmbeddedSubtitlesPresent,
skipIfAudioTrackMatches,
requirePerfectMatch,
lang,
disabledSubtitleFetchers,
subtitleFetcherOrder,
mediaType,
isAutomated,
2020-09-07 13:20:39 +02:00
cancellationToken);
2014-05-07 04:28:19 +02:00
}
2020-09-07 13:20:39 +02:00
private async Task<bool> DownloadSubtitles(
Video video,
List<MediaStream> mediaStreams,
2016-03-19 23:31:00 +01:00
bool skipIfEmbeddedSubtitlesPresent,
2014-05-08 04:16:11 +02:00
bool skipIfAudioTrackMatches,
bool requirePerfectMatch,
2014-05-07 04:28:19 +02:00
string language,
2018-09-12 19:26:21 +02:00
string[] disabledSubtitleFetchers,
string[] subtitleFetcherOrder,
2014-05-12 00:38:10 +02:00
VideoContentType mediaType,
bool isAutomated,
2014-05-07 04:28:19 +02:00
CancellationToken cancellationToken)
{
// There's already subtitles for this language
if (mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && i.IsTextSubtitleStream && string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
2014-05-07 04:28:19 +02:00
{
return false;
}
var audioStreams = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList();
2014-05-08 22:09:53 +02:00
var defaultAudioStreams = audioStreams.Where(i => i.IsDefault).ToList();
// If none are marked as default, just take a guess
if (defaultAudioStreams.Count == 0)
{
defaultAudioStreams = audioStreams.Take(1).ToList();
}
2014-05-08 07:04:39 +02:00
// There's already a default audio stream for this language
2014-05-08 04:16:11 +02:00
if (skipIfAudioTrackMatches &&
2014-05-08 22:09:53 +02:00
defaultAudioStreams.Any(i => string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
2014-05-07 22:28:28 +02:00
{
return false;
}
2014-05-07 22:24:34 +02:00
2014-05-07 04:28:19 +02:00
// There's an internal subtitle stream for this language
2016-03-19 23:31:00 +01:00
if (skipIfEmbeddedSubtitlesPresent &&
mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal && string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
2014-05-07 04:28:19 +02:00
{
return false;
}
var request = new SubtitleSearchRequest
{
ContentType = mediaType,
IndexNumber = video.IndexNumber,
Language = language,
MediaPath = video.Path,
Name = video.Name,
ParentIndexNumber = video.ParentIndexNumber,
ProductionYear = video.ProductionYear,
2014-05-17 06:24:10 +02:00
ProviderIds = video.ProviderIds,
// Stop as soon as we find something
SearchAllProviders = false,
2018-09-12 19:26:21 +02:00
IsPerfectMatch = requirePerfectMatch,
DisabledSubtitleFetchers = disabledSubtitleFetchers,
SubtitleFetcherOrder = subtitleFetcherOrder,
IsAutomated = isAutomated
2014-05-07 04:28:19 +02:00
};
if (video is Episode episode)
2014-05-07 04:28:19 +02:00
{
request.IndexNumberEnd = episode.IndexNumberEnd;
request.SeriesName = episode.SeriesName;
}
2014-05-07 04:28:19 +02:00
try
{
var searchResults = await _subtitleManager.SearchSubtitles(request, cancellationToken).ConfigureAwait(false);
var result = searchResults.FirstOrDefault();
2022-12-05 15:01:13 +01:00
if (result is not null)
2014-05-07 04:28:19 +02:00
{
2018-09-12 19:26:21 +02:00
await _subtitleManager.DownloadSubtitles(video, result.Id, cancellationToken).ConfigureAwait(false);
2014-05-07 04:28:19 +02:00
return true;
}
}
catch (RateLimitExceededException)
{
}
2014-05-07 04:28:19 +02:00
catch (Exception ex)
{
2018-12-20 13:11:26 +01:00
_logger.LogError(ex, "Error downloading subtitles");
2014-05-07 04:28:19 +02:00
}
return false;
}
}
}