site logo

by Frank Lin in Front-end
2018-04-05 5 minutes to read 1 views 0 comments

Get lyric for music can be easily done by several 3rd-party services. Especially in Foobar, the ESLyric component makes it easy to auto-fetch .lrc by JavaScript. But sometimes it may fail to work for certain music or from a certain lyric provider. Recently, as I installed a newer version of foobox 6, I found the lyrics from QQ music is getting some problems with the build-in script. So I would like to know what happens and try to fix it.

old script

Following is a snippet from the build-in qqmusic 0.0.2.js come along with foobox 6 (the author is btx258 but I couldn’t find more information about the author):

var QM_CFG = {
    // DEBUG: true,
    E_SRV: "https://y.qq.com/portal/player.html",
    S_SRV: "https://c.y.qq.com/soso/fcgi-bin/client_search_cp",
    L_SRV: "https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg",
    G_PRM: "&format=json&inCharset=utf8&outCharset=utf-8",
    P_MAX: 3,
    P_NUM: 30,
    L_LOW: 5,
    L_MAX: 10,
    RETRY: 1,
};

We could see the lyric is fetched from the L_SRV. I found some Chinese posts about this API, some say it is no longer working1 2; while others report that it has some limits and only working with back end3. From the present QQ music webpage, we can find that they are using a newer URL: https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.new.fcg. Directly request data from this API address though Ajax will give you some null data, and need a back-end server for requesting. Alternatively, we can build some URLs like https://music.qq.com/miniportal/static/lyric/10/4900010.xml that give you lrc data.

newer script

Okay, in the following part of this post, I will explain more with examples that step through the process to get the lyrics.

query music information

Well, before we request the lyric, we should know more information about a certain song, such as songid, songmid that from QQ music. So we should check the existence of a certain song first.

For simplicity, build a form that accepts input keywords (song name, artist, or album information) to search for certain music from QQ music.

<form class="form-row">
  <div class="form-group col-10">
    <label for="inputKewords" class="sr-only">keywords</label>
    <input type="text" class="form-control" id="inputKeywords" placeholder="keywords">
  </div>
  <div class="col-2"><button type="submit" class="btn btn-primary mb-2">Search</button></div>
</form>

URL for searching music is3:

https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?g_tk=5381&uin=0&format=jsonp&jsonpCallback=callback&inCharset=utf-8&outCharset=utf-8&notice=0&platform=h5&needNewCode=1&w=%E6%AC%A7%E9%98%B3%E6%9C%B5&zhidaqu=1&catZhida=1&t=0&flag=1&ie=utf-8&sem=1&aggr=0&perpage=20&n=20&p=1&remoteplace=txt.mqq.all&_=1512564562121
  • w: the keywords for searching
  • p: the present page
  • n: the number of songs per page
  • format: the string format, typically is utf-8
  • jsonpCallback: the jsonp callback function, you can define your own callback function name

with Ajax, we can request the information like:

function queryData(keywords) {
  var urlString = `https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?g_tk=5381&uin=0&format=jsonp&jsonpCallback=callback&inCharset=utf-8&outCharset=utf-8&notice=0&platform=h5&needNewCode=1&w=${keywords}&zhidaqu=1&catZhida=1&t=0&flag=1&ie=utf-8&sem=1&aggr=0&perpage=20&n=20&p=1&remoteplace=txt.mqq.all`;

  $.ajax({
    type: "get",
    url: urlString,
    dataType: "jsonp",
    jsonp: "callback",
    jsonpCallback: "callback",
    scriptCharset: 'utf-8',
    success: function(data) {
      // todo
    },
    error: function() {
      alert('fail')
    }
  });
}

OK, try it use the following form, it will give at most 5 results for your keywords (sets in n parameter) and fill in a table.

In the console log, you could find a returned array about the search results.

query the lyric

To get the lyric, we need to know the songid that included in the results of the previous step.

The lyric URL is something like: https://music.qq.com/miniportal/static/lyric/10/4900010.xml.

  • 10: the result of songid%10
  • 4900010: the songid

I have injected the id to the table items. You can now click on the table item to get the URL of the lyric, and it will present in the pre tag below. Notice that, this will only return an URL to you, not guarantee the URL really exists. After that, you can fetch lyric data from the XML address via Ajax request.

loading

Click the button will toggle the real lyric or a no lyric string if lyric does not exist.

This is just a simple demo, you can play around with those APIs from the reference list below and make things happen. A full demo that just for practice: https://playground.flinhong.com/qmusic/, happy coding…

lyric QQ ajax