Skip to content

Commit

Permalink
Merge pull request #192 from Xbai-hang/master
Browse files Browse the repository at this point in the history
fix kuaishou、bilibili、kugou、huajiao & update yy & update README.md
  • Loading branch information
umuoy1 authored Apr 25, 2024
2 parents ed9f4b4 + 953bfb2 commit 101ec20
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 94 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ npm run serve
- expires_in
- tokenSignDate
- mid
- cookies
- **streamerInfo**: 一个数组,描述录制信息。
- **name**: 主播名。
- uploadLocalFile(true): 是否投稿。
Expand Down Expand Up @@ -210,7 +211,8 @@ npm run serve
"refresh_token": "",
"expires_in": 0,
"tokenSignDate": 0,
"mid": 0
"mid": 0,
"cookies": ""
},
"streamerInfo": [
{
Expand Down
71 changes: 51 additions & 20 deletions src/engine/website/bilibili.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,68 @@
import { getExtendedLogger } from "../../log";

const axios = require("axios");

export function main(url: string) {
return new Promise(function (resolve, reject) {
const rid: any = url.match(/(?<=\/)\d{2,}/g);
axios
.get(
`https://api.live.bilibili.com/room/v1/Room/room_init?id=${rid}`
)
const roomInitUrl = `https://api.live.bilibili.com/room/v1/Room/room_init?id=${rid}`
const roomPlayInfoUrl = `https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo`
const config: any = {
method: "get",
url: '',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'User-Agent': `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${Math.floor(Math.random() * (120 - 100 + 1)) + 100}.0.0.0 Safari/537.36`,
// 由于 bilibili 限制,需登录才可获取最高码率
'Cookie': `${global.app.user.cookies}`,
'Referer': url
},
params: {}
};
config.url = roomInitUrl
axios(config)
.then(function (response: any) {
const data: any = response.data;
if (data["code"] != 0 || data["data"]["live_time"] < 0) {
if (data["code"] != 0 || data["data"]["live_status"] != 1) {
reject(
"BILIBILI=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
const real_id: string = data["data"]["room_id"];
const config: any = {
method: "get",
url: `https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl?cid=${real_id}&platform=h5&qn=10000`,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
};

axios(config).then(function (response: any) {
config.url = roomPlayInfoUrl
config.params = {
'room_id': real_id,
'protocol': '0,1', // 0: http_stream, 1: http_hls
'format': '0,1,2',
'codec': '0,1',
'qn': 10000,
'platform': 'html5', // web, html5, android, ios
'dolby': '5',
}
axios(config)
.then(function (response: any) {
const html: any = response.data;
getExtendedLogger("bilibili").trace(`获取哔哩哔哩房间 ${rid} 的推流信息 ${JSON.stringify(html, null, 2)}`)
const links: any = html["data"]["durl"];
let m3u8_url = links[0]["url"];
if (html['code'] != 0) {
reject(
"BILIBILI=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
const streamInfoList: any = html['data']['playurl_info']['playurl']['stream']
let m3u8_url: string = ''
streamInfoList.forEach((streamInfo: any) => {
if (streamInfo['format'][0]['format_name'] === 'flv') {
// 选取最高码率
const codec = streamInfo['format'][0]['codec'].reduce((prev: any, curr: any) => {
return (prev.current_qn >= curr.current_qn) ? prev : curr;
})
const baseUrl = codec['base_url']
const urlInfo: any = codec['url_info'][0]
m3u8_url = urlInfo['host'] + baseUrl + urlInfo['extra']
}
})
resolve(m3u8_url);
});
})
.catch((error: any) => {
reject(error)
})
})
.catch(function (error: any) {
reject(error);
Expand Down
55 changes: 41 additions & 14 deletions src/engine/website/huajiao.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,52 @@
const axios = require("axios");

export function main(url: string) {
return new Promise(function (resolve, reject) {
const rid: any = url.match(/[0-9]+/g);
const tt: any = Date.now();
axios
.get(
`https://h.huajiao.com/api/getFeedInfo?sid=${tt}&liveid=${rid}`
)
.then(function (response: any) {
const jsons: any = response.data;
if (jsons["data"]) {
resolve(jsons["data"]["live"]["main"]);
} else {
return new Promise((resolve, reject) => {
if (url.indexOf('user') != -1) {
// 主页地址,可以多次获取直播流
const uid = url.match(/(?<=user\/)(\d+)/g)![0];
axios.get(`https://webh.huajiao.com/User/getUserFeeds?_callback=padding&uid=${uid}&fmt=jsonp&_=${Date.now()}`)
.then((response: any) => {
const data = response.data.replace('/**/padding(', '').replace(');','')
const feedInfos = JSON.parse(data).data['feeds']
const feedInfo = feedInfos.find((feedInfo: any) => feedInfo.type === 1)
if (!feedInfo || !feedInfo['relay']) {
reject(
"HUAJIAO=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
const streamUrl: string = `http://al2-flv.live.huajiao.com/${feedInfo['relay']['channel']}/${feedInfo['feed']['sn']}.flv`
resolve(streamUrl)
})
.catch(function (error: any) {
.catch((error: any) => {
reject(error);
});
})
} else if (url.indexOf('l') != -1) {
// 当次直播地址,只能获取该次直播的直播流
const rid = url.match(/(?<=l\/)(\d+)/g)![0];
axios.get(`https://www.huajiao.com/l/${rid}`)
.then((response: any) => {
const data: any = response.data;
const feedInfo: any = JSON.parse(data.split('var feed = ')[1].split(';\n')[0])
const uid = feedInfo['author']['uid']
// 提醒用户更换主页链接
global.app.logger.warn(`HUAJIAO => roomUrl: ${url} 只能录制当次直播,请更换 roomUrl 为 https://www.huajiao.com/user/${uid}`)
if (feedInfo && feedInfo['feed']['duration'] != '00:00:00') {
reject(
"HUAJIAO=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
const streamUrl: string = `http://al2-flv.live.huajiao.com/${feedInfo['relay']['channel']}/${feedInfo['feed']['sn']}.flv`
resolve(streamUrl)
})
.catch((error: any) => {
global.app.logger.warn(`HUAJIAO => roomUrl: ${url} 只能录制当次直播,请更换 roomUrl 为 https://www.huajiao.com/user/xxxx`)
reject(error);
});
} else {
reject(
"HUAJIAO=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
});
}
73 changes: 49 additions & 24 deletions src/engine/website/kuaishou.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,57 @@ const axios = require("axios");
export function main(url: string) {
return new Promise(function (resolve, reject) {
const rid: any = url.match(/(?<=u\/)(.+)/g);

const config: any = {
method: "get",
url: `https://m.gifshow.com/fw/live/${rid[0]}`,
const session = axios.create({
baseURL: 'https://live.kuaishou.com',
headers: {
"user-agent":
"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
cookie: "did=web_",
},
};

axios(config)
.then(function (response: any) {
const html: any = response.data;
const reg: RegExp = /(?<=type="application\/x-mpegURL" src=")(.+?)(?=")/;
const strs: any = html.match(reg);
if (strs && strs.length >= 1) {
resolve(strs[0].replace(/#38;/g, ""));
} else {
reject(
"KUAISHOU=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
'User-Agent': `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${Math.floor(Math.random() * (120 - 100 + 1)) + 100}.0.0.0 Safari/537.36`
}
})
// 首页低风控生成 did cookie
session.get('/')
.then(() => {
const delay = Math.floor(Math.random() * 1000) + 3000
// 延迟3-4秒以防风控
setTimeout(() => {
session.get(`/u/${rid}`)
.then((response: any) => {
const errorKeys = ['错误代码22', '主播尚未开播']
errorKeys.forEach((errorKey) => {
if (response.data.indexOf(errorKey) != -1) {
reject(
"KUAISHOU=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
})
session.get(`/live_api/liveroom/livedetail?principalId=${rid}`)
.then((response: any) => {
const roomInfo: any = response.data.data
if (roomInfo['result'] == 1) {
const streamInfoList: any = roomInfo['liveStream']['playUrls'][0]['adaptationSet']['representation']
// 不登录只能录制标清码率? ===> 只在前端限制了
// 录制最高码率
const streamInfo = streamInfoList.reduce((prev: any, curr: any) => {
return (prev.bitrate > curr.bitrate) ? prev : curr;
})
const streamUrl: string = streamInfo['url']
resolve(streamUrl)
} else {
reject(
"KUAISHOU=>No match results:Maybe the roomid is error,or this room is not open!"
);
}
})
.catch((error: any) => {
reject(error)
})
})
.catch((error: any) => {
reject(error)
})
}, delay)
})
.catch(function (error: any) {
.catch((error: any) => {
reject(error);
});
})
});
}
65 changes: 49 additions & 16 deletions src/engine/website/kugou.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,56 @@ const axios = require("axios");

export function main(url: string) {
return new Promise(function (resolve, reject) {
const rid: any = url.match(/[0-9]+(?=\?)*/g);
axios
.get(
`https://fx1.service.kugou.com/video/pc/live/pull/v3/streamaddr?roomId=${rid[0]}&ch=fx&version=1.0&streamType=1-2-5&platform=7&ua=fx-flash&kugouId=0&layout=1`
)
.then(function (response: any) {
const json: any = response.data;
if (json && json["code"] == 0) {
resolve(json["data"]["horizontal"][0]["httpflv"][0]);
} else {
reject(
"KUGOU=>No match results:Maybe the roomid is error,or this room is not open!"
);
const rid: any = url.match(/[0-9]+(?=\?)*/)![0];
axios.get(`https://fanxing.kugou.com/${rid}`)
.then((response: any) => {
const match: any = response.data.match(/roomId=(\d+)/)
let roomId: string = rid;
if (match) {
roomId = match[1]
}
const config: any = {
method: "get",
url: `https://fx1.service.kugou.com/video/pc/live/pull/mutiline/streamaddr?std_rid=${roomId}`,
headers: {
'Content-Type': 'application/json;charset=utf-8',
'User-Agent': `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${Math.floor(Math.random() * (120 - 100 + 1)) + 100}.0.0.0 Safari/537.36`,
'Referer': url,
},
params: {
appid: '1010',
version: '1000',
std_plat: 7,
std_kid: 0,
std_imei: '',
streamType: '1-2-4-5-8',
targetLiveTypes: '1-5-6',
ua: 'fx-flash',
supportEncryptMode: 1,
_: Date.now()
}
}
axios(config)
.then((response: any) => {
const html: any = response.data;
if (html['code'] != 0 || html.data['lines'].length == 0) {
reject(
"KUGOU=>No match results:Maybe the roomid is error,or this room is not open!"
)
}
const streamInfoList: any = html.data['lines'].pop()['streamProfiles']
const streamInfo = streamInfoList.reduce((prev: any, curr: any) => {
return (prev.rate > curr.rate) ? prev : curr;
})
const streamUrl: string = streamInfo['httpsFlv'][0]
resolve(streamUrl)
})
.catch((error: any) => {
reject(error)
})
})
.catch((error: any) => {
reject(error)
})
.catch(function (error: any) {
reject(error);
});
});
}
Loading

0 comments on commit 101ec20

Please sign in to comment.