LyricProvider.cs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using BeatLyrics.Tool.DataProvider.OnlineLyric.Models;
  2. using BeatLyrics.Tool.Models;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. namespace BeatLyrics.Tool.DataProvider.OnlineLyric
  8. {
  9. public abstract class LyricProvider
  10. {
  11. private static readonly Regex RegexLrc = new Regex(@"\[(\d{2})\:(\d{2})[\.\:](\d{2,3})\](.*)", RegexOptions.Compiled);
  12. public abstract LyricSearchResultItem[] Search(string songName, string artist);
  13. public abstract bool GetDetail(LyricSearchResultItem input);
  14. public static List<LyricDetailExt> ParseLrc(string input, int duration)
  15. {
  16. var matches = RegexLrc.Matches(input);
  17. var ret = new List<LyricDetailExt>();
  18. foreach (Match match in matches)
  19. {
  20. var sameList = new List<LyricDetailExt>();
  21. var p = match;
  22. string text;
  23. do
  24. {
  25. var timeStamp = $"{p.Groups[1]}:{p.Groups[2]},{p.Groups[3].Value.PadLeft(3, '0')}";
  26. text = p.Groups[4].Value;
  27. var item = new LyricDetailExt
  28. {
  29. TimeMs = (int)TimeSpan.ParseExact(timeStamp, @"mm\:ss\,fff", null).TotalMilliseconds,
  30. Text = text,
  31. };
  32. ret.Add(item);
  33. sameList.Add(item);
  34. p = RegexLrc.Match(text); // handle multi time stamp tag
  35. } while (p.Success);
  36. if (sameList.Count <= 1) continue;
  37. foreach (var same in sameList) same.Text = text;
  38. }
  39. ret = ret.GroupBy(p => new { p.TimeMs, p.Text }).Select(q => q.First()).ToList();
  40. ret = ret.Where(p => false == string.IsNullOrWhiteSpace(p.Text)).OrderBy(p => p.TimeMs).ToList();
  41. for (var i = 0; i < ret.Count; i++)
  42. {
  43. var item = ret[i];
  44. var nextItem = ret.Count > i + 1 ? ret[i + 1] : null;
  45. if (nextItem != null) item.DurationMs = nextItem.TimeMs - item.TimeMs;
  46. else item.DurationMs = duration - item.TimeMs;
  47. if (item.DurationMs < 0) item.DurationMs = 1000;
  48. }
  49. return ret;
  50. }
  51. }
  52. }