@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 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, formatPriorities?: Array<"flv" | "hls">): Promise<{
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, formatPriorities = ["flv", "hls"]) {
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: item.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: item.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, FFMPEGRecorder, } from "@bililive-tools/manager";
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: `ffmpeg end, reason: ${JSON.stringify(args, (_, v) => (v instanceof Error ? v.stack : v))}`,
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
- const recorder = new FFMPEGRecorder({
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, options.formatPriorities);
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, options.formatPriorities);
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.2",
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.4.1",
40
+ "@bililive-tools/manager": "^1.6.0",
41
41
  "huya-danma-listener": "0.1.2"
42
42
  },
43
43
  "devDependencies": {},