feat(qt): 蜻蜓FM平台接入——audiostream HMAC-MD5 签名直链、SSR 搜索/频道节目列表
This commit is contained in:
1 parent
020e9bbb2e
commit
83d3eb3b49
5 files changed
+199
No files matched your search
@@ -0,0 +1,34 @@
|
||||
// 蜻蜓FM URL 获取(点播 audiostream 签名直链)
|
||||
// 链路(官网 main.js 逆向,2026-10-02 实测):
|
||||
// GET https://audio.qtfm.cn/audiostream/redirect/<channel>/<program>?access_token=&device_id=MOBILESITE&qingting_id=&t=<ms>&sign=<hex>
|
||||
// sign = HMAC-MD5("7l8CZ)SgZgM_bkrw", path+query) —— 签名内容含完整 path 与 query(sign 自身除外)
|
||||
// 匿名空 token 即可取免费节目;响应 302 到华为云签名 CDN(vohwod-sign.qtfm.cn,m4a/mp3)
|
||||
// 直播电台另有 /live/<cid>/64k.mp3 + HMAC-MD5("Lwrpu$K5oP") 签名(lhttp-hw.qtfm.cn)
|
||||
// songmid 为复合 id "<channelId>:<programId>"(/album/qt 列表产出)
|
||||
import crypto from 'node:crypto'
|
||||
|
||||
const SIGN_KEY = '7l8CZ)SgZgM_bkrw'
|
||||
const AUDIO_HOST = 'https://audio.qtfm.cn'
|
||||
|
||||
export const supportQualitys = ['64k', '128k']
|
||||
|
||||
export const buildProgramUrl = (channelId: string, programId: string) => {
|
||||
const s = `/audiostream/redirect/${channelId}/${programId}?access_token=&device_id=MOBILESITE&qingting_id=&t=${Date.now()}`
|
||||
const sign = crypto.createHmac('md5', SIGN_KEY).update(s).digest('hex')
|
||||
return `${AUDIO_HOST}${s}&sign=${sign}`
|
||||
}
|
||||
|
||||
export const getMusicUrl = (songInfo, type) => {
|
||||
const requestObj = { cancelHttp() {}, promise: null as any }
|
||||
const songmid = String(songInfo.songmid ?? '')
|
||||
const [channelId, programId] = songmid.split(':')
|
||||
requestObj.promise = (async() => {
|
||||
if (!channelId || !programId) {
|
||||
throw new Error('蜻蜓 id 需为 <channelId>:<programId>(见 /album/qt 节目列表)')
|
||||
}
|
||||
return { type: type === '128k' ? '128k' : '64k', url: buildProgramUrl(channelId, programId) }
|
||||
})()
|
||||
return requestObj
|
||||
}
|
||||
|
||||
export default { getMusicUrl, buildProgramUrl }
|
||||
Reference in new issue
Block a user