@bililive-tools/bilibili-recorder 1.7.0 → 1.8.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
@@ -53,7 +53,8 @@ interface Options {
53
53
  m3u8ProxyUrl?: string; // 代理链接,文档待补充
54
54
  videoFormat?: "auto"; // 视频格式: "auto", "ts", "mkv" ,auto模式下, 分段使用 "ts",不分段使用 "mp4"
55
55
  onlyAudio?: boolean; // 只录制音频,默认为否
56
- recorderType?: "auto" | "ffmpeg" | "mesio"; // 底层录制器,使用mesio时videoFormat参数无效
56
+ recorderType?: "auto" | "ffmpeg" | "mesio" | "bililive"; // 底层录制器,使用mesio和bililive时videoFormat参数无效
57
+ debugLevel?: `verbose` | "basic"; // verbose参数时,录制器会输出更加详细的log
57
58
  }
58
59
  ```
59
60
 
package/lib/index.js CHANGED
@@ -72,14 +72,10 @@ const ffmpegOutputOptions = [
72
72
  "10000000",
73
73
  ];
74
74
  const ffmpegInputOptions = [
75
- "-reconnect",
76
- "1",
77
- "-reconnect_streamed",
78
- "1",
79
- "-reconnect_delay_max",
80
- "10",
81
75
  "-rw_timeout",
82
- "15000000",
76
+ "10000000",
77
+ "-timeout",
78
+ "10000000",
83
79
  "-headers",
84
80
  "Referer:https://live.bilibili.com/",
85
81
  ];
@@ -96,6 +92,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
96
92
  cover: "",
97
93
  liveId: liveId,
98
94
  };
95
+ this.state = "idle";
99
96
  }
100
97
  catch (error) {
101
98
  this.state = "check-error";
@@ -113,12 +110,10 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
113
110
  return null;
114
111
  // 检查标题是否包含关键词,如果包含则不自动录制
115
112
  // 手动开始录制时不检查标题关键词
116
- if (!isManualStart &&
117
- this.titleKeywords &&
118
- typeof this.titleKeywords === "string" &&
119
- this.titleKeywords.trim()) {
113
+ if (utils.shouldCheckTitleKeywords(isManualStart, this.titleKeywords)) {
120
114
  const hasTitleKeyword = hasKeyword(this.liveInfo.title, this.titleKeywords);
121
115
  if (hasTitleKeyword) {
116
+ this.state = "title-blocked";
122
117
  this.emit("DebugLog", {
123
118
  type: "common",
124
119
  text: `跳过录制:直播间标题 "${this.liveInfo.title}" 包含关键词 "${this.titleKeywords}"`,
@@ -130,7 +125,6 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
130
125
  const { owner, title, roomId } = liveInfo;
131
126
  this.liveInfo = liveInfo;
132
127
  let res;
133
- // TODO: 先不做什么错误处理,就简单包一下预期上会有错误的地方
134
128
  try {
135
129
  let strictQuality = false;
136
130
  if (this.qualityRetry > 0) {
@@ -206,17 +200,19 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
206
200
  const reason = args[0] instanceof Error ? args[0].message : String(args[0]);
207
201
  this.recordHandle?.stop(reason);
208
202
  };
209
- let recorderType = this.recorderType === "mesio" ? "mesio" : "ffmpeg";
210
- const recorder = createBaseRecorder(recorderType, {
203
+ const recorder = createBaseRecorder(this.recorderType, {
211
204
  url: url,
212
205
  outputOptions: ffmpegOutputOptions,
213
206
  inputOptions: ffmpegInputOptions,
214
- mesioOptions: ["-H", "Referer:https://live.bilibili.com/"],
215
207
  segment: this.segment ?? 0,
216
208
  getSavePath: (opts) => getSavePath({ owner, title: opts.title ?? title, startTime: opts.startTime }),
217
209
  formatName: streamOptions.format_name,
218
210
  disableDanma: this.disableProvideCommentsWhenRecording,
219
211
  videoFormat: this.videoFormat,
212
+ debugLevel: this.debugLevel ?? "none",
213
+ headers: {
214
+ Referer: "https://live.bilibili.com/",
215
+ },
220
216
  }, onEnd, async () => {
221
217
  const info = await getInfo(this.channelId);
222
218
  return info;
@@ -232,8 +228,8 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
232
228
  this.state = "idle";
233
229
  throw err;
234
230
  }
235
- const handleVideoCreated = async ({ filename, title, cover }) => {
236
- this.emit("videoFileCreated", { filename, cover });
231
+ const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
232
+ this.emit("videoFileCreated", { filename, cover, rawFilename });
237
233
  if (title && this?.liveInfo) {
238
234
  this.liveInfo.title = title;
239
235
  }
@@ -281,13 +277,11 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
281
277
  extraDataController.addMessage(msg);
282
278
  });
283
279
  danmaClient.on("onRoomInfoChange", (msg) => {
284
- if (!isManualStart &&
285
- this.titleKeywords &&
286
- typeof this.titleKeywords === "string" &&
287
- this.titleKeywords.trim()) {
280
+ if (utils.shouldCheckTitleKeywords(isManualStart, this.titleKeywords)) {
288
281
  const title = msg?.body?.title ?? "";
289
282
  const hasTitleKeyword = hasKeyword(title, this.titleKeywords);
290
283
  if (hasTitleKeyword) {
284
+ this.state = "title-blocked";
291
285
  this.emit("DebugLog", {
292
286
  type: "common",
293
287
  text: `检测到标题包含关键词,停止录制:直播间标题 "${title}" 包含关键词 "${this.titleKeywords}"`,
@@ -338,6 +332,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, isManualStart, b
338
332
  id: genRecordUUID(),
339
333
  stream: stream.name,
340
334
  source: stream.source,
335
+ recorderType: recorder.type,
341
336
  url: stream.url,
342
337
  ffmpegArgs,
343
338
  savePath: savePath,
package/lib/utils.d.ts CHANGED
@@ -21,4 +21,4 @@ export declare function assertStringType(data: unknown, msg?: string): asserts d
21
21
  export declare function assertNumberType(data: unknown, msg?: string): asserts data is number;
22
22
  export declare function assertObjectType(data: unknown, msg?: string): asserts data is object;
23
23
  export declare function createInvalidStreamChecker(count?: number): (ffmpegLogLine: string) => boolean;
24
- export declare function hasKeyword(title: string, titleKeywords: string): boolean;
24
+ export declare function hasKeyword(title: string, titleKeywords: string | undefined): boolean;
package/lib/utils.js CHANGED
@@ -82,7 +82,7 @@ export function createInvalidStreamChecker(count = 10) {
82
82
  };
83
83
  }
84
84
  export function hasKeyword(title, titleKeywords) {
85
- const keywords = titleKeywords
85
+ const keywords = (titleKeywords ?? "")
86
86
  .split(",")
87
87
  .map((k) => k.trim())
88
88
  .filter((k) => k);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bililive-tools/bilibili-recorder",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "bililive-tools bilibili recorder implemention",
5
5
  "main": "./lib/index.js",
6
6
  "type": "module",
@@ -39,7 +39,7 @@
39
39
  "tiny-bilibili-ws": "^1.0.2",
40
40
  "lodash-es": "^4.17.21",
41
41
  "axios": "^1.7.8",
42
- "@bililive-tools/manager": "^1.6.1"
42
+ "@bililive-tools/manager": "^1.8.0"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "tsc",