diff options
| author | Alex <48403821+AlexDalas@users.noreply.github.com> | 2025-04-08 00:59:18 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-07 08:59:18 -0600 |
| commit | 82a561b87d3b6d023168d4604c1030ff936f55f4 (patch) | |
| tree | 25a973b26838e0e07b4dd900564189bdd29ffbcf /MediaBrowser.Providers | |
| parent | 04ca27ad075bdab1eae49c43fde1ed6d45c050e4 (diff) | |
Add API support for ELRC word-based lyrics (#12941)
* Add API support for ELRC word-based lyrics
Adds support for word-based timestamps from within ELRC files.
* Create TimeTags object
* redo TimeTag implementation
Change TimeTag to long, redo TimeTag implementation
Make timestamp not nullable
Update MediaBrowser.Model/Lyrics/LyricLine.cs
Make TimeTag list IReadOnlyList
Remove nullable Timestamp
Update TimeTag description
Co-Authored-By: Cody Robibero <cody@robibe.ro>
* Changes to LyricLineTimeTag
Moved TimeTag to LyricLineTimeTag
Change "timestamp" to "start" for consistency
Change plural "TimeTags" to "Cues"
Change comments
* Change LyricLineTimeTag to LyricLineCue, include info about end times
* Remove width
* Remove width tag
* Rewrite cue parser and add tests
---------
Co-authored-by: Cody Robibero <cody@robibe.ro>
Diffstat (limited to 'MediaBrowser.Providers')
| -rw-r--r-- | MediaBrowser.Providers/Lyric/LrcLyricParser.cs | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs index fffdf4887..27d17b535 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using Jellyfin.Extensions; using LrcParser.Model; using LrcParser.Parser; @@ -14,7 +15,7 @@ namespace MediaBrowser.Providers.Lyric; /// <summary> /// LRC Lyric Parser. /// </summary> -public class LrcLyricParser : ILyricParser +public partial class LrcLyricParser : ILyricParser { private readonly LyricParser _lrcLyricParser; @@ -65,13 +66,47 @@ public class LrcLyricParser : ILyricParser } List<LyricLine> lyricList = []; - - for (int i = 0; i < sortedLyricData.Count; i++) + for (var l = 0; l < sortedLyricData.Count; l++) { - long ticks = TimeSpan.FromMilliseconds(sortedLyricData[i].StartTime).Ticks; - lyricList.Add(new LyricLine(sortedLyricData[i].Text.Trim(), ticks)); + var cues = new List<LyricLineCue>(); + var lyric = sortedLyricData[l]; + + if (lyric.TimeTags.Count != 0) + { + var keys = lyric.TimeTags.Keys.ToList(); + int current = 0, next = 1; + while (next < keys.Count) + { + var currentKey = keys[current]; + var currentMs = lyric.TimeTags[currentKey] ?? 0; + var nextMs = lyric.TimeTags[keys[next]] ?? 0; + + cues.Add(new LyricLineCue( + position: Math.Max(currentKey.Index, 0), + start: TimeSpan.FromMilliseconds(currentMs).Ticks, + end: TimeSpan.FromMilliseconds(nextMs).Ticks)); + + current++; + next++; + } + + var lastKey = keys[current]; + var lastMs = lyric.TimeTags[lastKey] ?? 0; + + cues.Add(new LyricLineCue( + position: Math.Max(lastKey.Index, 0), + start: TimeSpan.FromMilliseconds(lastMs).Ticks, + end: l + 1 < sortedLyricData.Count ? TimeSpan.FromMilliseconds(sortedLyricData[l + 1].StartTime).Ticks : null)); + } + + long lyricStartTicks = TimeSpan.FromMilliseconds(lyric.StartTime).Ticks; + lyricList.Add(new LyricLine(WhitespaceRegex().Replace(lyric.Text.Trim(), " "), lyricStartTicks, cues)); } return new LyricDto { Lyrics = lyricList }; } + + // Replacement is required until https://github.com/karaoke-dev/LrcParser/issues/83 is resolved. + [GeneratedRegex(@"\s+")] + private static partial Regex WhitespaceRegex(); } |
