mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-13 19:20:23 +01:00
Store lyrics in the database as media streams (#9951)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -27,6 +28,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
Artists = Array.Empty<string>();
|
||||
AlbumArtists = Array.Empty<string>();
|
||||
LyricFiles = Array.Empty<string>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -65,6 +67,16 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
[JsonIgnore]
|
||||
public override MediaType MediaType => MediaType.Audio;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this audio has lyrics.
|
||||
/// </summary>
|
||||
public bool? HasLyrics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of lyric paths.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> LyricFiles { get; set; }
|
||||
|
||||
public override double GetDefaultPrimaryImageAspectRatio()
|
||||
{
|
||||
return 1;
|
||||
|
||||
@@ -168,6 +168,15 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>BaseItem.</returns>
|
||||
BaseItem GetItemById(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item by id, as T.
|
||||
/// </summary>
|
||||
/// <param name="id">The item id.</param>
|
||||
/// <typeparam name="T">The type of item.</typeparam>
|
||||
/// <returns>The item.</returns>
|
||||
T GetItemById<T>(Guid id)
|
||||
where T : BaseItem;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the intros.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Lyrics;
|
||||
using MediaBrowser.Model.Providers;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
@@ -9,16 +16,93 @@ namespace MediaBrowser.Controller.Lyrics;
|
||||
public interface ILyricManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the lyrics.
|
||||
/// Occurs when a lyric download fails.
|
||||
/// </summary>
|
||||
/// <param name="item">The media item.</param>
|
||||
/// <returns>A task representing found lyrics the passed item.</returns>
|
||||
Task<LyricResponse?> GetLyrics(BaseItem item);
|
||||
event EventHandler<LyricDownloadFailureEventArgs> LyricDownloadFailure;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if requested item has a matching local lyric file.
|
||||
/// Search for lyrics for the specified song.
|
||||
/// </summary>
|
||||
/// <param name="item">The media item.</param>
|
||||
/// <returns>True if item has a matching lyric file; otherwise false.</returns>
|
||||
bool HasLyricFile(BaseItem item);
|
||||
/// <param name="audio">The song.</param>
|
||||
/// <param name="isAutomated">Whether the request is automated.</param>
|
||||
/// <param name="cancellationToken">CancellationToken to use for the operation.</param>
|
||||
/// <returns>The list of lyrics.</returns>
|
||||
Task<IReadOnlyList<RemoteLyricInfoDto>> SearchLyricsAsync(
|
||||
Audio audio,
|
||||
bool isAutomated,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Search for lyrics.
|
||||
/// </summary>
|
||||
/// <param name="request">The search request.</param>
|
||||
/// <param name="cancellationToken">CancellationToken to use for the operation.</param>
|
||||
/// <returns>The list of lyrics.</returns>
|
||||
Task<IReadOnlyList<RemoteLyricInfoDto>> SearchLyricsAsync(
|
||||
LyricSearchRequest request,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Download the lyrics.
|
||||
/// </summary>
|
||||
/// <param name="audio">The audio.</param>
|
||||
/// <param name="lyricId">The remote lyric id.</param>
|
||||
/// <param name="cancellationToken">CancellationToken to use for the operation.</param>
|
||||
/// <returns>The downloaded lyrics.</returns>
|
||||
Task<LyricDto?> DownloadLyricsAsync(
|
||||
Audio audio,
|
||||
string lyricId,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Download the lyrics.
|
||||
/// </summary>
|
||||
/// <param name="audio">The audio.</param>
|
||||
/// <param name="libraryOptions">The library options to use.</param>
|
||||
/// <param name="lyricId">The remote lyric id.</param>
|
||||
/// <param name="cancellationToken">CancellationToken to use for the operation.</param>
|
||||
/// <returns>The downloaded lyrics.</returns>
|
||||
Task<LyricDto?> DownloadLyricsAsync(
|
||||
Audio audio,
|
||||
LibraryOptions libraryOptions,
|
||||
string lyricId,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Upload new lyrics.
|
||||
/// </summary>
|
||||
/// <param name="audio">The audio file the lyrics belong to.</param>
|
||||
/// <param name="lyricResponse">The lyric response.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task<LyricDto?> UploadLyricAsync(Audio audio, LyricResponse lyricResponse);
|
||||
|
||||
/// <summary>
|
||||
/// Get the remote lyrics.
|
||||
/// </summary>
|
||||
/// <param name="id">The remote lyrics id.</param>
|
||||
/// <param name="cancellationToken">CancellationToken to use for the operation.</param>
|
||||
/// <returns>The lyric response.</returns>
|
||||
Task<LyricDto?> GetRemoteLyricsAsync(string id, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the lyrics.
|
||||
/// </summary>
|
||||
/// <param name="audio">The audio file to remove lyrics from.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task DeleteLyricsAsync(Audio audio);
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of lyric providers.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>Lyric providers.</returns>
|
||||
IReadOnlyList<LyricProviderInfo> GetSupportedProviders(BaseItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Get the existing lyric for the audio.
|
||||
/// </summary>
|
||||
/// <param name="audio">The audio item.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The parsed lyric model.</returns>
|
||||
Task<LyricDto?> GetLyricsAsync(Audio audio, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Providers.Lyric;
|
||||
using MediaBrowser.Model.Lyrics;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
@@ -24,5 +24,5 @@ public interface ILyricParser
|
||||
/// </summary>
|
||||
/// <param name="lyrics">The raw lyrics content.</param>
|
||||
/// <returns>The parsed lyrics or null if invalid.</returns>
|
||||
LyricResponse? ParseLyrics(LyricFile lyrics);
|
||||
LyricDto? ParseLyrics(LyricFile lyrics);
|
||||
}
|
||||
|
||||
34
MediaBrowser.Controller/Lyrics/ILyricProvider.cs
Normal file
34
MediaBrowser.Controller/Lyrics/ILyricProvider.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Lyrics;
|
||||
using MediaBrowser.Model.Providers;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
/// Interface ILyricsProvider.
|
||||
/// </summary>
|
||||
public interface ILyricProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the provider name.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Search for lyrics.
|
||||
/// </summary>
|
||||
/// <param name="request">The search request.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The list of remote lyrics.</returns>
|
||||
Task<IEnumerable<RemoteLyricInfo>> SearchAsync(LyricSearchRequest request, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Get the lyrics.
|
||||
/// </summary>
|
||||
/// <param name="id">The remote lyric id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The lyric response.</returns>
|
||||
Task<LyricResponse?> GetLyricsAsync(string id, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics
|
||||
{
|
||||
/// <summary>
|
||||
/// An event that occurs when subtitle downloading fails.
|
||||
/// </summary>
|
||||
public class LyricDownloadFailureEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the item.
|
||||
/// </summary>
|
||||
public required BaseItem Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the provider.
|
||||
/// </summary>
|
||||
public required string Provider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception.
|
||||
/// </summary>
|
||||
public required Exception Exception { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace MediaBrowser.Providers.Lyric;
|
||||
|
||||
/// <summary>
|
||||
/// The information for a raw lyrics file before parsing.
|
||||
/// </summary>
|
||||
public class LyricFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LyricFile"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="content">The content, must not be empty.</param>
|
||||
public LyricFile(string name, string content)
|
||||
{
|
||||
Name = name;
|
||||
Content = content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the lyrics file. This must include the file extension.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the contents of the file.
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
/// Lyric model.
|
||||
/// </summary>
|
||||
public class LyricLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LyricLine"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The lyric text.</param>
|
||||
/// <param name="start">The lyric start time in ticks.</param>
|
||||
public LyricLine(string text, long? start = null)
|
||||
{
|
||||
Text = text;
|
||||
Start = start;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text of this lyric line.
|
||||
/// </summary>
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start time in ticks.
|
||||
/// </summary>
|
||||
public long? Start { get; }
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
/// LyricMetadata model.
|
||||
/// </summary>
|
||||
public class LyricMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the song artist.
|
||||
/// </summary>
|
||||
public string? Artist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the album this song is on.
|
||||
/// </summary>
|
||||
public string? Album { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title of the song.
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the author of the lyric data.
|
||||
/// </summary>
|
||||
public string? Author { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the length of the song in ticks.
|
||||
/// </summary>
|
||||
public long? Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets who the LRC file was created by.
|
||||
/// </summary>
|
||||
public string? By { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the lyric offset compared to audio in ticks.
|
||||
/// </summary>
|
||||
public long? Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the software used to create the LRC file.
|
||||
/// </summary>
|
||||
public string? Creator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the version of the creator used.
|
||||
/// </summary>
|
||||
public string? Version { get; set; }
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
/// LyricResponse model.
|
||||
/// </summary>
|
||||
public class LyricResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets Metadata for the lyrics.
|
||||
/// </summary>
|
||||
public LyricMetadata Metadata { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a collection of individual lyric lines.
|
||||
/// </summary>
|
||||
public IReadOnlyList<LyricLine> Lyrics { get; set; } = Array.Empty<LyricLine>();
|
||||
}
|
||||
Reference in New Issue
Block a user