MusicBee 是一個(gè)很棒的免費(fèi)音樂管理、播放軟件,支持通過插件來擴(kuò)展功能。然而 MusicBee 在初始情況下僅對(duì)外國的幾個(gè)歌詞數(shù)據(jù)庫進(jìn)行檢索,得到的結(jié)果一般是不帶時(shí)間軸的純文本歌詞,并且檢索成功率并不高。自己寫咯。

MusicBee歌詞插件下載
GitHub鏈接
使用方法:下載后將所有文件復(fù)制到 MusicBee 目錄下的 Plugins 文件夾內(nèi),重啟 MusicBee,在首選項(xiàng)-插件中看到 GetLyrics 插件即成功啟用。
在歌詞界面 右鍵-重新搜索 可以查找歌詞,默認(rèn)在切歌時(shí)會(huì)查找一次,右鍵-查找下一個(gè)提供者 會(huì)在插件提供的歌詞和內(nèi)置的數(shù)據(jù)庫查詢結(jié)果中切換。
更新
2017-8-3
現(xiàn)在可以自己選擇搜索結(jié)果了
2017-8-8
現(xiàn)在可以在選項(xiàng)中設(shè)置是否自動(dòng)選擇歌詞
MusicBee插件開發(fā)
獲取模板
從這里下載MusicBee的插件開發(fā)模板。本文以C#為開發(fā)語言,熟悉VB的也可以去官網(wǎng)下載VB語言的插件開發(fā)模板,具體細(xì)節(jié)應(yīng)該大同小異。官方并沒有給出任何插件相關(guān)文檔,所有API和要求都寫在了模板里(偷懶,報(bào)警了?。?。
下載解壓應(yīng)該得到類似的目錄結(jié)構(gòu):

