|
@@ -10,6 +10,7 @@ using Jellyfin.Data.Enums;
|
|
using MediaBrowser.Controller.Entities;
|
|
using MediaBrowser.Controller.Entities;
|
|
using MediaBrowser.Controller.Entities.Audio;
|
|
using MediaBrowser.Controller.Entities.Audio;
|
|
using MediaBrowser.Controller.Library;
|
|
using MediaBrowser.Controller.Library;
|
|
|
|
+using MediaBrowser.Controller.Lyrics;
|
|
using MediaBrowser.Controller.MediaEncoding;
|
|
using MediaBrowser.Controller.MediaEncoding;
|
|
using MediaBrowser.Controller.Persistence;
|
|
using MediaBrowser.Controller.Persistence;
|
|
using MediaBrowser.Controller.Providers;
|
|
using MediaBrowser.Controller.Providers;
|
|
@@ -36,6 +37,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
private readonly ILibraryManager _libraryManager;
|
|
private readonly ILibraryManager _libraryManager;
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
|
private readonly LyricResolver _lyricResolver;
|
|
private readonly LyricResolver _lyricResolver;
|
|
|
|
+ private readonly ILyricManager _lyricManager;
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="AudioFileProber"/> class.
|
|
/// Initializes a new instance of the <see cref="AudioFileProber"/> class.
|
|
@@ -46,13 +48,15 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
/// <param name="itemRepo">Instance of the <see cref="IItemRepository"/> interface.</param>
|
|
/// <param name="itemRepo">Instance of the <see cref="IItemRepository"/> interface.</param>
|
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
|
/// <param name="lyricResolver">Instance of the <see cref="LyricResolver"/> interface.</param>
|
|
/// <param name="lyricResolver">Instance of the <see cref="LyricResolver"/> interface.</param>
|
|
|
|
+ /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param>
|
|
public AudioFileProber(
|
|
public AudioFileProber(
|
|
ILogger<AudioFileProber> logger,
|
|
ILogger<AudioFileProber> logger,
|
|
IMediaSourceManager mediaSourceManager,
|
|
IMediaSourceManager mediaSourceManager,
|
|
IMediaEncoder mediaEncoder,
|
|
IMediaEncoder mediaEncoder,
|
|
IItemRepository itemRepo,
|
|
IItemRepository itemRepo,
|
|
ILibraryManager libraryManager,
|
|
ILibraryManager libraryManager,
|
|
- LyricResolver lyricResolver)
|
|
|
|
|
|
+ LyricResolver lyricResolver,
|
|
|
|
+ ILyricManager lyricManager)
|
|
{
|
|
{
|
|
_logger = logger;
|
|
_logger = logger;
|
|
_mediaEncoder = mediaEncoder;
|
|
_mediaEncoder = mediaEncoder;
|
|
@@ -60,6 +64,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
_libraryManager = libraryManager;
|
|
_libraryManager = libraryManager;
|
|
_mediaSourceManager = mediaSourceManager;
|
|
_mediaSourceManager = mediaSourceManager;
|
|
_lyricResolver = lyricResolver;
|
|
_lyricResolver = lyricResolver;
|
|
|
|
+ _lyricManager = lyricManager;
|
|
}
|
|
}
|
|
|
|
|
|
[GeneratedRegex(@"I:\s+(.*?)\s+LUFS")]
|
|
[GeneratedRegex(@"I:\s+(.*?)\s+LUFS")]
|
|
@@ -107,7 +112,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
- Fetch(item, result, options, cancellationToken);
|
|
|
|
|
|
+ await FetchAsync(item, result, options, cancellationToken).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
|
|
var libraryOptions = _libraryManager.GetLibraryOptions(item);
|
|
var libraryOptions = _libraryManager.GetLibraryOptions(item);
|
|
@@ -211,7 +216,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
/// <param name="mediaInfo">The <see cref="Model.MediaInfo.MediaInfo"/>.</param>
|
|
/// <param name="mediaInfo">The <see cref="Model.MediaInfo.MediaInfo"/>.</param>
|
|
/// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
|
|
/// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
|
|
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
|
|
- protected void Fetch(
|
|
|
|
|
|
+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
|
|
+ private async Task FetchAsync(
|
|
Audio audio,
|
|
Audio audio,
|
|
Model.MediaInfo.MediaInfo mediaInfo,
|
|
Model.MediaInfo.MediaInfo mediaInfo,
|
|
MetadataRefreshOptions options,
|
|
MetadataRefreshOptions options,
|
|
@@ -225,7 +231,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
|
|
|
|
if (!audio.IsLocked)
|
|
if (!audio.IsLocked)
|
|
{
|
|
{
|
|
- FetchDataFromTags(audio, options);
|
|
|
|
|
|
+ await FetchDataFromTags(audio, options).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
|
|
var mediaStreams = new List<MediaStream>(mediaInfo.MediaStreams);
|
|
var mediaStreams = new List<MediaStream>(mediaInfo.MediaStreams);
|
|
@@ -241,9 +247,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
/// </summary>
|
|
/// </summary>
|
|
/// <param name="audio">The <see cref="Audio"/>.</param>
|
|
/// <param name="audio">The <see cref="Audio"/>.</param>
|
|
/// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
|
|
/// <param name="options">The <see cref="MetadataRefreshOptions"/>.</param>
|
|
- private void FetchDataFromTags(Audio audio, MetadataRefreshOptions options)
|
|
|
|
|
|
+ private async Task FetchDataFromTags(Audio audio, MetadataRefreshOptions options)
|
|
{
|
|
{
|
|
- var file = TagLib.File.Create(audio.Path);
|
|
|
|
|
|
+ using var file = TagLib.File.Create(audio.Path);
|
|
var tagTypes = file.TagTypesOnDisk;
|
|
var tagTypes = file.TagTypesOnDisk;
|
|
Tag? tags = null;
|
|
Tag? tags = null;
|
|
|
|
|
|
@@ -398,6 +404,14 @@ namespace MediaBrowser.Providers.MediaInfo
|
|
{
|
|
{
|
|
audio.SetProviderId(MetadataProvider.MusicBrainzTrack, tags.MusicBrainzTrackId);
|
|
audio.SetProviderId(MetadataProvider.MusicBrainzTrack, tags.MusicBrainzTrackId);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Save extracted lyrics if they exist,
|
|
|
|
+ // and if we are replacing all metadata or the audio doesn't yet have lyrics.
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(tags.Lyrics)
|
|
|
|
+ && (options.ReplaceAllMetadata || audio.GetMediaStreams().All(s => s.Type != MediaStreamType.Lyric)))
|
|
|
|
+ {
|
|
|
|
+ await _lyricManager.SaveLyricAsync(audio, "lrc", tags.Lyrics).ConfigureAwait(false);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|