LyricParser.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { IParser } from './IParser';
  2. import { Lyric } from '../bean/Lyric';
  3. import { LyricLine } from '../bean/LyricLine';
  4. import { printD, printW } from '../extensions/Extension';
  5. /**
  6. * The parser to parse the string array of a standard lyric file.
  7. */
  8. export class LyricParser implements IParser {
  9. // Example lyric file:
  10. // [ti:画心]
  11. // [ar:张靓颖]
  12. // [al:432326]
  13. // [by:]
  14. // [offset:0]
  15. // [00:00.10]画心 - 张靓颖
  16. // [01:05.49]看不穿 是你失落的魂魄
  17. /**
  18. * Parse the string array to a Lyric.
  19. * @param src The lyric source, a string array.
  20. * @returns A lyric instance.
  21. */
  22. parse(src: Array<string>): Lyric {
  23. let lyricLines = new Array<LyricLine>()
  24. let title = ""
  25. let artist = ""
  26. let album = ""
  27. let by = ""
  28. let offset = 0
  29. const ignoredTags = [ 'hash', 'sign', 'qq', 'total','Outro']; // 定义需要忽略的标签
  30. for (let i = 0; i < src.length; i++) {
  31. let line = src[i]
  32. console.info(`content The line of file:line ${line}`);
  33. if (line == "" || line == "\n" || line == "\r" || line == "\r\n" || line == "[Verse]" || line == "[Chorus]"
  34. || line == "[PreChorus]" || line == "[PreChorus]"||line == "[Bridge]") {
  35. printW("the lyric line is empty, carriage return or line feed, line index= " + i)
  36. continue
  37. }
  38. // 检查是否是需要忽略的标签
  39. const shouldIgnore = ignoredTags.some(tag => line.indexOf(tag) > 0);
  40. if (shouldIgnore) {
  41. printW(`the lyric line contains ignored tag, line index= ${i}`);
  42. continue;
  43. }
  44. if (line.indexOf("ti") > 0) {
  45. title = this.parseIdTag(line)
  46. } else if (line.indexOf("ar") > 0) {
  47. artist = this.parseIdTag(line)
  48. } else if (line.indexOf("al") > 0) {
  49. album = this.parseIdTag(line)
  50. } else if (line.indexOf("by") > 0) {
  51. by = this.parseIdTag(line)
  52. } else if (line.indexOf("offset") > 0) {
  53. offset = Number.parseInt(this.parseIdTag(line))
  54. } else {
  55. // [00:00.10]画心 - 张靓颖
  56. // [01:05.49][02:08.40]看不穿 是你失落的魂魄
  57. let spr = line.split(']')
  58. if (spr.length <= 1) {
  59. printW("the lyric line is no timestamp, line index= " + i)
  60. continue
  61. }
  62. // parse text
  63. let text = spr[spr.length-1]
  64. // printD("text= " + text)
  65. // parse timeline
  66. for (let i = 0;i < spr.length - 1; i++) {
  67. let timeline = spr[i].replace("[", "")
  68. let timeStamp = this.parseTimeline(timeline)
  69. // printD("timestamp= " + timeStamp)
  70. lyricLines.push(new LyricLine(text, timeStamp - offset, -1))
  71. }
  72. }
  73. }
  74. lyricLines.sort((l1, l2) => {
  75. return l1.beginTime - l2.beginTime
  76. })
  77. for (let i = 0;i < lyricLines.length; i++) {
  78. let lyricLine = lyricLines[i]
  79. if (i == lyricLines.length - 1) {
  80. lyricLine.nextTime = lyricLine.beginTime + 1000 - offset
  81. } else {
  82. let next = lyricLines[i+1]
  83. lyricLine.nextTime = next.beginTime
  84. }
  85. }
  86. let result = new Lyric(artist, title, album, by, offset, lyricLines)
  87. return result
  88. }
  89. private parseIdTag(line: string): string {
  90. let spr = line.split(":")
  91. let spr1 = spr[1]
  92. let result = spr1.replace("]", "")
  93. return result
  94. }
  95. private parseTimeline(timeString: string): number {
  96. // 00:00.50
  97. let timeStringList = timeString.split(':')
  98. let minuteString = timeStringList[0] //00
  99. let minute = Number.parseInt(minuteString)
  100. let secondStrings = timeStringList[1] //00.50
  101. let secondStringList = secondStrings.split(".")
  102. let secondString = secondStringList[0] //00
  103. let millionSecondString = secondStringList[1] //50
  104. let seconds = Number.parseInt(secondString)
  105. let millionSecond = Number.parseInt(millionSecondString)
  106. return minute * 60000 + seconds * 1000 + millionSecond // covert to million seconds
  107. }
  108. }