用宇宙最強(qiáng)IDE打開 .csproj 的項(xiàng)目工程文件,其中 TestCSharpDll.cs 這個(gè)文件可以隨意重命名。在VS中打開以后,可以看到我們主要需要改寫的就是這個(gè) TestCSharpDll.cs 文件。
基礎(chǔ)信息改寫
整個(gè)插件有一些基礎(chǔ)信息可供定制,改寫的位置在 TestCSharpDll.cs -> Initialise方法里面。大概長這樣,注意看注釋咯:
public PluginInfo Initialise(IntPtr apiInterfacePtr)
{
mbApiInterface = new MusicBeeApiInterface();
mbApiInterface.Initialise(apiInterfacePtr);
about.PluginInfoVersion = PluginInfoVersion;
about.Name = "GetLyrics";//你的插件的名字
about.Description = "Get Lyrics From Internet";//插件描述
about.Author = "Dixeran";//插件作者
about.TargetApplication = "";
// current only applies to artwork, lyrics or instant messenger name that appears in the provider drop down selector or target Instant Messenger(不知道啥用,別改)
about.Type = PluginType.LyricsRetrieval;
//這個(gè)很重要,速覽定義可以看到,這是一個(gè)枚舉類型,決定了插件被調(diào)用的函數(shù),我這里寫的是提供歌詞的插件,所以必須是這個(gè)值。
about.VersionMajor = 1; // your plugin version(插件版本號(hào))
about.VersionMinor = 0;
about.Revision = 1;
about.MinInterfaceVersion = MinInterfaceVersion;
about.MinApiRevision = MinApiRevision;
about.ReceiveNotifications = ReceiveNotificationFlags.DownloadEvents;
about.ConfigurationPanelHeight = 0; // height in pixels that musicbee should reserve in a panel for config settings. When set, a handle to an empty panel will be passed to the Configure function
return about;
}
更改完畢以后,已經(jīng)可以試著生成了!如果參數(shù)都正確的話,把生成的插件(三個(gè)文件)放到 MusicBee 安裝目錄的 Plugins 文件夾內(nèi),啟動(dòng) MusicBee,在首選項(xiàng)->插件中應(yīng)該可以看到剛剛生成的插件啦。
關(guān)鍵函數(shù)改寫
插件要起作用,關(guān)鍵在于改寫特定的被調(diào)函數(shù)并且返回正確的格式。例如這里是歌詞插件,可以看到在代碼中最下面有一個(gè)函數(shù)RetrieveLyrics(...),上面還有一大段注釋,大概意思就是如果插件類型是PluginType.LyricsRetrieval,這個(gè)函數(shù)就會(huì)被調(diào)用,你提供的歌詞以 string 對(duì)象返回,如果沒有查到歌詞,返回 null。函數(shù)調(diào)用提供了很多歌曲相關(guān)的參數(shù),足夠我們查找歌詞了,接下來就是抓取QQ音樂的API并且把查詢方法寫入函數(shù)中。
using System.Net;
using System.IO;
using Newtonsoft.Json.Linq;
using System.Web;
public string RetrieveLyrics(string sourceFileUrl, string artist, string trackTitle, string album, bool synchronisedPreferred, string provider)
{
string SearchUrl = String.Format("http://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w={0} {1}&g_tk=5381&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0", trackTitle, artist);
var request = (HttpWebRequest)WebRequest.Create(SearchUrl);
var response = (HttpWebResponse)request.GetResponse();
var SearchString = new StreamReader(response.GetResponseStream()).ReadToEnd();
SearchString = SearchString.Replace("callback(", "");
SearchString = SearchString.Replace("})", "}");//刪除回調(diào)中的多余字符
JObject SearchResult = JObject.Parse(SearchString);//解析搜索結(jié)果
JArray SongList = (JArray)SearchResult["data"]["song"]["list"];//搜索結(jié)果曲目列表
int ID = SongList[0]["id"].ToObject<int>();//從曲目列表得到歌曲唯一id(默認(rèn)首選)
var LyricsUrl = String.Format("http://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?nobase64=1&musicid={0}&callback=jsonp1&g_tk=5381&jsonpCallback=jsonp1&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0", ID.ToString());
var Lyrequest = (HttpWebRequest)WebRequest.Create(LyricsUrl);
Lyrequest.Referer = "https://y.qq.com/";//QQ音樂查詢歌詞必帶
var Lyresponse = (HttpWebResponse)Lyrequest.GetResponse();
var LyricsRawString = new StreamReader(Lyresponse.GetResponseStream()).ReadToEnd();
LyricsRawString = LyricsRawString.Replace("jsonp1(", "");
LyricsRawString = LyricsRawString.Replace("})", "}");//刪除回調(diào)中的多余字符
JObject LyricsResult = JObject.Parse(LyricsRawString);//解析得到的JSON
int Lycode = LyricsResult["retcode"].ToObject<int>();//判斷是否存在歌詞
if(Lycode != 0)
{
return null;
}
else
{
string LyricsString = LyricsResult["lyric"].ToObject<string>();//解析JSON中的歌詞
LyricsString = HttpUtility.HtmlDecode(LyricsString);
return LyricsString;
}
}
很簡短的代碼噢,為了解析JSON額外引入了 Newtonsoft.Json 這個(gè)庫。只要搞懂了下面這個(gè)QQ音樂API的解析,代碼的邏輯就很明顯啦。
QQ音樂API分析
使用的是QQ音樂網(wǎng)頁版的API。通過使用Fiddler抓包可以看到,搜索歌曲的時(shí)候調(diào)用的是
http://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w={關(guān)鍵字}&g_tk=5381&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0
返回的結(jié)構(gòu)大概是這樣的:
Callback({
json
})
對(duì)回調(diào)中的json進(jìn)行解析,可以得到類似的結(jié)構(gòu)

候選歌曲的列表在data-song-list這個(gè)列表,list中的每一個(gè)item都是這樣的結(jié)構(gòu)

通過這些數(shù)據(jù),我們可以做進(jìn)一步的校驗(yàn),判斷這個(gè)item是不是我們所需的音樂;而獲取對(duì)應(yīng)歌詞的關(guān)鍵是其中的"id"字段,接下來要通過歌曲id請(qǐng)求歌詞。
請(qǐng)求歌詞的地址是
http://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?nobase64=1&musicid={歌曲id}&callback=jsonp1&g_tk=5381&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0
請(qǐng)求的時(shí)候 Refer 必須為https://y.qq.com/,返回的數(shù)據(jù)類似這樣:
Callback({
json
})
解析其中的json,"lyric"字段就是我們所需的歌詞(經(jīng)過HtmlEncode)。于是通過HtmlDecode()方法即可得到最終的歌詞。