Add Lyrics API Endpoint

This commit is contained in:
1hitsong 2022-09-09 20:14:23 -04:00
parent faadbbce00
commit 5f5347aee3
6 changed files with 173 additions and 0 deletions

2
.gitignore vendored
View File

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

View File

@ -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() });
}
}
}

View File

@ -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;
}
}
}

View File

@ -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>

Binary file not shown.

View File

@ -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; }
}
}