网易云歌词接口 解析类 如何用

网易云歌词接口

// /lyric?id=447926071
{
  "sgc": false,
  "sfy": false,
  "qfy": false,
  "lrc": {
    "version": 7,
    "lyric": "[00:00.000] 作曲 : 赵雷\n[00:01.000] 作词 : 赵雷\n[00:04.75]编曲:赵雷 / 喜子\n[00:05.75]\n[00:06.75]BASS:张岭\n[00:07.75]鼓:贝贝\n[00:08.75]钢琴:柳森\n[00:09.75]箱琴:赵雷 / 喜子\n[00:10.75]笛子:祝子\n[00:11.75]弦乐编写:柳森\n[00:12.75]弦乐:亚洲爱乐国际乐团\n[00:13.75]和声:朱奇迹 / 赵雷 / 旭东\n[00:16.75]让我掉下眼泪的 不止昨夜的酒\n[00:25.91]让我依依不舍的 不止你的温柔\n[00:33.91]余路还要走多久 你攥着我的手\n[00:41.70]让我感到为难的 是挣扎的自由\n[00:52.10]分别总是在九月 回忆是思念的愁\n[00:59.63]深秋嫩绿的垂柳 亲吻着我额头\n[01:07.53]在那座阴雨的小城里 我从未忘记你\n[01:15.41]成都 带不走的 只有你\n[01:23.69]和我在成都的街头走一走\n[01:31.08]直到所有的灯都熄灭了也不停留\n[01:39.69]你会挽着我的衣袖 我会把手揣进裤兜\n[01:47.08]走到玉林路的尽头 坐在(走过)小酒馆的门口\n[02:30.37]分别总是在九月 回忆是思念的愁\n[02:38.10]深秋嫩绿的垂柳 亲吻着我额头\n[02:46.13]在那座阴雨的小城里 我从未忘记你\n[02:54.02]成都 带不走的 只有你\n[03:02.34]和我在成都的街头走一走\n[03:10.41]直到所有的灯都熄灭了也不停留\n[03:18.34]你会挽着我的衣袖 我会把手揣进裤兜\n[03:25.51]走到玉林路的尽头 坐在(走过)小酒馆的门口\n[04:35.96][03:35.40]和我在成都的街头走一走\n[04:42.76][03:45.39]直到所有的灯都熄灭了也不停留\n[03:53.62]和我在成都的街头走一走\n[04:01.35]直到所有的灯都熄灭了也不停留\n[04:08.95]你会挽着我的衣袖 我会把手揣进裤兜\n[04:17.27]走到玉林路的尽头 坐在(走过)小酒馆的门口\n"
  },
  "klyric": {
    "version": 0,
    "lyric": null
  },
  "tlyric": {
    "version": 0,
    "lyric": null
  },
  "code": 200
}

解析类

export class Lyric {
  constructor(data) {
    this.data = data;
    this.lrc = data["lrc"]["lyric"];
    this.tlyric = data["tlyric"]["lyric"];
    this.lrcMap = this.getLyricMap(this.lrc);
    this.finalLrcMap = this.convertProp(Object.assign({}, this.lrcMap));
    this.tlyricMap = this.getLyricMap(this.tlyric);
    this.finalTlyricMap = this.convertProp(Object.assign({}, this.tlyricMap));
  }
  // 以对象形式格式化歌词,{[00:12.570]: "歌词"}
  getLyricMap(lrc) {
    let key, value, sIdx, eIdx, nsIdx;
    let ret = {};
    if (!lrc || typeof lrc !== "string") return ret;
    while (lrc) {
      sIdx = lrc.indexOf("[");
      eIdx = lrc.indexOf("]") + 1;
      if (sIdx !== -1 && eIdx !== -1) {
        key = lrc.slice(sIdx, eIdx);
        advance(eIdx);
        nsIdx = lrc.indexOf("[");
        value = lrc.slice(0, nsIdx);
        ret[key] = value.trim();
        advance(nsIdx);
      } else {
        break;
      }
    }
    function advance(n) {
      lrc = lrc.substring(n);
    }
    return ret;
  }
  // 再次格式化歌词,{12570: "歌词"},过滤了空串
  convertProp(obj) {
    Object.keys(obj).forEach((str) => {
      if (!obj[str]) {
        delete obj[str];
      } else {
        let prop = f(str);
        obj[prop] = obj[str];
        delete obj[str];
      }
    });
    function f(str) {
      str = str.match(/^\[(\d+):(\d+)\.(\d+)/);
      return Number(str[1]) * 60 * 1000 + Number(str[2]) * 1000 + Number(str[3]);
    }
    return obj;
  }
  // 获取当前歌词
  getCurPlayLyric(audioCurTime) {
    let audioCurTimeMs = audioCurTime * 1000;
    let arrTime = Object.keys(this.finalLrcMap);
    let i = 0,
      len = arrTime.length,
      idx;
    let hasTranslate = Object.keys(this.finalTlyricMap).length > 0;
    if (audioCurTimeMs === 0) {
      return g.call(this, arrTime[0]);
    }
    if (audioCurTimeMs >= Number(arrTime[len - 1])) {
      return g.call(this, arrTime[len - 1]);
    }
    for (; i < len; i++) {
      if (audioCurTimeMs >= Number(arrTime[i - 1]) && audioCurTimeMs < Number(arrTime[i])) {
        idx = i - 1;
        break;
      }
    }
    return g.call(this, arrTime[idx]);
    function g(prop) {
      return hasTranslate ? v(this.finalLrcMap[prop]) + "\n" + v(this.finalTlyricMap[prop]) : v(this.finalLrcMap[prop]);
    }
    function v(val) {
      return typeof val === "undefined" ? "" : val;
    }
  }
}

如何用

// init lyricData是歌词接口返回的数据
lyric = new Lyric(lyricData);
// 监听播放 $audio是audio标签,如果使用vue,内置timeupdate钩子
$audio.addEventListener(
  "timeupdate",
  () => {
    // 当前时间的歌词
    let lyric = getCurPlayLyric($audio.currentTime);
  },
  false
);

暂无评论