@bililive-tools/huya-recorder 1.3.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/huya_api.d.ts +5 -1
- package/lib/huya_api.js +13 -4
- package/lib/index.js +6 -3
- package/lib/stream.d.ts +1 -0
- package/lib/stream.js +10 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ interface Options {
|
|
|
46
46
|
saveCover?: boolean; // 保存封面
|
|
47
47
|
api?: "auto" | "mp" | "web"; // 默认为auto,在星秀区使用mp接口,其他使用web接口,你也可以强制指定
|
|
48
48
|
videoFormat?: "auto"; // 视频格式: "auto", "ts", "mkv" ,auto模式下, 分段使用 "ts",不分段使用 "mp4"
|
|
49
|
+
recorderType?: "auto" | "ffmpeg" | "mesio"; // 底层录制器,使用mesio时videoFormat参数无效
|
|
49
50
|
}
|
|
50
51
|
```
|
|
51
52
|
|
package/lib/huya_api.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { Recorder } from "@bililive-tools/manager";
|
|
1
2
|
import type { StreamProfile } from "./types.js";
|
|
2
|
-
export declare function getRoomInfo(roomIdOrShortId: string,
|
|
3
|
+
export declare function getRoomInfo(roomIdOrShortId: string, opts?: {
|
|
4
|
+
formatPriorities?: Array<"flv" | "hls">;
|
|
5
|
+
quality?: Recorder["quality"];
|
|
6
|
+
}): Promise<{
|
|
3
7
|
living: boolean;
|
|
4
8
|
id: number;
|
|
5
9
|
owner: string;
|
package/lib/huya_api.js
CHANGED
|
@@ -5,7 +5,7 @@ import { initInfo } from "./anticode.js";
|
|
|
5
5
|
const requester = axios.create({
|
|
6
6
|
timeout: 10e3,
|
|
7
7
|
});
|
|
8
|
-
export async function getRoomInfo(roomIdOrShortId,
|
|
8
|
+
export async function getRoomInfo(roomIdOrShortId, opts = {}) {
|
|
9
9
|
const res = await requester.get(`https://www.huya.com/${roomIdOrShortId}`);
|
|
10
10
|
const html = res.data;
|
|
11
11
|
const match = html.match(/var hyPlayerConfig = ({[^]+?};)/);
|
|
@@ -18,6 +18,7 @@ export async function getRoomInfo(roomIdOrShortId, formatPriorities = ["flv", "h
|
|
|
18
18
|
desc: info.sDisplayName,
|
|
19
19
|
bitRate: info.iBitRate,
|
|
20
20
|
}));
|
|
21
|
+
streams.push({ desc: "真原画", bitRate: -1 });
|
|
21
22
|
const data = hyPlayerConfig.stream.data[0];
|
|
22
23
|
assert(data, `Unexpected resp, data is null`);
|
|
23
24
|
const sources = {
|
|
@@ -35,9 +36,13 @@ export async function getRoomInfo(roomIdOrShortId, formatPriorities = ["flv", "h
|
|
|
35
36
|
// }));
|
|
36
37
|
for (const item of data?.gameStreamInfoList ?? []) {
|
|
37
38
|
if (item.sFlvAntiCode && item.sFlvAntiCode.length > 0) {
|
|
39
|
+
let sStreamName = item.sStreamName;
|
|
40
|
+
if (opts.quality === -1) {
|
|
41
|
+
sStreamName = sStreamName.replace("-imgplus", "");
|
|
42
|
+
}
|
|
38
43
|
const url = initInfo({
|
|
39
44
|
baseUrl: item.sFlvUrl,
|
|
40
|
-
sStreamName:
|
|
45
|
+
sStreamName: sStreamName,
|
|
41
46
|
antiCode: item.sFlvAntiCode,
|
|
42
47
|
suffix: item.sFlvUrlSuffix,
|
|
43
48
|
_sessionId: Date.now(),
|
|
@@ -48,9 +53,13 @@ export async function getRoomInfo(roomIdOrShortId, formatPriorities = ["flv", "h
|
|
|
48
53
|
});
|
|
49
54
|
}
|
|
50
55
|
if (item.sHlsAntiCode && item.sHlsAntiCode.length > 0) {
|
|
56
|
+
let sStreamName = item.sStreamName;
|
|
57
|
+
if (opts.quality === -1) {
|
|
58
|
+
sStreamName = sStreamName.replace("-imgplus", "");
|
|
59
|
+
}
|
|
51
60
|
const url = initInfo({
|
|
52
61
|
baseUrl: item.sHlsUrl,
|
|
53
|
-
sStreamName:
|
|
62
|
+
sStreamName: sStreamName,
|
|
54
63
|
antiCode: item.sHlsAntiCode,
|
|
55
64
|
suffix: item.sHlsUrlSuffix,
|
|
56
65
|
_sessionId: Date.now(),
|
|
@@ -62,7 +71,7 @@ export async function getRoomInfo(roomIdOrShortId, formatPriorities = ["flv", "h
|
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
const startTime = new Date(data.gameLiveInfo?.startTime * 1000);
|
|
65
|
-
const formatSources = getFormatSources(sources, formatPriorities);
|
|
74
|
+
const formatSources = getFormatSources(sources, opts.formatPriorities);
|
|
66
75
|
return {
|
|
67
76
|
living: vMultiStreamInfo.length > 0 && data.gameStreamInfoList.length > 0,
|
|
68
77
|
id: data.gameLiveInfo.profileRoom,
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import mitt from "mitt";
|
|
3
|
-
import { defaultFromJSON, defaultToJSON, genRecorderUUID, genRecordUUID, utils,
|
|
3
|
+
import { defaultFromJSON, defaultToJSON, genRecorderUUID, genRecordUUID, utils, createBaseRecorder, } from "@bililive-tools/manager";
|
|
4
4
|
import { getInfo, getStream } from "./stream.js";
|
|
5
5
|
import { ensureFolderExist } from "./utils.js";
|
|
6
6
|
import HuYaDanMu from "huya-danma-listener";
|
|
@@ -114,6 +114,8 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
|
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
116
|
catch (err) {
|
|
117
|
+
if (this.qualityRetry > 0)
|
|
118
|
+
this.qualityRetry -= 1;
|
|
117
119
|
this.state = "idle";
|
|
118
120
|
throw err;
|
|
119
121
|
}
|
|
@@ -135,12 +137,13 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
|
|
|
135
137
|
isEnded = true;
|
|
136
138
|
this.emit("DebugLog", {
|
|
137
139
|
type: "common",
|
|
138
|
-
text: `
|
|
140
|
+
text: `record end, reason: ${JSON.stringify(args, (_, v) => (v instanceof Error ? v.stack : v))}`,
|
|
139
141
|
});
|
|
140
142
|
const reason = args[0] instanceof Error ? args[0].message : String(args[0]);
|
|
141
143
|
this.recordHandle?.stop(reason);
|
|
142
144
|
};
|
|
143
|
-
|
|
145
|
+
let recorderType = this.recorderType === "mesio" ? "mesio" : "ffmpeg";
|
|
146
|
+
const recorder = createBaseRecorder(recorderType, {
|
|
144
147
|
url: stream.url,
|
|
145
148
|
outputOptions: ffmpegOutputOptions,
|
|
146
149
|
inputOptions: ffmpegInputOptions,
|
package/lib/stream.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare function getInfo(channelId: string): Promise<{
|
|
|
12
12
|
}>;
|
|
13
13
|
export declare function getStream(opts: Pick<Recorder, "channelId" | "quality" | "streamPriorities" | "sourcePriorities" | "api" | "formatPriorities"> & {
|
|
14
14
|
strictQuality?: boolean;
|
|
15
|
+
api?: "web" | "mp" | "auto";
|
|
15
16
|
}): Promise<{
|
|
16
17
|
currentStream: {
|
|
17
18
|
name: string;
|
package/lib/stream.js
CHANGED
|
@@ -18,7 +18,10 @@ export async function getInfo(channelId) {
|
|
|
18
18
|
}
|
|
19
19
|
async function getRoomInfo(channelId, options) {
|
|
20
20
|
if (options.api == "auto") {
|
|
21
|
-
const info = await getRoomInfoByWeb(channelId,
|
|
21
|
+
const info = await getRoomInfoByWeb(channelId, {
|
|
22
|
+
formatPriorities: options.formatPriorities,
|
|
23
|
+
quality: options.quality,
|
|
24
|
+
});
|
|
22
25
|
if (info.gid == 1663) {
|
|
23
26
|
return getRoomInfoByMobile(channelId, options.formatPriorities);
|
|
24
27
|
}
|
|
@@ -28,7 +31,10 @@ async function getRoomInfo(channelId, options) {
|
|
|
28
31
|
return getRoomInfoByMobile(channelId, options.formatPriorities);
|
|
29
32
|
}
|
|
30
33
|
else if (options.api == "web") {
|
|
31
|
-
return getRoomInfoByWeb(channelId,
|
|
34
|
+
return getRoomInfoByWeb(channelId, {
|
|
35
|
+
formatPriorities: options.formatPriorities,
|
|
36
|
+
quality: options.quality,
|
|
37
|
+
});
|
|
32
38
|
}
|
|
33
39
|
assert(false, "Invalid api");
|
|
34
40
|
}
|
|
@@ -36,6 +42,7 @@ export async function getStream(opts) {
|
|
|
36
42
|
const info = await getRoomInfo(opts.channelId, {
|
|
37
43
|
api: opts.api ?? "auto",
|
|
38
44
|
formatPriorities: opts.formatPriorities ?? ["flv", "hls"],
|
|
45
|
+
quality: opts.quality,
|
|
39
46
|
});
|
|
40
47
|
if (!info.living) {
|
|
41
48
|
throw new Error("It must be called getStream when living");
|
|
@@ -72,7 +79,7 @@ export async function getStream(opts) {
|
|
|
72
79
|
}
|
|
73
80
|
let url = expectSource.url;
|
|
74
81
|
// MP协议下原画不需要添加ratio参数
|
|
75
|
-
if (expectStream.bitRate) {
|
|
82
|
+
if (expectStream.bitRate && expectStream.bitRate !== -1 && !url.includes("ratio=")) {
|
|
76
83
|
url = url + "&ratio=" + expectStream.bitRate;
|
|
77
84
|
}
|
|
78
85
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bililive-tools/huya-recorder",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "bililive-tools huya recorder implemention",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"mitt": "^3.0.1",
|
|
38
38
|
"lodash-es": "^4.17.21",
|
|
39
39
|
"axios": "^1.7.8",
|
|
40
|
-
"@bililive-tools/manager": "^1.
|
|
40
|
+
"@bililive-tools/manager": "^1.6.0",
|
|
41
41
|
"huya-danma-listener": "0.1.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {},
|