@bililive-tools/douyin-recorder 1.11.0 → 1.12.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/lib/douyin_api.js CHANGED
@@ -144,7 +144,7 @@ async function getRoomInfoByUserWeb(secUserId, opts = {}) {
144
144
  const signed = get__ac_signature(timestamp, url, nonce, ua);
145
145
  cookies = `__ac_nonce=${nonce}; __ac_signature=${signed}; __ac_referer=__ac_blank`;
146
146
  }
147
- const res = await axios.get(url, {
147
+ const res = await requester.get(url, {
148
148
  headers: {
149
149
  "User-Agent": ua,
150
150
  cookie: cookies,
@@ -229,7 +229,7 @@ async function getRoomInfoByHtml(webRoomId, opts = {}) {
229
229
  const signed = get__ac_signature(timestamp, url, nonce, ua);
230
230
  cookies = `__ac_nonce=${nonce}; __ac_signature=${signed}; __ac_referer=__ac_blank`;
231
231
  }
232
- const res = await axios.get(url, {
232
+ const res = await requester.get(url, {
233
233
  headers: {
234
234
  "User-Agent": ua,
235
235
  cookie: cookies,
package/lib/index.js CHANGED
@@ -30,7 +30,7 @@ function createRecorder(opts) {
30
30
  async getLiveInfo() {
31
31
  const channelId = this.channelId;
32
32
  const info = await getInfo(channelId, {
33
- cookie: this.auth,
33
+ auth: this.auth,
34
34
  uid: this.uid,
35
35
  });
36
36
  return {
@@ -65,7 +65,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
65
65
  // 如果已经在录制中,只在需要检查标题关键词时才获取最新信息
66
66
  if (this.recordHandle != null) {
67
67
  const shouldStop = await utils.checkTitleKeywordsWhileRecording(this, isManualStart, (channelId) => getInfo(channelId, {
68
- cookie: this.auth,
68
+ auth: this.auth,
69
69
  api: this.api,
70
70
  uid: this.uid,
71
71
  }));
@@ -78,7 +78,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
78
78
  // 获取直播间信息
79
79
  try {
80
80
  const liveInfo = await getInfo(this.channelId, {
81
- cookie: this.auth,
81
+ auth: this.auth,
82
82
  api: this.api,
83
83
  uid: this.uid,
84
84
  });
@@ -113,7 +113,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
113
113
  streamPriorities: this.streamPriorities,
114
114
  sourcePriorities: this.sourcePriorities,
115
115
  strictQuality: strictQuality,
116
- cookie: this.auth,
116
+ auth: this.auth,
117
117
  formatPriorities: this.formatPriorities,
118
118
  doubleScreen: this.doubleScreen,
119
119
  api: this.api,
@@ -173,7 +173,9 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
173
173
  Cookie: this.auth,
174
174
  },
175
175
  }, onEnd, async () => {
176
- const info = await getInfo(this.channelId);
176
+ const info = await getInfo(this.channelId, {
177
+ auth: this.auth,
178
+ });
177
179
  return info;
178
180
  });
179
181
  const savePath = getSavePath({
@@ -249,6 +251,41 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
249
251
  this.emit("Message", comment);
250
252
  extraDataController.addMessage(comment);
251
253
  });
254
+ client.on("privilegeScreenChat", (msg) => {
255
+ const extraDataController = downloader.getExtraDataController();
256
+ if (!extraDataController)
257
+ return;
258
+ const comment = {
259
+ type: "comment",
260
+ // 抖音飘屏没有时间戳数据,默认使用当前时间
261
+ timestamp: Date.now(),
262
+ text: msg.content,
263
+ color: "#e0c39c",
264
+ sender: {
265
+ uid: msg.user.id,
266
+ name: msg.user.nickName,
267
+ },
268
+ };
269
+ this.emit("Message", comment);
270
+ extraDataController.addMessage(comment);
271
+ });
272
+ client.on("screenChat", (msg) => {
273
+ const extraDataController = downloader.getExtraDataController();
274
+ if (!extraDataController)
275
+ return;
276
+ const comment = {
277
+ type: "comment",
278
+ timestamp: this.useServerTimestamp ? Number(msg.eventTime) / 1000000 : Date.now(),
279
+ text: msg.content,
280
+ color: "#d7f6fc",
281
+ sender: {
282
+ uid: msg.user.id,
283
+ name: msg.user.nickName,
284
+ },
285
+ };
286
+ this.emit("Message", comment);
287
+ extraDataController.addMessage(comment);
288
+ });
252
289
  client.on("gift", (msg) => {
253
290
  const extraDataController = downloader.getExtraDataController();
254
291
  if (!extraDataController)
@@ -267,7 +304,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
267
304
  color: "#ffffff",
268
305
  sender: {
269
306
  uid: msg.user.id,
270
- name: msg.user.nickName,
307
+ name: msg?.user?.nickName ?? "unknown",
271
308
  // avatar: msg.ic,
272
309
  // extra: {
273
310
  // level: msg.level,
package/lib/stream.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Recorder } from "@bililive-tools/manager";
2
2
  import type { APIType, RealAPIType } from "./types.js";
3
3
  export declare function getInfo(channelId: string, opts?: {
4
- cookie?: string;
4
+ auth?: string;
5
5
  api?: APIType;
6
6
  uid?: string | number;
7
7
  }): Promise<{
@@ -20,7 +20,7 @@ export declare function getInfo(channelId: string, opts?: {
20
20
  export declare function getStream(opts: Pick<Recorder, "channelId" | "quality" | "streamPriorities" | "sourcePriorities"> & {
21
21
  rejectCache?: boolean;
22
22
  strictQuality?: boolean;
23
- cookie?: string;
23
+ auth?: string;
24
24
  formatPriorities?: Array<"flv" | "hls">;
25
25
  doubleScreen?: boolean;
26
26
  api?: APIType;
package/lib/stream.js CHANGED
@@ -5,7 +5,7 @@ export async function getInfo(channelId, opts) {
5
5
  // 如果使用 balance 模式,使用负载均衡器
6
6
  if (opts?.api === "balance") {
7
7
  info = await globalLoadBalancer.callWithLoadBalance(channelId, {
8
- auth: opts.cookie,
8
+ auth: opts.auth,
9
9
  uid: opts.uid,
10
10
  });
11
11
  }
@@ -38,7 +38,7 @@ export async function getStream(opts) {
38
38
  }
39
39
  const info = await getRoomInfo(opts.channelId, {
40
40
  doubleScreen: opts.doubleScreen ?? true,
41
- auth: opts.cookie,
41
+ auth: opts.auth,
42
42
  api: api,
43
43
  uid: opts.uid,
44
44
  });
package/lib/utils.d.ts CHANGED
@@ -8,5 +8,4 @@ export declare function assert(assertion: unknown, msg?: string): asserts assert
8
8
  export declare function assertStringType(data: unknown, msg?: string): asserts data is string;
9
9
  export declare function assertNumberType(data: unknown, msg?: string): asserts data is number;
10
10
  export declare function assertObjectType(data: unknown, msg?: string): asserts data is object;
11
- export declare function replaceExtName(filePath: string, newExtName: string): string;
12
11
  export declare function get__ac_signature(one_time_stamp: any, one_site: any, one_nonce: any, ua_n: any): string;
package/lib/utils.js CHANGED
@@ -39,9 +39,6 @@ export function assertNumberType(data, msg) {
39
39
  export function assertObjectType(data, msg) {
40
40
  assert(typeof data === "object", msg);
41
41
  }
42
- export function replaceExtName(filePath, newExtName) {
43
- return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + newExtName);
44
- }
45
42
  export function get__ac_signature(one_time_stamp, one_site, one_nonce, ua_n) {
46
43
  function cal_one_str(one_str, orgi_iv) {
47
44
  var k = orgi_iv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bililive-tools/douyin-recorder",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "@bililive-tools douyin recorder implemention",
5
5
  "main": "./lib/index.js",
6
6
  "type": "module",
@@ -38,8 +38,8 @@
38
38
  "lodash-es": "^4.17.21",
39
39
  "mitt": "^3.0.1",
40
40
  "sm-crypto": "^0.3.13",
41
- "@bililive-tools/manager": "^1.10.0",
42
- "douyin-danma-listener": "0.2.1"
41
+ "@bililive-tools/manager": "^1.12.0",
42
+ "douyin-danma-listener": "0.3.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "*"
@@ -1,2 +0,0 @@
1
- declare function runExamples(): Promise<void>;
2
- export { runExamples };
@@ -1,130 +0,0 @@
1
- /**
2
- * 抖音录播器负载均衡使用示例
3
- */
4
- import { getInfo } from "../stream.js";
5
- import { loadBalancer } from "./loadBalancerManager.js";
6
- async function basicExample() {
7
- console.log("=== 基本使用示例 ===");
8
- try {
9
- // 使用负载均衡模式获取房间信息
10
- const roomInfo = await getInfo("测试房间ID", {
11
- api: "balance", // 关键:使用balance模式启用负载均衡
12
- cookie: "your-cookie-here",
13
- });
14
- console.log("获取到房间信息:", {
15
- title: roomInfo.title,
16
- owner: roomInfo.owner,
17
- living: roomInfo.living,
18
- });
19
- }
20
- catch (error) {
21
- console.error("获取房间信息失败:", error.message);
22
- }
23
- }
24
- async function managementExample() {
25
- console.log("\n=== 管理功能示例 ===");
26
- // 1. 查看当前状态
27
- console.log("1. 当前负载均衡器状态:");
28
- loadBalancer.printStatus();
29
- // 2. 检查API健康状态
30
- console.log("\n2. API健康状态检查:");
31
- const apis = ["web", "webHTML", "mobile", "userHTML"];
32
- apis.forEach((api) => {
33
- const isHealthy = loadBalancer.isAPIHealthy(api);
34
- console.log(`${api}: ${isHealthy ? "✅ 健康" : "❌ 不健康"}`);
35
- });
36
- // 3. 获取推荐API
37
- const recommendedAPI = loadBalancer.getRecommendedAPI();
38
- console.log(`\n3. 推荐使用的API: ${recommendedAPI}`);
39
- // 4. 配置调整示例
40
- console.log("\n4. 配置调整示例:");
41
- console.log("原始配置:", loadBalancer.getConfig());
42
- // 调整配置:更保守的失败策略
43
- loadBalancer.updateConfig({
44
- maxFailures: 2, // 减少到2次失败就禁用
45
- blockDuration: 120000, // 禁用2分钟
46
- });
47
- console.log("调整后配置:", loadBalancer.getConfig());
48
- // 5. API权重调整示例
49
- console.log("\n5. API权重调整示例:");
50
- console.log("调整前状态:");
51
- console.table(loadBalancer.getStatus());
52
- // 提高mobile接口的优先级和权重
53
- loadBalancer.updateAPIConfig("mobile", {
54
- priority: 1, // 最高优先级
55
- weight: 5, // 最高权重
56
- });
57
- console.log("调整mobile接口权重后:");
58
- console.table(loadBalancer.getStatus());
59
- }
60
- async function errorHandlingExample() {
61
- console.log("\n=== 错误处理示例 ===");
62
- // 模拟检查被禁用的API
63
- const blockedAPIs = loadBalancer.getBlockedAPIs();
64
- if (blockedAPIs.length > 0) {
65
- console.log(`发现 ${blockedAPIs.length} 个被禁用的API:`, blockedAPIs);
66
- // 可以选择重置这些API
67
- console.log("重置被禁用的API...");
68
- blockedAPIs.forEach((api) => {
69
- loadBalancer.resetAPI(api);
70
- });
71
- console.log("重置完成,当前健康的API:", loadBalancer.getHealthyAPIs());
72
- }
73
- else {
74
- console.log("所有API都处于健康状态 ✅");
75
- }
76
- }
77
- async function monitoringExample() {
78
- console.log("\n=== 监控示例 ===");
79
- // 模拟监控函数
80
- function checkSystemHealth() {
81
- const status = loadBalancer.getStatus();
82
- const healthyCount = status.filter((s) => !s.isBlocked).length;
83
- const totalCount = status.length;
84
- console.log(`系统健康状态: ${healthyCount}/${totalCount} 个API可用`);
85
- if (healthyCount < totalCount / 2) {
86
- console.warn("⚠️ 警告:超过一半的API不可用!");
87
- loadBalancer.printStatus();
88
- // 可以触发告警或自动恢复逻辑
89
- console.log("执行自动恢复...");
90
- loadBalancer.resetAll();
91
- }
92
- // 显示详细状态
93
- status.forEach((s) => {
94
- if (s.isBlocked) {
95
- const retryTime = new Date(s.nextRetryTime).toLocaleString();
96
- console.log(`❌ ${s.api}: 被禁用,下次重试时间: ${retryTime}`);
97
- }
98
- else if (s.failureCount > 0) {
99
- console.log(`⚠️ ${s.api}: 失败 ${s.failureCount} 次,仍可用`);
100
- }
101
- else {
102
- console.log(`✅ ${s.api}: 健康`);
103
- }
104
- });
105
- }
106
- // 执行健康检查
107
- checkSystemHealth();
108
- // 在实际应用中,可以设置定时器
109
- // setInterval(checkSystemHealth, 60000); // 每分钟检查一次
110
- }
111
- // 主函数
112
- async function runExamples() {
113
- try {
114
- await basicExample();
115
- await managementExample();
116
- await errorHandlingExample();
117
- await monitoringExample();
118
- console.log("\n=== 示例执行完成 ===");
119
- console.log("\n最终状态:");
120
- loadBalancer.printStatus();
121
- }
122
- catch (error) {
123
- console.error("示例执行失败:", error);
124
- }
125
- }
126
- // 如果直接运行此文件
127
- if (import.meta.url === `file://${process.argv[1]}`) {
128
- runExamples();
129
- }
130
- export { runExamples };