1hitsong 2 лет назад
Родитель
Сommit
5f5347aee3

+ 2 - 0
.gitignore

@@ -281,3 +281,5 @@ apiclient/generated
 
 # Omnisharp crash logs
 mono_crash.*.json
+
+!LrcParser.dll

+ 49 - 0
Jellyfin.Api/Controllers/UserLibraryController.cs

@@ -1,14 +1,18 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
+using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
 using Jellyfin.Api.Extensions;
+using Jellyfin.Api.Helpers;
 using Jellyfin.Api.ModelBinders;
+using Jellyfin.Api.Models.UserDtos;
 using Jellyfin.Data.Enums;
 using Jellyfin.Extensions;
+using Kfstorm.LrcParser;
 using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
@@ -381,5 +385,50 @@ namespace Jellyfin.Api.Controllers
 
             return _userDataRepository.GetUserDataDto(item, user);
         }
+
+        /// <summary>
+        /// Gets an item's lyrics.
+        /// </summary>
+        /// <param name="userId">User id.</param>
+        /// <param name="itemId">Item id.</param>
+        /// <response code="200">Lyrics returned.</response>
+        /// <response code="404">Something went wrong. No Lyrics will be returned.</response>
+        /// <returns>An <see cref="OkResult"/> containing the intros to play.</returns>
+        [HttpGet("Users/{userId}/Items/{itemId}/Lyrics")]
+        [ProducesResponseType(StatusCodes.Status200OK)]
+        public ActionResult<QueryResult<BaseItemDto>> GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
+        {
+            var user = _userManager.GetUserById(userId);
+
+            if (user == null)
+            {
+                List<Lyrics> lyricsList = new List<Lyrics>
+                {
+                    new Lyrics { Error = "User Not Found" }
+                };
+                return NotFound(new { Results = lyricsList.ToArray() });
+            }
+
+            var item = itemId.Equals(default)
+                ? _libraryManager.GetUserRootFolder()
+                : _libraryManager.GetItemById(itemId);
+
+            if (item == null)
+            {
+                List<Lyrics> lyricsList = new List<Lyrics>
+                {
+                    new Lyrics { Error = "Requested Item Not Found" }
+                };
+                return NotFound(new { Results = lyricsList.ToArray() });
+            }
+
+            List<Lyrics> result = ItemHelper.GetLyricData(item);
+            if (string.IsNullOrEmpty(result.ElementAt(0).Error))
+            {
+                return Ok(new { Results = result });
+            }
+
+            return NotFound(new { Results = result.ToArray() });
+        }
     }
 }

+ 87 - 0
Jellyfin.Api/Helpers/ItemHelper.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Jellyfin.Api.Models.UserDtos;
+using Kfstorm.LrcParser;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Devices;
+using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Controller.Net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Jellyfin.Api.Helpers
+{
+    /// <summary>
+    /// Item helper.
+    /// </summary>
+    public static class ItemHelper
+    {
+        /// <summary>
+        /// Opens lyrics file, converts to a List of Lyrics, and returns it.
+        /// </summary>
+        /// <param name="item">Requested Item.</param>
+        /// <returns>Collection of Lyrics.</returns>
+        internal static List<Lyrics> GetLyricData(BaseItem item)
+        {
+            List<Lyrics> lyricsList = new List<Lyrics>();
+
+            string lrcFilePath = @Path.ChangeExtension(item.Path, "lrc");
+
+            // LRC File not found, fallback to TXT file
+            if (!System.IO.File.Exists(lrcFilePath))
+            {
+                string txtFilePath = @Path.ChangeExtension(item.Path, "txt");
+                if (!System.IO.File.Exists(txtFilePath))
+                {
+                    lyricsList.Add(new Lyrics { Error = "Lyric File Not Found" });
+                    return lyricsList;
+                }
+
+                var lyricTextData = System.IO.File.ReadAllText(txtFilePath);
+                string[] lyricTextLines = lyricTextData.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
+
+                foreach (var lyricLine in lyricTextLines)
+                {
+                    lyricsList.Add(new Lyrics { Text = lyricLine });
+                }
+
+                return lyricsList;
+            }
+
+            // Process LRC File
+            ILrcFile lyricData;
+            string lrcFileContent = System.IO.File.ReadAllText(lrcFilePath);
+            try
+            {
+                lrcFileContent = lrcFileContent.Replace('<', '[');
+                lrcFileContent = lrcFileContent.Replace('>', ']');
+                lyricData = Kfstorm.LrcParser.LrcFile.FromText(lrcFileContent);
+            }
+            catch
+            {
+                lyricsList.Add(new Lyrics { Error = "No Lyrics Data" });
+                return lyricsList;
+            }
+
+            if (lyricData == null)
+            {
+                lyricsList.Add(new Lyrics { Error = "No Lyrics Data" });
+                return lyricsList;
+            }
+
+            foreach (var lyricLine in lyricData.Lyrics)
+            {
+                double ticks = lyricLine.Timestamp.TotalSeconds * 10000000;
+                lyricsList.Add(new Lyrics { Start = Math.Ceiling(ticks), Text = lyricLine.Content });
+            }
+
+            return lyricsList;
+        }
+    }
+}

+ 12 - 0
Jellyfin.Api/Jellyfin.Api.csproj

@@ -46,4 +46,16 @@
     </AssemblyAttribute>
   </ItemGroup>
 
+  <ItemGroup>
+    <Reference Include="LrcParser">
+      <HintPath>Libraries\LrcParser.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="Libraries\LrcParser.dll">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+
 </Project>

BIN
Jellyfin.Api/Libraries/LrcParser.dll


+ 23 - 0
Jellyfin.Api/Models/UserDtos/Lyrics.cs

@@ -0,0 +1,23 @@
+namespace Jellyfin.Api.Models.UserDtos
+{
+    /// <summary>
+    /// Lyric dto.
+    /// </summary>
+    public class Lyrics
+    {
+        /// <summary>
+        /// Gets or sets the start.
+        /// </summary>
+        public double? Start { get; set; }
+
+        /// <summary>
+        /// Gets or sets the test.
+        /// </summary>
+        public string? Text { get; set; }
+
+        /// <summary>
+        /// Gets or sets the error.
+        /// </summary>
+        public string? Error { get; set; }
+    }
+}