Browse Source

fix two letter language code stream selection (#1798)

pull/1799/head
Jason Dove 1 year ago committed by GitHub
parent
commit
4f393d7b06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      ErsatzTV.Application/Artists/Queries/GetArtistByIdHandler.cs
  3. 2
      ErsatzTV.Application/Television/Queries/GetTelevisionShowByIdHandler.cs
  4. 27
      ErsatzTV.Core/FFmpeg/FFmpegStreamSelector.cs
  5. 2
      ErsatzTV.Core/Interfaces/Repositories/ISearchRepository.cs
  6. 8
      ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs
  7. 4
      ErsatzTV.Infrastructure/Data/Repositories/Caching/CachingSearchRepository.cs
  8. 2
      ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs
  9. 2
      ErsatzTV.Infrastructure/Search/ElasticSearchIndex.cs
  10. 4
      ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs
  11. 3
      ErsatzTV/Program.cs

1
CHANGELOG.md

@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix adding items to empty playlists
- Fix filler preset editor and deco dead air fallback editor to only show supported collection types
- Fix infinite loop caused by impossible schedule (all collection items longer than schedule item duration)
- Fix selecting audio and subtitle streams with two-letter language codes
### Changed
- Remove some unnecessary API calls related to media server scanning and paging

2
ErsatzTV.Application/Artists/Queries/GetArtistByIdHandler.cs

@ -24,7 +24,7 @@ public class GetArtistByIdHandler : IRequestHandler<GetArtistById, Option<Artist @@ -24,7 +24,7 @@ public class GetArtistByIdHandler : IRequestHandler<GetArtistById, Option<Artist
async artist =>
{
List<string> mediaCodes = await _searchRepository.GetLanguagesForArtist(artist);
List<string> languageCodes = await _searchRepository.GetAllLanguageCodes(mediaCodes);
List<string> languageCodes = await _searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes);
return ProjectToViewModel(artist, languageCodes);
},
() => Task.FromResult(Option<ArtistViewModel>.None));

2
ErsatzTV.Application/Television/Queries/GetTelevisionShowByIdHandler.cs

@ -35,7 +35,7 @@ public class GetTelevisionShowByIdHandler : IRequestHandler<GetTelevisionShowByI @@ -35,7 +35,7 @@ public class GetTelevisionShowByIdHandler : IRequestHandler<GetTelevisionShowByI
.Map(list => list.HeadOrNone());
List<string> mediaCodes = await _searchRepository.GetLanguagesForShow(show);
List<string> languageCodes = await _searchRepository.GetAllLanguageCodes(mediaCodes);
List<string> languageCodes = await _searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes);
return ProjectToViewModel(show, languageCodes, maybeJellyfin, maybeEmby);
},
() => Task.FromResult(Option<TelevisionShowViewModel>.None));

27
ErsatzTV.Core/FFmpeg/FFmpegStreamSelector.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.FFmpeg;
using ErsatzTV.Core.Interfaces.Metadata;
@ -69,7 +70,8 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector @@ -69,7 +70,8 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector
});
}
List<string> allLanguageCodes = await _searchRepository.GetAllLanguageCodes(new List<string> { language });
List<string> allLanguageCodes = await _searchRepository.GetAllThreeLetterLanguageCodes([language])
.Map(GetTwoAndThreeLetterLanguageCodes);
if (allLanguageCodes.Count > 1)
{
_logger.LogDebug("Preferred audio language has multiple codes {Codes}", allLanguageCodes);
@ -178,7 +180,8 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector @@ -178,7 +180,8 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector
else
{
// filter to preferred language
allCodes = await _searchRepository.GetAllLanguageCodes(new List<string> { language });
allCodes = await _searchRepository.GetAllThreeLetterLanguageCodes([language])
.Map(GetTwoAndThreeLetterLanguageCodes);
if (allCodes.Count > 1)
{
_logger.LogDebug("Preferred subtitle language has multiple codes {Codes}", allCodes);
@ -402,6 +405,26 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector @@ -402,6 +405,26 @@ public class FFmpegStreamSelector : IFFmpegStreamSelector
return Option<MediaStream>.None;
}
private static List<string> GetTwoAndThreeLetterLanguageCodes(List<string> threeLetterLanguageCodes)
{
CultureInfo[] allCultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
var result = new System.Collections.Generic.HashSet<string>();
foreach (string code in threeLetterLanguageCodes)
{
IEnumerable<CultureInfo> cultures = allCultures
.Filter(ci => string.Equals(ci.ThreeLetterISOLanguageName, code, StringComparison.OrdinalIgnoreCase));
foreach (CultureInfo culture in cultures)
{
result.Add(culture.ThreeLetterISOLanguageName);
result.Add(culture.TwoLetterISOLanguageName);
}
}
return result.ToList();
}
private static AudioStream[] GetAudioStreamsForScript(MediaVersion version) => version.Streams
.Filter(s => s.MediaStreamKind == MediaStreamKind.Audio)
.Map(a => new AudioStream(a.Index, a.Channels, a.Codec, a.Default, a.Forced, a.Language, a.Title))

2
ErsatzTV.Core/Interfaces/Repositories/ISearchRepository.cs

@ -11,6 +11,6 @@ public interface ISearchRepository @@ -11,6 +11,6 @@ public interface ISearchRepository
Task<List<string>> GetSubLanguagesForSeason(Season season);
Task<List<string>> GetLanguagesForArtist(Artist artist);
Task<List<string>> GetSubLanguagesForArtist(Artist artist);
Task<List<string>> GetAllLanguageCodes(List<string> mediaCodes);
Task<List<string>> GetAllThreeLetterLanguageCodes(List<string> mediaCodes);
IAsyncEnumerable<MediaItem> GetAllMediaItems();
}

8
ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs

@ -19,15 +19,15 @@ public class CachingSearchRepositoryTests @@ -19,15 +19,15 @@ public class CachingSearchRepositoryTests
var frenchResult = new List<string> { "french_result" };
ISearchRepository searchRepo = Substitute.For<ISearchRepository>();
searchRepo.GetAllLanguageCodes(englishMediaCodes).Returns(englishResult.AsTask());
searchRepo.GetAllLanguageCodes(frenchMediaCodes).Returns(frenchResult.AsTask());
searchRepo.GetAllThreeLetterLanguageCodes(englishMediaCodes).Returns(englishResult.AsTask());
searchRepo.GetAllThreeLetterLanguageCodes(frenchMediaCodes).Returns(frenchResult.AsTask());
var repo = new CachingSearchRepository(searchRepo);
List<string> result1 = await repo.GetAllLanguageCodes(englishMediaCodes);
List<string> result1 = await repo.GetAllThreeLetterLanguageCodes(englishMediaCodes);
result1.Should().BeEquivalentTo(englishResult);
List<string> result2 = await repo.GetAllLanguageCodes(frenchMediaCodes);
List<string> result2 = await repo.GetAllThreeLetterLanguageCodes(frenchMediaCodes);
result2.Should().BeEquivalentTo(frenchResult);
}
}

