首先,通过分析酷狗在线音乐的报文,可以找到它的LRC歌词。
然后,查看它的调用堆栈,可以找到发起该请求的JS源码。

去掉报文前缀,其实它的内部就是一个JSON

代码运行结果

<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<style>
* {margin: 0;padding: 0;
}
.container {display: flex;
}
.lrc-container {overflow-x: hidden;border: 1px solid black;
}
.lrc-panel {width: 30rem;height: 22rem;line-height: 250%;display: inline-block;overflow-y: scroll;box-sizing: border-box;
}
.lrc-panel>div {text-align: center;
}
.play-over {color: blue;
}
#QQAudio, #KugouAudio {width: 100%;
}
#KugouAudio {display: none;
}
</style>
<script>
//心跳-王心语(酷狗lrc格式)
const response1 = `jQuery191017512709795911285_1543801309287({"status":1,"err_code":0,"data":{"hash":"AE2F1C6F855C8A670D2B6DDCD19AA805","timelength":239000,"filesize":3839115,"audio_name":"\u90d1\u5408\u60e0\u5b50 - \u5411\u4f60\u5954\u8dd1","have_album":1,"album_name":"\u5411\u4f60\u5954\u8dd1","album_id":"2017710","img":"http:\/\/imge.kugou.com\/stdmusic\/20170419\/20170419190138997417.jpg","have_mv":1,"video_id":"616926","author_name":"\u90d1\u5408\u60e0\u5b50","song_name":"\u5411\u4f60\u5954\u8dd1","lyrics":"[00:00.20]\u60e0\u5b50 - \u5411\u4f60\u5954\u8dd1\r\n[00:01.41]\u4f5c\u8bcd:\u79cb\u6c34\r\n[00:02.27]\u4f5c\u66f2:\u795e\u9a6c\u5c0f\u58ee\r\n[00:22.28]\u8d70\u8fc7\u90a3\u8857\u89d2\r\n[00:24.36]\u4f3c\u4e4e\u8fd8\u662f\u90a3\u719f\u6089\u7684\u5473\u9053\r\n[00:30.98]\u95ea\u70c1\u7684\u706f\u5149\r\n[00:33.21]\u76ee\u7779\u7740\u6211\u90a3\u4ec5\u5b58\u7684\u9a84\u50b2\r\n[00:39.14]\u970e\u90a3\u95f4\u7684\u9519\u89c9\r\n[00:41.44]\u524d\u9762\u8fd8\u662f\u4f60\u5ba0\u6eba\u7684\u5fae\u7b11\r\n[00:47.04]\u6211\u60f3\u5b66\u4f1a\u5954\u8dd1\r\n[00:49.83]\u5c31\u53ef\u4ee5\u8df3\u8fdb\u4f60\u7684\u6000\u62b1\r\n[00:57.31]\u5b64\u72ec\u7684\u8857\u9053\r\n[00:59.44]\u604d\u60da\u662f\u4f60\u7275\u6211\u624b\u7684\u70ed\u95f9\r\n[01:05.91]\u6a21\u7cca\u7684\u53cc\u773c\r\n[01:08.08]\u8033\u8fb9\u662f\u4f60\u5531\u60c5\u6b4c\u7684\u66f2\u8c03\r\n[01:14.01]\u6211\u548c\u6e05\u98ce\u4f4e\u5583\r\n[01:16.54]\u53ef\u5426\u7a0d\u53bb\u6211\u6700\u771f\u7684\u601d\u5ff5\r\n[01:22.05]\u6211\u548c\u65f6\u95f4\u8d5b\u8dd1\r\n[01:24.98]\u6015\u4f60\u56de\u5934\u65f6\u770b\u6211\u4e0d\u5230\r\n[01:30.34]\u6df1\u7231\u6211\u7684\u4eba\u548c\u6211\u7231\u7684\u4eba\r\n[01:34.53]\u5230\u4e86\u6700\u540e\u7ec8\u7a76\u54ea\u4e00\u4e2a\r\n[01:36.78]\u4f1a\u66f4\u91cd\u8981\r\n[01:39.20]\u90a3\u4e00\u79cd\u65b9\u5f0f\r\n[01:41.33]\u8ba9\u6211\u6289\u62e9\r\n[01:43.19]\u5176\u5b9e\u5e76\u4e0d\u53ef\u9760\r\n[01:48.05]\u6b64\u65f6\u7684\u6b64\u523b\r\n[01:50.12]\u53ea\u60f3\u8eab\u65c1\u6709\u4f60\r\n[01:51.99]\u9759\u9759\u7684\u966a\u7740\u6211\r\n[01:53.47]\u4e00\u8d77\u5929\u8352\u5730\u8001\r\n[01:57.06]\u4e0d\u77e5\u9053\r\n[01:57.70]\u8fd9\u6837\u7684\u8868\u767d\r\n[02:01.01]\u4f1a\u4e0d\u4f1a\u592a\u65e9\r\n[02:24.55]\u5b64\u72ec\u7684\u8857\u9053\r\n[02:26.75]\u604d\u60da\u662f\u4f60\u7275\u6211\u624b\u7684\u70ed\u95f9\r\n[02:33.33]\u6a21\u7cca\u7684\u53cc\u773c\r\n[02:35.50]\u8033\u8fb9\u662f\u4f60\u5531\u60c5\u6b4c\u7684\u66f2\u8c03\r\n[02:41.53]\u6211\u548c\u6e05\u98ce\u4f4e\u5583\r\n[02:43.68]\u53ef\u5426\u7a0d\u53bb\u6211\u6700\u771f\u7684\u601d\u5ff5\r\n[02:49.21]\u6211\u548c\u65f6\u95f4\u8d5b\u8dd1\r\n[02:52.30]\u6015\u4f60\u56de\u5934\u65f6\u770b\u6211\u4e0d\u5230\r\n[02:57.71]\u6df1\u7231\u6211\u7684\u4eba\u548c\u6211\u7231\u7684\u4eba\r\n[03:01.66]\u5230\u4e86\u6700\u540e\u7ec8\u7a76\u54ea\u4e00\u4e2a\r\n[03:04.08]\u4f1a\u66f4\u91cd\u8981\r\n[03:06.41]\u90a3\u4e00\u79cd\u65b9\u5f0f\r\n[03:08.58]\u8ba9\u6211\u6289\u62e9\r\n[03:10.35]\u5176\u5b9e\u5e76\u4e0d\u53ef\u9760\r\n[03:15.26]\u6b64\u65f6\u7684\u6b64\u523b\r\n[03:17.19]\u53ea\u60f3\u8eab\u65c1\u6709\u4f60\r\n[03:19.32]\u9759\u9759\u7684\u966a\u7740\u6211\r\n[03:20.70]\u4e00\u8d77\u5929\u8352\u5730\u8001\r\n[03:24.29]\u4e0d\u77e5\u9053\r\n[03:25.14]\u8fd9\u6837\u7684\u8868\u767d\r\n[03:28.38]\u4f1a\u4e0d\u4f1a\u592a\u65e9\r\n[03:33.16]\u6211\u7684\u5c0f\u5c0f\u613f\u671b\r\n[03:35.79]\u5c31\u662f\u548c\u4f60\u6162\u6162\u53d8\u8001\r\n","author_id":"669356","privilege":0,"privilege2":"0","play_url":"http:\/\/fs.w.kugou.com\/201812031036\/ee33f53d08cda71a6d64a940a1a878e6\/G095\/M0A\/13\/1F\/P5QEAFj3Q6GAIywPADqUi71UxSw776.mp3","authors":[{"is_publish":"1","author_id":"669356","avatar":"20170421150041803.jpg","author_name":"\u90d1\u5408\u60e0\u5b50"}],"bitrate":127}});
`;
//体面-于文文(酷狗lrc格式)
const response2 = `jQuery19103209198362507233_1543889299163({"status":1,"err_code":0,"data":{"hash":"238B786A3F93C42E3D212953E1CE96C3","timelength":282080,"filesize":4525288,"audio_name":"\u4e8e\u6587\u6587 - \u4f53\u9762","have_album":1,"album_name":"\u4f53\u9762","album_id":"8149034","img":"http:\/\/imge.kugou.com\/stdmusic\/20171221\/20171221090821129644.jpg","have_mv":1,"video_id":"636232","author_name":"\u4e8e\u6587\u6587","song_name":"\u4f53\u9762","lyrics":"[00:00.56]\u4e8e\u6587\u6587 - \u4f53\u9762\r\n[00:01.88]\u4f5c\u8bcd\uff1a\u5510\u606c\r\n[00:02.94]\u4f5c\u66f2\uff1a\u4e8e\u6587\u6587\r\n[00:05.97]\u7f16\u66f2\uff1a\u90d1\u6960\r\n[00:07.60]\u5236\u4f5c\u4eba\uff1a\u90d1\u6960\r\n[00:08.80]\u548c\u58f0\u7f16\u5199\uff1a\u4e8e\u6587\u6587\r\n[00:24.12]\u522b\u5806\u780c\u6000\u5ff5\u8ba9\u5267\u60c5\u53d8\u5f97\u72d7\u8840\r\n[00:35.43]\u6df1\u7231\u4e86\u591a\u5e74\u53c8\u4f55\u5fc5\u6bc1\u4e86\u7ecf\u5178\r\n[00:44.26]\u90fd\u5df2\u6210\u5e74\u4e0d\u62d6\u4e0d\u6b20\r\n[00:49.97]\u6d6a\u8d39\u65f6\u95f4\u662f\u6211\u60c5\u613f\r\n[00:55.61]\u50cf\u8c22\u5e55\u7684\u6f14\u5458\r\n[00:59.06]\u773c\u770b\u7740\u706f\u5149\u7184\u706d\r\n[01:06.84]\u6765\u4e0d\u53ca\u518d\u8f70\u8f70\u70c8\u70c8\r\n[01:12.50]\u5c31\u4fdd\u7559\u544a\u522b\u7684\u5c0a\u4e25\r\n[01:18.17]\u6211\u7231\u4f60\u4e0d\u540e\u6094\r\n[01:21.66]\u4e5f\u5c0a\u91cd\u6545\u4e8b\u7ed3\u5c3e\r\n[01:29.38]\u5206\u624b\u5e94\u8be5\u4f53\u9762\r\n[01:32.66]\u8c01\u90fd\u4e0d\u8981\u8bf4\u62b1\u6b49\r\n[01:36.50]\u4f55\u6765\u4e8f\u6b20\r\n[01:38.28]\u6211\u6562\u7ed9\u5c31\u6562\u5fc3\u788e\r\n[01:42.17]\u955c\u5934\u524d\u9762\u662f\r\n[01:44.15]\u4ece\u524d\u7684\u6211\u4eec\u5728\u559d\u5f69\r\n[01:48.32]\u6d41\u7740\u6cea\u58f0\u5636\u529b\u7aed\r\n[01:52.02]\u79bb\u5f00\u4e5f\u5f88\u4f53\u9762\r\n[01:55.11]\u624d\u6ca1\u8f9c\u8d1f\u8fd9\u4e9b\u5e74\r\n[01:59.02]\u7231\u5f97\u70ed\u70c8\r\n[02:00.85]\u8ba4\u771f\u4ed8\u51fa\u7684\u753b\u9762\r\n[02:04.68]\u522b\u8ba9\u6267\u5ff5\u6bc1\u6389\u4e86\u6628\u5929\r\n[02:09.29]\u6211\u7231\u8fc7\u4f60\u5229\u843d\u5e72\u8106\r\n[02:36.85]\u6700\u719f\u6089\u7684\u8857\u4e3b\u89d2\u5374\u6362\u4e86\u4eba\u6f14\r\n[02:48.16]\u6211\u54ed\u5230\u54fd\u54bd\r\n[02:50.09]\u5fc3\u518d\u75db\u5c31\u5f53\u7834\u8327\r\n[02:57.02]\u6765\u4e0d\u53ca\u518d\u8f70\u8f70\u70c8\u70c8\r\n[03:02.58]\u5c31\u4fdd\u7559\u544a\u522b\u7684\u5c0a\u4e25\r\n[03:08.22]\u6211\u7231\u4f60\u4e0d\u540e\u6094\r\n[03:11.96]\u4e5f\u5c0a\u91cd\u6545\u4e8b\u7ed3\u5c3e\r\n[03:19.55]\u5206\u624b\u5e94\u8be5\u4f53\u9762\r\n[03:22.68]\u8c01\u90fd\u4e0d\u8981\u8bf4\u62b1\u6b49\r\n[03:26.57]\u4f55\u6765\u4e8f\u6b20\r\n[03:28.28]\u6211\u6562\u7ed9\u5c31\u6562\u5fc3\u788e\r\n[03:32.33]\u955c\u5934\u524d\u9762\u662f\r\n[03:34.46]\u4ece\u524d\u7684\u6211\u4eec\u5728\u559d\u5f69\r\n[03:38.44]\u6d41\u7740\u6cea\u58f0\u5636\u529b\u7aed\r\n[03:41.99]\u79bb\u5f00\u4e5f\u5f88\u4f53\u9762\r\n[03:45.33]\u624d\u6ca1\u8f9c\u8d1f\u8fd9\u4e9b\u5e74\u7231\u5f97\u70ed\u70c8\r\n[03:51.04]\u8ba4\u771f\u4ed8\u51fa\u7684\u753b\u9762\r\n[03:54.78]\u522b\u8ba9\u6267\u5ff5\u6bc1\u6389\u4e86\u6628\u5929\r\n[03:59.46]\u6211\u7231\u8fc7\u4f60\u5229\u843d\u5e72\u8106\r\n[04:05.44]\u518d\u89c1\u4e0d\u8d1f\u9047\u89c1\r\n","author_id":"86820","privilege":8,"privilege2":"1000","play_url":"http:\/\/fs.w.kugou.com\/201812040959\/4db465946beab6c09ed897827d768ef4\/G123\/M09\/1E\/13\/uw0DAFo7CmOAckvsAEUM6BGXWvo816.mp3","authors":[{"is_publish":"1","author_id":"86820","avatar":"20180920194639307.jpg","author_name":"\u4e8e\u6587\u6587"}],"bitrate":128}});`;//百度百科LRC标准格式
const response3 = `
[ti:依赖] ——ti.=title, 标题,即歌曲名
[ar:蔡健雅] ——ar.=artist,艺术家,即歌手名
[al:MY SPACE] ——al.=album,专辑,即歌曲被收录的专辑
[by:Chapter Chang] ——by somebody,即LRC歌词文件的制作者
[offset:0] ——补偿时值。500=0.5秒,正负值分别提前和延长相应的时间(其值多为500的倍数)
[00:00.50]蔡健雅 - 依赖
[00:07.94]词、曲:蔡健雅、陶晶莹
[00:11.60]关了灯把房间整理好
[00:15.48]凌晨三点还是睡不著
[00:19.64]你应该是不在 所以把电话挂掉
[00:30.39]在黑暗手表跟着心跳
[00:34.57]怎么慢它停也停不了
[00:39.70]我应该只是心情不好
[00:45.00]那又怎样
[00:48.50]但本来是这样
[01:21.36]朋友们对我的安慰
[01:25.20]都是同样的一个话题
[01:29.73]我一定要变得更坚强
[01:34.68]说很简单
[00:38.50]但是做却很难
[00:53.00][01:43.88][02:11.23]虽然无所谓写在脸上
[00:58.21][01:48.44][02:15.79]我还是舍不得让你离开
[01:02.97][01:53.50][02:20.60]虽然闭着眼假装听不到
[01:07.84][01:58.23][02:25.11][02:33.15]你对爱 已不再 想依赖
`;class MediaPlayer {getKugouData(response) {//JSON.parse转json字符串时遇到一些特殊字符需要先转义response = response.replace(/\r\n/g, "\\r\\n");const data = response.match(/\{.+\}/m);const jsonData = JSON.parse(data);return jsonData.data;}parseKugouLrc(response) {const data = this.getKugouData(response);const lrc = this.parseLrc(data.lyrics);lrc.ti = data.song_name;lrc.ar = data.author_name;return lrc;}parseLrc(data) {let result = { lyrics: new Array() };//箭号表达式的this指向它父对象的上下文,如果要用到arguments的话就不能用箭头表达式data.split(/\r\n|\n/).forEach((line)=>{//过滤掉空行,\s匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]if(!/^\s*$/.test(line)) {       const arr = line.split("]");for(let i = 0; i < arr.length; i++) {if(arr[i].indexOf("ti") != -1) {//ti.=title, 标题,即歌曲名result.ti = arr[i].substr(1);break;} else if(arr[i].indexOf("ar") != -1) {//ar.=artist,艺术家,即歌手名result.ar = arr[i].substr(1);break;} else if(arr[i].indexOf("al") != -1) {//al.=album,专辑,即歌曲被收录的专辑result.al = arr[i].substr(1);break;} else if(arr[i].indexOf("by") != -1) {//by somebody,即LRC歌词文件的制作者result.by = arr[i].substr(1);break;} else if(arr[i].indexOf("offset") != -1) {//补偿时值。500=0.5秒,正负值分别提前和延长相应的时间(其值多为500的倍数)result.offset = arr[i].substr(1);break;} else if(arr[i].indexOf("[") == 0) {//两种情况“[mm:ss]”或“[mm:ss.ff]”(分钟数:秒数.百分之一秒数),这里需要把它们统一转换为毫秒//string.substr(start [, length ])//string.substring(start, end)const mm = parseInt(arr[i].substr(1, 2));const ss = parseFloat(arr[i].substr(4));const time = mm * 60 + ss;const lrc = arr[arr.length-1];if(lrc.indexOf("[" == -1)) result.lyrics.push([time, lrc]);else  result.lyrics.push([time]);} else {//歌词}}}});result.lyrics.sort((a,b)=>{return a[0] - b[0];});return result;}constructor (responseLrc) {this.lyrics = this.parseKugouLrc(responseLrc);this.index = -1;this.lrcPanel = document.getElementsByClassName("lrc-panel")[0];this.fraction = 0.5; //当前歌词的基准线this.audio = document.getElementById("QQAudio");}init () {this.lrcPanel.innerHTML = "";//使用父布局来隐藏子元素的滚动条const container = document.getElementsByClassName("lrc-container")[0];//offsetWidth:获取到的值是width+padding+border;//clientWidth: 获取对象可见内容的宽度,不包括滚动条,不包括边框;container.style.width = this.lrcPanel.clientWidth - 8 + "px";this.lyrics.lyrics.forEach((lrc)=>{const div = document.createElement("div");div.innerText = lrc[1];this.lrcPanel.appendChild(div);});//通过设置padding,将当前歌词定位于基准线上const panelHeight = this.lrcPanel.clientHeight;const childHalfHeight = this.lrcPanel.firstChild.offsetHeight / 2;this.fractionTop = panelHeight * this.fraction - childHalfHeight;this.lrcPanel.style.paddingTop = this.fractionTop + "px";this.lrcPanel.style.paddingBottom = panelHeight * (1-this.fraction) - childHalfHeight + "px";/*最简单的方法是当时间改变的时候做判断但是存在很大的优化空间,比如通常index会出现在下一位,没必要全部比较。这里呈现的只是最简单的lrc格式,qrc(腾讯)和krc(酷狗)都能精确到字,如果每次都逐个比较会消耗很多CPU资源但是涉及到状态机又比较麻烦,需要记录onSeeked,用audio自带的control不太好弄,用自己的seekbar倒是方便记录状态*/this.audio.ontimeupdate=()=>{if(this.audio.ended){return;}let reachIndex = -2;let offset = 0;if(this.lyrics.offset != undefined) this.lyrics.offset / 1000;const len = this.lyrics.lyrics.length;const children = this.lrcPanel.children;for(let i=0; i<len; i++) {//duration 歌曲总时长,以秒计数,浮点型。currentTime 当前时间if(this.audio.currentTime < this.lyrics.lyrics[i][0]) {reachIndex = i - 1;break;}};if(reachIndex == -2) reachIndex = len - 1;if(reachIndex != this.index) {this.index = reachIndex;for(let i=0; i<children.length; i++) {if(i == reachIndex) children[i].className = "play-over";else children[i].removeAttribute("class");}this.lrcPanel.scrollTo(0, children[reachIndex < 0 ? 0 : reachIndex].offsetTop - this.fractionTop);}};let title = this.lyrics.ti + "_" + this.lyrics.ar + "_";setInterval(()=>{document.title = title;title = title.substr(1) + title.charAt(0);}, 1000);}
}window.onload = ()=>{const player = new MediaPlayer(response2);player.init();
};/*
这里是对纯前端跨域访问的尝试,很不幸
首先酷狗不支持跨域访问。
其次,尝试过通过酷狗的JS用JSONP来获取,但是由于它的内部混淆了,然后报了一些错,而且时间不允许,就没接下去做了不过本次失败的经验告诉大家,纯前端想跨域访问是不可能的,还是靠后端吧。fetch用来取代ajax,下面展示了fetch的两种写法//这是es6的async/await语法的fetch
async function fetchLrc() {const url = "http://www.kugou.com/yy/index.php?r=play/getdata&hash=CB7EE97F4CC11C4EA7A1FA4B516A5D97";const header = new Headers({
//      'Accept': '* /*',
//      'Accept-Encoding': 'gzip, deflate, br',
//      'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
//      'Connection': 'keep-alive',
//      'Cookie': 'kg_mid=64cd73a46bbf114fc40a917…62f509129360d6bb3d=1543801310',
//      'Host': 'wwwapi.kugou.com',
//      'Referer': 'http://www.kugou.com/song/fh5rj81.html?frombaidu?frombaidu',
//      'TE': 'Trailers',
//      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/63.0',});const option = {method: 'GET',mode: 'cors',            //请求的模式,主要用于跨域设置headers: header,credentials: "include",    //是否发送Cookie omit, same-origin}//const response = await fetch(url, option);const response = fetch("https://www.baidu.com");console.log(response);if(response.code == 200) {const data = await response.json();document.write(data);}
}//这是基于promise语法的fetch
fetch('http://www.kugou.com/yy/index.php?r=play/getdata&hash=CB7EE97F4CC11C4EA7A1FA4B516A5D97', {mode: 'cors'}).then(response => response.json()).then(data => {console.log(data)});
*/
</script>
</head>
<body>
<div class="container"><div class="lrc-container"><div class="lrc-panel"></div><!--autoplay 如果出现该属性,则音频在就绪后马上播放。controls 如果出现该属性,则向用户显示控件,比如播放按钮。loop      如果出现该属性,则每当音频结束时重新开始播放。preload       如果出现该属性,则音频在页面加载时进行加载,并预备播放。如果使用 "autoplay",则忽略该属性。src       要播放的音频的 URL。--><!-- QQ --><audio id="QQAudio" autoplay="false" loop controls src="http://isure.stream.qqmusic.qq.com/C400000Md1wq0vnwzE.m4a?guid=4355126464&amp;vkey=14B628F0C84C04446DDF79BDDAD479694510C6F7CF7CAC545D7564E50C6E5A0B073DDE8BB6456C019145D9F0A36FA5B22B7901E36B7139E1&amp;uin=0&amp;fromtag=66"><source src="http://isure.stream.qqmusic.qq.com/C400000Md1wq0vnwzE.m4a?guid=4355126464&amp;vkey=14B628F0C84C04446DDF79BDDAD479694510C6F7CF7CAC545D7564E50C6E5A0B073DDE8BB6456C019145D9F0A36FA5B22B7901E36B7139E1&amp;uin=0&amp;fromtag=66"><p class="myAudiohide">你的浏览器不支持<code>audio</code>标签.</p></audio><!-- 酷狗 --><audio id="KugouAudio" src="http://fs.w.kugou.com/201812040959/4db465946beab6c09ed897827d768ef4/G123/M09/1E/13/uw0DAFo7CmOAckvsAEUM6BGXWvo816.mp3" preload="auto"><p class="myAudiohide">你的浏览器不支持<code>audio</code>标签.</p></audio></div>
</div>
</body>
</html>

JavaScrpt LRC歌词同步 和 es6 的 fetch 的 async/await 和 promise 两种写法相关推荐

  1. html+js的lrc歌词同步播放器

    <html> <head> <title>lrc歌词同步播放器</title> <style> body, td { font-family ...

  2. Android自定义View来实现解析lrc歌词同步滚动、上下拖动、缩放歌词等功能

    http://blog.csdn.net/ouyang_peng/article/details/50813419 前言 一LRC歌词文件简介 1什么是LRC歌词文件 2LRC歌词文件的格式 LRC歌 ...

  3. js解析lrc 实现lrc歌词同步滚动效果

    这两天想着做一个h5的网页播放器,实现歌词同步滚动 但是上网找了很多资料,竟发现没有比较完善的代码供参考,但是无意间看到了百度的千千音乐有这样的效果,就想着一定能通过js实现 经过两三天的努力,终于做 ...

  4. 网页中LRC歌词同步显示

    <html><head> <title>音乐歌词同步测试</title> <style> <!-- .div { width:460p ...

  5. android 本地lrc 歌词同步,android 音乐播放器-------歌词同步 lrc

    lrc格式 : [al:这首歌所在的唱片集 ] [ar:歌词作者 ] [by:本LRC文件的创建者 ] [offset:+/- 以毫秒为单位整体时间戳调整,+增加,-减小 ] [re:创建此LRC文件 ...

  6. Android中解析lrc歌词 同步歌曲

    </pre><pre name="code" class="java">//歌词解析类 public class LrcParser { ...

  7. 论HTML5 Audio 标签歌词同步的实现

    HTML5草案里面其实有原生的字幕标签(<track> Tag)的,但使用的是vtt格式的文件,非常规的字幕(.sub, .srt)或歌词文件(.lrc). 用法如下(代码来自W3Scho ...

  8. MP3制作之LRC歌词文件解析(附:源代码)

    LRC 歌词同步 一.准备工作   既然要制作歌词同步程序,首先要准备一首歌,我们就以"周杰伦-青花瓷"为例.首先要下载这首"青花瓷.mp3",保存为" ...

  9. android 歌词同步 换行,HTML5音乐播放器同步显示歌词

    歌词文件的格式 实现之前,当然得了解一下歌词文件的格式了.常规歌词文件的格式基本是一句一行,每行由两部分组成,前面是中括号括起来的时间轴,后面紧跟歌词,像下面这样:[ti:记兰生襄铃] [ar:HIT ...

  10. es6 --- promise和async/await的区别

    首先需要了解async函数: async是Generator函数的语法糖: // 使用Generator依次读取两个文件 var fs = require('fs'); var readFile = ...

最新文章

  1. 021Python路--单例设计模式
  2. 汇编:SF符号标志位
  3. OpenCV 掩膜的应用
  4. 微信摇一摇插件ios_微信开发平台 Jeewx-Boot
  5. 为什么说任何基于比较的算法将 5 个元素排序都需要 7 次?
  6. 平板电脑可以开发php吗,PHP代码判断设备是手机还是平板电脑(两种方法)
  7. echarts formatter_牛X!用 Echarts 打造一个轮播图!
  8. c 读取mysql另一个窗体中显示出来_二级ACCESS数据库4窗体的笔试题考点分析
  9. Red Hat 6.5 版本虚拟机安装
  10. php中mysql的增删_PHP MySql增删改查的简单实例
  11. 代码结构中Dao,Service,Controller,Util,Model意思和划分
  12. AcWing 1762. 牛的洗牌(暴力)
  13. 浏览器原理学习笔记1-浏览器进程
  14. Android抓包思想总结
  15. html实现分级目录线,jQuery 实现支持分级标题标签的文章目录
  16. 各大著名汽车标志图 来历
  17. 工业相机镜头的参数与选型
  18. 使用muscle进行多序列比对
  19. JAVA编写Word
  20. 利用Cam对Hopenet网络模型进行可视化

热门文章

  1. 教妹学 Java:晦涩难懂的泛型
  2. 【180719】疯狂躲避球源代码
  3. android 电子签名设备,Android 电子签名制作
  4. 第三方平台代微信公众号开发
  5. python自动化测试课程学费一般多少 学习方式不同,价格也会存在差异
  6. Proximal Algorithms 1 介绍
  7. 多元微积分_旋度1.正负0旋度
  8. VBA学习笔记4:将同一文件下的多个工作簿的数据汇总为一个工作表
  9. TP-link二级路由器配置
  10. 路由器做二级路由方法