摘要:每次用網易云音樂客戶端播放聽歌的時候,收藏的歌曲,在我的博客上也可以同步進行更新。
最近應該發現,我的博客https://blog.codelabo.cn左下角多了一個音樂播放器
這個是怎么實現的?一起來看看吧
APlayer首先我們需要一個音頻播放器,這里我用到了APlayer,這是由bilibili前端大神DIYgod開源的播放器,有興趣的可以去TA的主頁看看,非常驚艷,這里我就不多說了
我們看一下APlayer的官方文檔,方法很簡單
const ap = new APlayer({ container: document.getElementById("aplayer"), audio: [{ name: "name", artist: "artist", url: "url.mp3", cover: "cover.jpg" }] });
這里的audio是一個音頻列表,可以是一個對象或對象數組
對象具體的參數如下
名稱 | 描述 |
---|---|
name | 音頻名稱 |
artist | 音頻藝術家 |
url | 音頻鏈接 |
cover | 音頻封面 |
lrc | 音頻歌詞 |
LRC一共有三種方式來給 APlayer 傳遞歌詞,詳情可參考https://aplayer.js.org/#/home?id=lrc,
這里我們選擇最方便的一種,直接給LRC鏈接
網易云音樂API這部分我找到了網上有人分享的API,這種官方不可能給公開API,所以還是要小心使用,說不定哪天就被修改了
http://moonlib.com/606.html
我們現在其實想要兩個,一個是歌單的列表,還有一個是歌詞。
# 歌單 https://music.163.com/api/playlist/detail?id=37880978
id為歌單ID
# 歌詞 https://music.163.com/api/song/lyric?os=pc&id=93920&lv=-1&kv=-1&tv=-1
id為歌曲ID接口實現
lv:值為-1,我猜測應該是判斷是否搜索lyric格式
kv:值為-1,這個值貌似并不影響結果,意義不明
tv:值為-1,是否搜索tlyric格式
雖然我們已經找到了網易云音樂API,但是返回的數據不是我們所需要的呀
比如這個歌單的接口
# Request https://music.163.com/api/playlist/detail?id=2119983629 # Response { "result":{ "subscribers":[], "subscribed": false, "creator":{...}, "artists": null, "tracks":[ { album: { name: "メトロノーム", id: 36787278, type: "專輯", size: 12, picId:18419018788768520, } alias: [], artists: [{name: "MACO", id: 901025, picId: 0, img1v1Id: 0, briefDesc: "",…}], audition: null, bMusic: {...}, commentThreadId: "R_SO_4_515573221", copyFrom: "", copyright: 1, copyrightId: 7003, crbt: null, ... } ] } }
里面字段很多,我上面只列舉了一部分,tracks就是歌單列表,但是很顯然,和我們需要的格式還差很多
那么怎么來轉換一下,變成我們需要的數據格式呢?
[{ name: "name", artist: "artist", url: "url.mp3", cover: "cover.jpg", lrc: "a.lrc" }]
這里我們就需要在服務端來完成了,思路很簡單,在服務器上請求https://music.163.com/api/playlist/detail?id=2119983629這個接口,然后拿到結果后手動處理一下,最后再返給客戶端,相當于做了一次中轉
我這里服務端是用koa實現的,其他框架應該差不多服務端發起請求
在服務端發起請求也可以用我們熟悉的fetch,不過你需要先安裝node-fetch這個庫
yarn add node-fetch
然后你就可以像前端一樣發起請求了
const fetch = require("node-fetch"); //... const getPlayList = (id) => { return fetch(`http://music.163.com/api/playlist/detail?id=${id}`) .then((response) => { if (response.ok) { return response.json(); } }) .catch((err) => { console.warn(err); }) }接口定義
現在我們需要新增一個接口用來處理歌單,返回出我們需要的格式
//獲取音樂列表 router.get("/playlist/:id", async (ctx, next) => { const responseData = { "success": false, "data":[], "message": "", } const { id } = ctx.params; try { const data = await getPlayList(id); if(data.code===200){ const playList = data.result.tracks.map(item=>({ id: item.id, name: item.name, artist: item.artists.map(el=>el.name).join(","),//由于歌手是一個數組,這里我們把它轉換成字符串拼接 url: `https://music.163.com/song/media/outer/url?id=${item.id}.mp3`,//歌曲地址 cover: item.album.picUrl.replace(/http:/,"https:"), lrc:null })) responseData.success = true; responseData.message = "操作成功"; responseData.data = playList; ctx.body = responseData; } } catch (error) { responseData.success = false; responseData.message = error.message; responseData.data = []; ctx.body = responseData; } });
注意這里的歌曲鏈接url,本來返回信息里面是不包含的,只有歌曲ID,不過我們發現通過https://music.163.com/song/media/outer/url?id=ID可以直接在線播放指定ID的歌曲,所以我們這里直接寫在返回結果上。
歌詞處理還有一個問題就是歌詞,上面的接口中,歌詞返回結果也不是我們需要的格式
# Request https://music.163.com/api/song/lyric?os=pc&id=93920&lv=-1&kv=-1&tv=-1 # Response { "sgc": true, "sfy": false, "qfy": false, "lrc": { "version": 7, "lyric": "[00:29.620]細雨帶風濕透黃昏的街道 [00:35.050]抹去雨水雙眼無幫地仰望 [00:40.240]望向孤單的晚燈是那傷感的記憶 [00:48.630]再次泛起心里無數的思念 [00:54.000]以往片刻歡笑仍掛在臉上 [00:58.770]愿你此刻可會知是我衷心的說聲 [01:06.310]喜歡你 [01:08.940]那雙眼動人笑聲更迷人 [01:14.330]愿再可輕撫你那可愛面容 [01:22.490]挽手說夢話象昨天你共我 [01:42.970]滿帶理想的我曾經多沖動 [01:48.340]埋怨與她相愛難有自由 [01:53.040]愿你此刻可會知是我衷心的說聲 [02:00.420]喜歡你 [02:03.230]那雙眼動人笑聲更迷人 [02:08.540]愿再可輕撫你那可愛面容 [02:16.750]挽手說夢話象昨天你共我 [02:24.740]每晚夜里自我獨行 [02:27.670]隨處蕩 多冰冷 [02:35.070]以往為了自我掙扎從不知她的痛苦 [02:49.380]喜歡你 [02:52.020]那雙眼動人笑聲更迷人 [02:57.420]愿再可輕撫你那可愛面容 [03:05.590]挽手說夢話象昨天你共我 [03:13.870]挽手說夢話象昨天你共我 " }, "klyric": {...}, "code": 200 }
反正就是很全面,但是我們需要的僅僅是里面的內容部分,比如上面我就只需要這一段
[00:29.620]細雨帶風濕透黃昏的街道 [00:35.050]抹去雨水雙眼無幫地仰望 [00:40.240]望向孤單的晚燈是那傷感的記憶 [00:48.630]再次泛起心里無數的思念 [00:54.000]以往片刻歡笑仍掛在臉上 [00:58.770]愿你此刻可會知是我衷心的說聲 ...
所以我們需要再次做一個中介處理
const getLyric = (id) => { return fetch(`http://music.163.com/api/song/lyric?os=pc&id=${id}&lv=-1&kv=-1&tv=-1`) .then((response) => { if (response.ok) { return response.json(); } }) .catch((err) => { console.warn(err); }) } //獲取音樂歌詞 router.get("/lyric/:id", async (ctx, next) => { const { id } = ctx.params; try { const lyric = await getLyric(id); ctx.body = lyric.lrc.lyric;//返回指定部分 } catch (error) { ctx.body = ""; } });
這樣在上面歌詞列表中就可以直接用/api/lyric/:ID來獲取歌詞了
//... { id: item.id, name: item.name, artist: item.artists.map(el=>el.name).join(","), url: `https://music.163.com/song/media/outer/url?id=${item.id}.mp3`, cover: item.album.picUrl.replace(/http:/,"https:"), lrc:`/api/lyric/${item.id}`//這里歌詞寫上我們定義的接口地址 } //...測試一下吧
通過以上處理,我們接口就返回我們自定義的數據格式了
# Request https://localhost:3000/api/playlist/2119983629 # Response { "success": true, "data": [ { "id": 515573221, "name": "Sweet Memory", "artist": "MACO", "url": "https://music.163.com/song/media/outer/url?id=515573221.mp3", "cover": "https://p1.music.126.net/-U7mfaIjENUu8G_O0Dhv8g==/18419018788768520.jpg", "lrc": "/api/lyric/515573221" }, { "id": 488388942, "name": "願い~あの頃のキミへ~", "artist": "當山みれい", "url": "https://music.163.com/song/media/outer/url?id=488388942.mp3", "cover": "https://p1.music.126.net/kbLlBkGfEcA3RJyC5JhkDA==/18346451021830743.jpg", "lrc": "/api/lyric/488388942" }, ... ], "message": "操作成功" }添加到博客
其實上面對接口的數據改造才是關鍵,下面添加到自己的頁面就很簡單了。
如果你是傳統HTML頁面,可以直接文章開頭的方式引用
const ap = new APlayer({ container: document.getElementById("aplayer"), audio: [{ name: "name", artist: "artist", url: "url.mp3", cover: "cover.jpg" }] });
如果使用了使用模塊管理器:
import "APlayer/dist/APlayer.min.css"; import APlayer from "APlayer"; const ap = new APlayer(options);
如果是react項目,那么可以用封裝好的react-aplayer
import React from "react"; import ReactAplayer from "react-aplayer"; export default class App extends React.Component { // event binding example onPlay = () => { console.log("on play"); }; onPause = () => { console.log("on pause"); }; // example of access aplayer instance onInit = ap => { this.ap = ap; }; render() { const props = { theme: "#F57F17", lrcType: 3, audio: [ { name: "光るなら", artist: "Goose house", url: "https://moeplayer.b0.upaiyun.com/aplayer/hikarunara.mp3", cover: "https://moeplayer.b0.upaiyun.com/aplayer/hikarunara.jpg", lrc: "https://moeplayer.b0.upaiyun.com/aplayer/hikarunara.lrc", theme: "#ebd0c2" } ] }; return ({/* example of access aplayer instance API */} ); } }如果是vue項目,可以使用vue-aplayer
其他更多可以參考Aplayer生態
小節這里的歌單,我選擇了自己收藏的歌曲。每次用網易云音樂客戶端播放聽歌的時候,收藏的歌曲,在我的博客上也可以同步進行更新。
差不多就這些了,可能對于專業后端開發來說,這些完全就是小學生操作,但是對于一個前端來說,做這些事就感覺闖入了一片新天地,還是有很多感悟的。很多以前前端做不了的事,現在nodeJS也能幫我們解決,進一步打通了前后端的天然屏障,離全棧也越來越近了 ^ ^
大家如果喜歡我的博客,可以多多關注一下
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98655.html
相關文章
selenium實戰-同步網易云音樂歌單到qq音樂
摘要:對于這次的爬蟲來說,由于網易云音樂以及音樂網頁中大部分元素都是使用渲染生成的,因此選擇使用來完成這次的腳本。可以發現網易云音樂的手機版歌單地址是。現在已經支持網易云音樂與音樂歌單的互相同步。 本文主要介紹selenium在爬蟲腳本的實際應用。適合剛接觸python,沒使用過selenium的童鞋。(如果你是老司機路過的話,幫忙點個star吧) 項目地址 https://github.c...
HTML+CSS+JAVASCRIPT 高仿低配網頁版網易云音樂播放器
摘要:高仿低配網頁版網易云音樂播放器前言沒有使用任何框架,只是想用最簡單純的代碼實現下前臺后臺是參考網上的例子寫的,代碼是在的基礎上重新寫的還有她的姊妹篇網易云音樂移動端,請查看這里寫在前頭的話鄙人野生前端一只,專業,自學前端已經一年多了 HTML+CSS+JAVASCRIPT 高仿低配網頁版網易云音樂播放器 showImg(https://segmentfault.com/img/remo...
HTML+CSS+JAVASCRIPT 高仿低配網頁版網易云音樂播放器
摘要:高仿低配網頁版網易云音樂播放器前言沒有使用任何框架,只是想用最簡單純的代碼實現下前臺后臺是參考網上的例子寫的,代碼是在的基礎上重新寫的還有她的姊妹篇網易云音樂移動端,請查看這里寫在前頭的話鄙人野生前端一只,專業,自學前端已經一年多了 HTML+CSS+JAVASCRIPT 高仿低配網頁版網易云音樂播放器 showImg(https://segmentfault.com/img/remo...
Vue 實現網易云音樂 WebApp
摘要:基于等開發一款移動端音樂,界面參考了安卓版的網易云音樂布局適配常見移動端。圖標使用阿里巴巴圖標庫,中間的唱片旋轉動畫使用了實現。搜索功能實現功能搜索歌手歌單歌曲熱門搜索數據節流上拉刷新保存搜索記錄。 基于 Vue(2.5) + vuex + vue-router + vue-axios +better-scroll + Scss + ES6 等開發一款移動端音樂 WebApp,UI ...
發表評論
0條評論
閱讀 1818·2023-04-26 02:51
閱讀 2849·2021-09-10 10:50
閱讀 3026·2021-09-01 10:48
閱讀 3593·2019-08-30 15:53
閱讀 1816·2019-08-29 18:40
閱讀 405·2019-08-29 16:16
閱讀 2024·2019-08-29 13:21
閱讀 1816·2019-08-29 11:07