4
ErsatzTV.Infrastructure/Data/Repositories/Caching/CachingSearchRepository.cs

@ -29,14 +29,14 @@ public class CachingSearchRepository : ICachingSearchRepository @@ -29,14 +29,14 @@ public class CachingSearchRepository : ICachingSearchRepository
public Task<List<string>> GetSubLanguagesForArtist(Artist artist) =>
_searchRepository.GetSubLanguagesForArtist(artist);
public async Task<List<string>> GetAllLanguageCodes(List<string> mediaCodes)
public async Task<List<string>> GetAllThreeLetterLanguageCodes(List<string> mediaCodes)
{
if (!_cache.ContainsKey(mediaCodes))
{
await _slim.WaitAsync();
try
{
_cache.TryAdd(mediaCodes, await _searchRepository.GetAllLanguageCodes(mediaCodes));
_cache.TryAdd(mediaCodes, await _searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes));
}
finally
{

2
ErsatzTV.Infrastructure/Data/Repositories/SearchRepository.cs

@ -231,7 +231,7 @@ public class SearchRepository : ISearchRepository @@ -231,7 +231,7 @@ public class SearchRepository : ISearchRepository
new { ArtistId = artist.Id }).Map(result => result.ToList());
}
public virtual async Task<List<string>> GetAllLanguageCodes(List<string> mediaCodes)
public virtual async Task<List<string>> GetAllThreeLetterLanguageCodes(List<string> mediaCodes)
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
return await dbContext.LanguageCodes.GetAllLanguageCodes(mediaCodes);

2
ErsatzTV.Infrastructure/Search/ElasticSearchIndex.cs

@ -852,7 +852,7 @@ public class ElasticSearchIndex : ISearchIndex @@ -852,7 +852,7 @@ public class ElasticSearchIndex : ISearchIndex
private async Task<List<string>> GetLanguages(ISearchRepository searchRepository, List<string> mediaCodes)
{
var englishNames = new System.Collections.Generic.HashSet<string>();
foreach (string code in await searchRepository.GetAllLanguageCodes(mediaCodes))
foreach (string code in await searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes))
{
Option<CultureInfo> maybeCultureInfo = _cultureInfos.Find(
ci => string.Equals(ci.ThreeLetterISOLanguageName, code, StringComparison.OrdinalIgnoreCase));

4
ErsatzTV.Infrastructure/Search/LuceneSearchIndex.cs

@ -540,7 +540,7 @@ public sealed class LuceneSearchIndex : ISearchIndex @@ -540,7 +540,7 @@ public sealed class LuceneSearchIndex : ISearchIndex
}
var englishNames = new System.Collections.Generic.HashSet<string>();
foreach (string code in await searchRepository.GetAllLanguageCodes(mediaCodes))
foreach (string code in await searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes))
{
Option<CultureInfo> maybeCultureInfo = _cultureInfos.Find(
ci => string.Equals(ci.ThreeLetterISOLanguageName, code, StringComparison.OrdinalIgnoreCase));
@ -564,7 +564,7 @@ public sealed class LuceneSearchIndex : ISearchIndex @@ -564,7 +564,7 @@ public sealed class LuceneSearchIndex : ISearchIndex
}
var englishNames = new System.Collections.Generic.HashSet<string>();
foreach (string code in await searchRepository.GetAllLanguageCodes(mediaCodes))
foreach (string code in await searchRepository.GetAllThreeLetterLanguageCodes(mediaCodes))
{
Option<CultureInfo> maybeCultureInfo = _cultureInfos.Find(
ci => string.Equals(ci.ThreeLetterISOLanguageName, code, StringComparison.OrdinalIgnoreCase));

3
ErsatzTV/Program.cs

@ -80,6 +80,9 @@ public class Program @@ -80,6 +80,9 @@ public class Program
.MinimumLevel.Override(
"ErsatzTV.Core.FFmpeg.FFmpegLibraryProcessService",
LoggingLevelSwitches.StreamingLevelSwitch)
.MinimumLevel.Override(
"ErsatzTV.Core.FFmpeg.FFmpegStreamSelector",
LoggingLevelSwitches.StreamingLevelSwitch)
.MinimumLevel.Override("ErsatzTV.Controllers.IptvController", LoggingLevelSwitches.StreamingLevelSwitch)
.MinimumLevel.Override("ErsatzTV.Controllers.InternalController", LoggingLevelSwitches.StreamingLevelSwitch)

Loading…
Cancel
Save