@bililive-tools/manager 1.14.1 → 1.16.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.
@@ -194,6 +194,11 @@ export class BililiveDownloader extends EventEmitter {
194
194
  if (timeMatch) {
195
195
  time = timeMatch[1];
196
196
  }
197
+ const spaceMath = line.match(/下载进度:\s*([\d.]+\s*MB)\s*/);
198
+ if (spaceMath) {
199
+ const space = spaceMath[1];
200
+ time = time ? `${time} ${space}` : space;
201
+ }
197
202
  return {
198
203
  time,
199
204
  };
@@ -154,7 +154,7 @@ export class FFmpegDownloader extends EventEmitter {
154
154
  let time = null;
155
155
  const timeMatch = line.match(/time=([0-9:.]+)/);
156
156
  if (timeMatch) {
157
- time = timeMatch[1];
157
+ time = timeMatch[1].split(".")[0];
158
158
  }
159
159
  return {
160
160
  time,
@@ -11,6 +11,7 @@ export interface BaseRecorderOptions {
11
11
  getSavePath: (data: {
12
12
  startTime: number;
13
13
  title?: string;
14
+ extraMs?: boolean;
14
15
  }) => string;
15
16
  segment: Segment;
16
17
  inputOptions?: string[];
@@ -38,6 +39,7 @@ export interface IDownloader extends EventEmitter {
38
39
  readonly getSavePath: (data: {
39
40
  startTime: number;
40
41
  title?: string;
42
+ extraMs?: boolean;
41
43
  }) => string;
42
44
  run(): void;
43
45
  stop(): Promise<void>;
@@ -5,6 +5,7 @@ import type { TrueVideoFormat } from "../index.js";
5
5
  export type GetSavePath = (data: {
6
6
  startTime: number;
7
7
  title?: string;
8
+ extraMs?: boolean;
8
9
  }) => string;
9
10
  type RecorderType = Exclude<RecorderCreateOpts["recorderType"], undefined | "auto">;
10
11
  export declare class Segment extends EventEmitter {
@@ -1,5 +1,6 @@
1
1
  import EventEmitter from "node:events";
2
2
  import fs from "fs/promises";
3
+ import fsSync from "fs";
3
4
  import { createRecordExtraDataController } from "../xml_stream_controller.js";
4
5
  import { ensureFolderExist, isFfmpegStartSegment, isMesioStartSegment, isBililiveStartSegment, isFfmpegStart, retry, cleanTerminalText, } from "../utils.js";
5
6
  export class Segment extends EventEmitter {
@@ -64,10 +65,19 @@ export class Segment extends EventEmitter {
64
65
  });
65
66
  }
66
67
  }
67
- this.outputVideoFilePath = this.getSavePath({
68
+ let recordSavePath = this.getSavePath({
68
69
  startTime: startTime,
69
- title: liveInfo?.title,
70
+ title: liveInfo?.title ? liveInfo.title : undefined,
70
71
  });
72
+ // 文件重复判断
73
+ if (fsSync.existsSync(recordSavePath + "." + this.videoExt)) {
74
+ recordSavePath = this.getSavePath({
75
+ startTime: startTime,
76
+ title: liveInfo?.title,
77
+ extraMs: true,
78
+ });
79
+ }
80
+ this.outputVideoFilePath = recordSavePath;
71
81
  ensureFolderExist(this.outputVideoFilePath);
72
82
  if (!this.disableDanma) {
73
83
  this.extraDataController = createRecordExtraDataController(`${this.outputVideoFilePath}.xml`);
@@ -112,12 +122,19 @@ export class StreamManager extends EventEmitter {
112
122
  callBack;
113
123
  constructor(getSavePath, hasSegment, disableDanma, recorderType, videoFormat, callBack) {
114
124
  super();
115
- const recordSavePath = getSavePath({ startTime: Date.now() });
116
- this.recordSavePath = recordSavePath;
125
+ const startTime = Date.now();
126
+ let recordSavePath = getSavePath({ startTime });
117
127
  this.videoFormat = videoFormat;
118
128
  this.recorderType = recorderType;
119
129
  this.hasSegment = hasSegment;
120
130
  this.callBack = callBack;
131
+ console.log("Initial recordSavePath:", recordSavePath);
132
+ // 文件重复判断
133
+ if (fsSync.existsSync(recordSavePath + "." + videoFormat)) {
134
+ console.log("File already exists, generating new save path with extraMs");
135
+ recordSavePath = getSavePath({ startTime, extraMs: true });
136
+ }
137
+ this.recordSavePath = recordSavePath;
121
138
  if (hasSegment) {
122
139
  this.segment = new Segment(getSavePath, disableDanma, this.videoExt);
123
140
  this.segment.on("DebugLog", (data) => {
@@ -131,6 +148,7 @@ export class StreamManager extends EventEmitter {
131
148
  });
132
149
  }
133
150
  else {
151
+ ensureFolderExist(recordSavePath);
134
152
  const extraDataSavePath = `${recordSavePath}.xml`;
135
153
  if (!disableDanma) {
136
154
  this.extraDataController = createRecordExtraDataController(extraDataSavePath);
package/lib/manager.d.ts CHANGED
@@ -125,6 +125,7 @@ export declare function genSavePathFromRule<ME extends AnyObject, P extends Reco
125
125
  startTime: number;
126
126
  liveStartTime: Date;
127
127
  recordStartTime: Date;
128
+ extraMs?: boolean;
128
129
  }): string;
129
130
  export type GetProviderExtra<P> = P extends RecorderProvider<infer E> ? E : never;
130
131
  export { StreamManager };
package/lib/manager.js CHANGED
@@ -381,6 +381,9 @@ export function genSavePathFromRule(manager, recorder, extData) {
381
381
  channelId,
382
382
  };
383
383
  let savePathRule = manager.savePathRule;
384
+ if (extData?.extraMs) {
385
+ savePathRule += "_{ms}";
386
+ }
384
387
  try {
385
388
  savePathRule = ejs.render(savePathRule, params);
386
389
  }
package/lib/recorder.d.ts CHANGED
@@ -93,6 +93,7 @@ export type GetSavePath = (data: {
93
93
  startTime: number;
94
94
  liveStartTime: Date;
95
95
  recordStartTime: Date;
96
+ extraMs?: boolean;
96
97
  }) => string;
97
98
  export interface Recorder<E extends AnyObject = UnknownObject> extends Emitter<{
98
99
  RecordStart: RecordHandle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bililive-tools/manager",
3
- "version": "1.14.1",
3
+ "version": "1.16.0",
4
4
  "description": "Batch scheduling recorders",
5
5
  "main": "./lib/index.js",
6
6
  "type": "module",