bililive-cli 3.12.1 → 3.13.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.
@@ -11363,12 +11363,12 @@ const APP_DEFAULT_CONFIG = {
11363
11363
  hotProgressColor: "#f9f5f3",
11364
11364
  hotProgressFillColor: "#333333",
11365
11365
  convert2Mp4: false,
11366
- removeSourceAferrConvert2Mp4: true,
11367
11366
  flvRepair: false,
11368
11367
  syncId: undefined,
11369
11368
  uploadHandleTime: ["00:00:00", "23:59:59"],
11370
11369
  limitUploadTime: false,
11371
11370
  uploadNoDanmu: false,
11371
+ uploadToSameMedia: false,
11372
11372
  noDanmuVideoPreset: undefined,
11373
11373
  limitVideoConvertTime: false,
11374
11374
  videoHandleTime: ["00:00:00", "23:59:59"],
@@ -54494,7 +54494,7 @@ async function trash(paths, options) {
54494
54494
  } else if (process$2.platform === 'win32') {
54495
54495
  module = await Promise.resolve().then(function () { return require('./windows-OmnJ7a39.cjs'); });
54496
54496
  } else {
54497
- module = await Promise.resolve().then(function () { return require('./linux-CUI0soP3.cjs'); });
54497
+ module = await Promise.resolve().then(function () { return require('./linux-CXmRE85w.cjs'); });
54498
54498
  }
54499
54499
 
54500
54500
  return module.default(paths);
@@ -65707,8 +65707,9 @@ class Platform extends BaseRequest {
65707
65707
  */
65708
65708
  async editMediaWebApi(videos, options, mode) {
65709
65709
  this.auth.authLogin();
65710
+ const { sortByCid, ...mediaOptions } = options;
65710
65711
  const archive = await this.getArchive({
65711
- aid: options.aid,
65712
+ aid: mediaOptions.aid,
65712
65713
  });
65713
65714
  const archiveData = archive.archive;
65714
65715
  for (const key of [
@@ -65725,9 +65726,9 @@ class Platform extends BaseRequest {
65725
65726
  videos: [],
65726
65727
  ...archiveData,
65727
65728
  csrf: csrf,
65728
- ...options,
65729
+ ...mediaOptions,
65729
65730
  watermark: {
65730
- state: options.watermark?.state ?? archive.watermark.state,
65731
+ state: mediaOptions.watermark?.state ?? archive.watermark.state,
65731
65732
  },
65732
65733
  };
65733
65734
  this.checkOptions(data);
@@ -65740,10 +65741,10 @@ class Platform extends BaseRequest {
65740
65741
  data.desc = this.convertDescV2ToDesc(data.desc_v2);
65741
65742
  }
65742
65743
  if (mode === "append") {
65743
- data.videos = [...archive.videos, ...videos];
65744
+ data.videos = this.sortVideosByCid([...archive.videos, ...videos], sortByCid);
65744
65745
  }
65745
65746
  else if (mode === "replace") {
65746
- data.videos = videos;
65747
+ data.videos = this.sortVideosByCid(videos, sortByCid);
65747
65748
  }
65748
65749
  else {
65749
65750
  throw new Error("mode can only be append or replace");
@@ -65872,6 +65873,29 @@ class Platform extends BaseRequest {
65872
65873
  // }
65873
65874
  return true;
65874
65875
  }
65876
+ sortVideosByCid(videos, cidOrder) {
65877
+ if (!cidOrder || cidOrder.length === 0) {
65878
+ return videos;
65879
+ }
65880
+ const orderMap = new Map();
65881
+ cidOrder.forEach((cid, index) => {
65882
+ if (!orderMap.has(cid)) {
65883
+ orderMap.set(cid, index);
65884
+ }
65885
+ });
65886
+ const matchedVideos = [];
65887
+ const unmatchedVideos = [];
65888
+ videos.forEach(video => {
65889
+ const order = orderMap.get(video.cid);
65890
+ if (order === undefined) {
65891
+ unmatchedVideos.push(video);
65892
+ return;
65893
+ }
65894
+ matchedVideos.push({ video, order });
65895
+ });
65896
+ matchedVideos.sort((left, right) => left.order - right.order);
65897
+ return [...matchedVideos.map(item => item.video), ...unmatchedVideos];
65898
+ }
65875
65899
  /**
65876
65900
  * 获取推荐标签
65877
65901
  * subtype,title,description三个参数对结果影响较大
@@ -66923,7 +66947,10 @@ class Video extends BaseRequest {
66923
66947
  const duration = detail.View?.duration;
66924
66948
  if (!duration)
66925
66949
  throw new Error("视频时长获取失败");
66926
- const totalSegment = Math.ceil(duration / 360);
66950
+ const part = detail.View?.pages?.find((p) => p.cid === params.cid);
66951
+ if (!part)
66952
+ throw new Error("未找到对应cid的视频分P");
66953
+ const totalSegment = Math.ceil(part.duration / 360);
66927
66954
  const dmList = [];
66928
66955
  // 从1开始
66929
66956
  for (let i = 0; i < totalSegment; i++) {
@@ -179736,31 +179763,119 @@ async function drawSmoothLineChart(data, width, height) {
179736
179763
  return canvas$1;
179737
179764
  }
179738
179765
 
179766
+ const createEmptyXmlBuckets = () => ({
179767
+ danmu: [],
179768
+ sc: [],
179769
+ guard: [],
179770
+ gift: [],
179771
+ });
179772
+ const isXmlDanmuItemType = (value) => {
179773
+ return ["danmu", "sc", "guard", "gift"].includes(String(value));
179774
+ };
179775
+ const isValidXmlItemForType = (type, item) => {
179776
+ if (type === "danmu") {
179777
+ return typeof item["@_p"] === "string" && item["@_p"].length > 0;
179778
+ }
179779
+ return ((typeof item["@_ts"] === "string" && item["@_ts"].length > 0) ||
179780
+ typeof item["@_ts"] === "number");
179781
+ };
179782
+ const logInvalidTransformedItem = (reason, sourceType, item, targetType) => {
179783
+ logObj.error("filterFunction transform item dropped", {
179784
+ reason,
179785
+ sourceType,
179786
+ targetType,
179787
+ item,
179788
+ });
179789
+ };
179790
+ const createFilterFunction = (filterFunction) => {
179791
+ if (!filterFunction.includes("filter")) {
179792
+ return;
179793
+ }
179794
+ return new Function("type", "danmu", "logger", `
179795
+ ${filterFunction}
179796
+ return filter(type, danmu, logger);`);
179797
+ };
179798
+ const createTransformFunction = (filterFunction) => {
179799
+ if (!filterFunction.includes("transform")) {
179800
+ return;
179801
+ }
179802
+ return new Function("type", "danmu", "logger", `
179803
+ ${filterFunction}
179804
+ return transform(type, danmu, logger);`);
179805
+ };
179806
+ const transformXmlItem = (sourceType, item, transformFunc) => {
179807
+ const transformed = transformFunc(sourceType, item, logObj);
179808
+ if (transformed == null || transformed === false) {
179809
+ return null;
179810
+ }
179811
+ const candidate = transformed === true || transformed === undefined ? item : transformed;
179812
+ if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) {
179813
+ logInvalidTransformedItem("transform must return an object", sourceType, candidate);
179814
+ return null;
179815
+ }
179816
+ const nextType = "type" in candidate ? candidate.type : sourceType;
179817
+ if (!isXmlDanmuItemType(nextType)) {
179818
+ logInvalidTransformedItem("unsupported target type", sourceType, candidate, nextType);
179819
+ return null;
179820
+ }
179821
+ const normalizedItem = { ...candidate };
179822
+ delete normalizedItem.type;
179823
+ if (!isValidXmlItemForType(nextType, normalizedItem)) {
179824
+ logInvalidTransformedItem("missing required fields for target type", sourceType, candidate, nextType);
179825
+ return null;
179826
+ }
179827
+ return {
179828
+ type: nextType,
179829
+ item: normalizedItem,
179830
+ };
179831
+ };
179832
+ const processXmlItems = (events, filterFunction) => {
179833
+ const buckets = createEmptyXmlBuckets();
179834
+ const filterFunc = createFilterFunction(filterFunction);
179835
+ const transformFunc = createTransformFunction(filterFunction);
179836
+ for (const event of events) {
179837
+ if (filterFunc && !filterFunc(event.sourceType, event.item, logObj)) {
179838
+ continue;
179839
+ }
179840
+ if (!transformFunc) {
179841
+ buckets[event.sourceType].push(event.item);
179842
+ continue;
179843
+ }
179844
+ const transformedItem = transformXmlItem(event.sourceType, event.item, transformFunc);
179845
+ if (!transformedItem) {
179846
+ continue;
179847
+ }
179848
+ buckets[transformedItem.type].push(transformedItem.item);
179849
+ }
179850
+ return buckets;
179851
+ };
179852
+ const createXmlEvents = (items, sourceType) => {
179853
+ const result = [];
179854
+ for (const item of items) {
179855
+ result.push({
179856
+ sourceType,
179857
+ item,
179858
+ });
179859
+ }
179860
+ return result;
179861
+ };
179739
179862
  /**
179740
- * 生成过滤后的xml文件
179863
+ * 生成经过自定义处理后的xml文件
179741
179864
  * @param input
179742
179865
  * @param output
179743
- * @param filterFunction
179866
+ * @param options
179744
179867
  * @returns
179745
179868
  */
179746
- const genFilteredXml = async (input, output, filterFunction) => {
179747
- const filterFunc = new Function("type", "danmu", "logger", `
179748
- ${filterFunction}
179749
- return filter(type, danmu, logger);`);
179869
+ const genProcessedXml = async (input, output, filterFunction) => {
179750
179870
  const { jObj, danmuku, sc, guard, gift } = await parseXmlFile(input, true);
179751
- const filteredDanmuku = danmuku.filter((item) => {
179752
- return filterFunc("danmu", item, logObj);
179753
- });
179754
- const filteredSc = sc.filter((item) => {
179755
- return filterFunc("sc", item, logObj);
179756
- });
179757
- const filteredGuard = guard.filter((item) => {
179758
- return filterFunc("guard", item, logObj);
179759
- });
179760
- const filteredGift = gift.filter((item) => {
179761
- return filterFunc("gift", item, logObj);
179762
- });
179763
- const xmlData = generateMergedXmlContent(filteredDanmuku, filteredGift, filteredSc, filteredGuard, jObj.i?.metadata || {});
179871
+ const events = [
179872
+ ...createXmlEvents(danmuku, "danmu"),
179873
+ ...createXmlEvents(sc, "sc"),
179874
+ ...createXmlEvents(guard, "guard"),
179875
+ ...createXmlEvents(gift, "gift"),
179876
+ ];
179877
+ const processedBuckets = processXmlItems(events, filterFunction);
179878
+ const xmlData = generateMergedXmlContent(processedBuckets.danmu, processedBuckets.gift, processedBuckets.sc, processedBuckets.guard, jObj.i?.metadata || {});
179764
179879
  await fs$k.writeFile(output, xmlData);
179765
179880
  return output;
179766
179881
  };
@@ -179785,10 +179900,13 @@ const addConvertDanmu2AssTask = async (originInput, output, danmuOptions, option
179785
179900
  opts = await customChangeFunc(originInput, opts);
179786
179901
  }
179787
179902
  let filteredOutput;
179788
- if (opts.filterFunction && (opts.filterFunction ?? "").includes("filter")) {
179789
- // 如果存在自定义过滤函数,则需要把过滤后的xml保存到临时文件夹中
179903
+ const hasFilterFunction = Boolean((opts.filterFunction ?? "").trim()) && (opts.filterFunction ?? "").includes("filter");
179904
+ const hasTransformFunction = Boolean((opts.filterFunction ?? "").trim()) &&
179905
+ (opts.filterFunction ?? "").includes("transform");
179906
+ if (hasTransformFunction || hasFilterFunction) {
179907
+ // 如果存在自定义数据处理函数,则需要把处理后的xml保存到临时文件夹中
179790
179908
  filteredOutput = path$y.join(tempDir, `${uuid$5()}.xml`);
179791
- await genFilteredXml(originInput, filteredOutput, opts.filterFunction);
179909
+ await genProcessedXml(originInput, filteredOutput, opts.filterFunction);
179792
179910
  }
179793
179911
  if (opts.blacklist) {
179794
179912
  const fileTxtPath = path$y.join(tempDir, `${uuid$5()}.txt`);
@@ -181468,8 +181586,10 @@ async function addMediaApi(uid, video, options) {
181468
181586
  * 编辑视频接口
181469
181587
  */
181470
181588
  async function editMediaApi(uid, aid, video, options) {
181471
- const mediaOptions = {};
181472
- console.log("编辑视频", options);
181589
+ const mediaOptions = {
181590
+ sortByCid: options.sortByCid,
181591
+ };
181592
+ // console.log("编辑视频", options);
181473
181593
  // const globalConfig = container.resolve("globalConfig");
181474
181594
  // const mediaOptions = formatOptions(options, path.join(globalConfig.userDataPath, "cover"));
181475
181595
  const client = createClient(uid);
@@ -181808,6 +181928,7 @@ async function editMedia(aid, filePath, options, uid, extraOptions) {
181808
181928
  uid,
181809
181929
  mediaOptions: formattedOptions,
181810
181930
  aid,
181931
+ sortParams: extraOptions?.sortParams,
181811
181932
  }, {
181812
181933
  onEnd: async () => {
181813
181934
  // 审核检查
@@ -182159,6 +182280,8 @@ const biliApi = {
182159
182280
  editVideoPartName,
182160
182281
  queryVideoStatus,
182161
182282
  getPlayUrl,
182283
+ readUser,
182284
+ writeUser,
182162
182285
  };
182163
182286
 
182164
182287
  /**
@@ -184110,11 +184233,14 @@ class BiliPartVideoTask extends AbstractTask {
184110
184233
  logObj.error(`task ${this.taskId} error: ${error}`);
184111
184234
  }
184112
184235
  }
184113
- this.completedPart = data;
184236
+ this.completedPart = {
184237
+ ...data,
184238
+ filePath: this.command.filePath,
184239
+ };
184114
184240
  this.endTime = Date.now();
184115
184241
  // 重置进度追踪
184116
184242
  this.speedCalculator.reset();
184117
- callback.onEnd && callback.onEnd(data);
184243
+ callback.onEnd && callback.onEnd(this.completedPart);
184118
184244
  this.emitter.emit("task-end", { taskId: this.taskId });
184119
184245
  });
184120
184246
  command.emitter.on("error", (err) => {
@@ -184161,6 +184287,7 @@ class BiliPartVideoTask extends AbstractTask {
184161
184287
  cid: part.cid,
184162
184288
  filename: part.filename,
184163
184289
  title: this.command.title,
184290
+ filePath: this.command.filePath,
184164
184291
  };
184165
184292
  this.endTime = Date.now();
184166
184293
  // 重置进度追踪
@@ -184365,7 +184492,7 @@ class BiliAddVideoTask extends BiliVideoTask {
184365
184492
  this.progress = 100;
184366
184493
  this.callback.onEnd && this.callback.onEnd(data);
184367
184494
  this.output = String(data.aid);
184368
- this.emitter.emit("task-end", { taskId: this.taskId });
184495
+ this.emitter.emit("task-end", { taskId: this.taskId, data: parts });
184369
184496
  uploadPartService.removeByCids(parts.map((part) => part.cid));
184370
184497
  exports.statisticsService.addOrUpdate({
184371
184498
  where: { stat_key: this.lastUpdateTimeKey },
@@ -184391,10 +184518,12 @@ class BiliAddVideoTask extends BiliVideoTask {
184391
184518
  class BiliEditVideoTask extends BiliVideoTask {
184392
184519
  aid;
184393
184520
  mediaOptions;
184521
+ sortParams;
184394
184522
  constructor(options, callback) {
184395
184523
  super(options, callback);
184396
184524
  this.aid = options.aid;
184397
184525
  this.mediaOptions = options.mediaOptions;
184526
+ this.sortParams = options.sortParams;
184398
184527
  this.on("completed", () => {
184399
184528
  this.submit();
184400
184529
  });
@@ -184439,12 +184568,26 @@ class BiliEditVideoTask extends BiliVideoTask {
184439
184568
  return;
184440
184569
  }
184441
184570
  try {
184442
- const data = await retryWithAxiosError(() => editMediaApi(this.uid, this.aid, parts, this.mediaOptions), 5);
184571
+ const sortByCid = [];
184572
+ if (this.sortParams && Array.isArray(this.sortParams)) {
184573
+ for (const param of this.sortParams) {
184574
+ if (param.cid) {
184575
+ sortByCid.push(param.cid);
184576
+ }
184577
+ else {
184578
+ const part = parts.find((p) => p.filePath === param.filePath);
184579
+ if (part) {
184580
+ sortByCid.push(part.cid);
184581
+ }
184582
+ }
184583
+ }
184584
+ }
184585
+ const data = await retryWithAxiosError(() => editMediaApi(this.uid, this.aid, parts, { ...this.mediaOptions, sortByCid: sortByCid }), 5);
184443
184586
  this.status = "completed";
184444
184587
  this.progress = 100;
184445
184588
  this.callback.onEnd && this.callback.onEnd(data);
184446
184589
  this.output = String(data.aid);
184447
- this.emitter.emit("task-end", { taskId: this.taskId });
184590
+ this.emitter.emit("task-end", { taskId: this.taskId, data: parts });
184448
184591
  uploadPartService.removeByCids(parts.map((part) => part.cid));
184449
184592
  exports.statisticsService.addOrUpdate({
184450
184593
  where: { stat_key: this.lastUpdateTimeKey },
@@ -185517,7 +185660,7 @@ function getValuesFromArrayLikeFlexSpaceBetween(array, columnCount) {
185517
185660
  });
185518
185661
  return columnValues;
185519
185662
  }
185520
- function ensureFolderExist$5(fileOrFolderPath) {
185663
+ function ensureFolderExist(fileOrFolderPath) {
185521
185664
  const folder = path$y.dirname(fileOrFolderPath);
185522
185665
  if (!fs$D.existsSync(folder)) {
185523
185666
  fs$D.mkdirSync(folder, { recursive: true });
@@ -185926,7 +186069,7 @@ var utils$2 = {
185926
186069
  replaceExtName,
185927
186070
  singleton: singleton$1,
185928
186071
  getValuesFromArrayLikeFlexSpaceBetween,
185929
- ensureFolderExist: ensureFolderExist$5,
186072
+ ensureFolderExist,
185930
186073
  assert: assert$m,
185931
186074
  assertStringType,
185932
186075
  assertNumberType,
@@ -186408,11 +186551,20 @@ class Segment extends EventEmitter$j {
186408
186551
  });
186409
186552
  }
186410
186553
  }
186411
- this.outputVideoFilePath = this.getSavePath({
186554
+ let recordSavePath = this.getSavePath({
186412
186555
  startTime: startTime,
186413
- title: liveInfo?.title,
186556
+ title: liveInfo?.title ? liveInfo.title : undefined,
186414
186557
  });
186415
- ensureFolderExist$5(this.outputVideoFilePath);
186558
+ // 文件重复判断
186559
+ if (require$$0$6.existsSync(recordSavePath + "." + this.videoExt)) {
186560
+ recordSavePath = this.getSavePath({
186561
+ startTime: startTime,
186562
+ title: liveInfo?.title,
186563
+ extraMs: true,
186564
+ });
186565
+ }
186566
+ this.outputVideoFilePath = recordSavePath;
186567
+ ensureFolderExist(this.outputVideoFilePath);
186416
186568
  if (!this.disableDanma) {
186417
186569
  this.extraDataController = createRecordExtraDataController(`${this.outputVideoFilePath}.xml`);
186418
186570
  }
@@ -186456,12 +186608,19 @@ class StreamManager extends EventEmitter$j {
186456
186608
  callBack;
186457
186609
  constructor(getSavePath, hasSegment, disableDanma, recorderType, videoFormat, callBack) {
186458
186610
  super();
186459
- const recordSavePath = getSavePath({ startTime: Date.now() });
186460
- this.recordSavePath = recordSavePath;
186611
+ const startTime = Date.now();
186612
+ let recordSavePath = getSavePath({ startTime });
186461
186613
  this.videoFormat = videoFormat;
186462
186614
  this.recorderType = recorderType;
186463
186615
  this.hasSegment = hasSegment;
186464
186616
  this.callBack = callBack;
186617
+ console.log("Initial recordSavePath:", recordSavePath);
186618
+ // 文件重复判断
186619
+ if (require$$0$6.existsSync(recordSavePath + "." + videoFormat)) {
186620
+ console.log("File already exists, generating new save path with extraMs");
186621
+ recordSavePath = getSavePath({ startTime, extraMs: true });
186622
+ }
186623
+ this.recordSavePath = recordSavePath;
186465
186624
  if (hasSegment) {
186466
186625
  this.segment = new Segment(getSavePath, disableDanma, this.videoExt);
186467
186626
  this.segment.on("DebugLog", (data) => {
@@ -186475,6 +186634,7 @@ class StreamManager extends EventEmitter$j {
186475
186634
  });
186476
186635
  }
186477
186636
  else {
186637
+ ensureFolderExist(recordSavePath);
186478
186638
  const extraDataSavePath = `${recordSavePath}.xml`;
186479
186639
  if (!disableDanma) {
186480
186640
  this.extraDataController = createRecordExtraDataController(extraDataSavePath);
@@ -186932,6 +187092,9 @@ function genSavePathFromRule(manager, recorder, extData) {
186932
187092
  channelId,
186933
187093
  };
186934
187094
  let savePathRule = manager.savePathRule;
187095
+ if (extData?.extraMs) {
187096
+ savePathRule += "_{ms}";
187097
+ }
186935
187098
  try {
186936
187099
  savePathRule = ejs.render(savePathRule, params);
186937
187100
  }
@@ -187331,6 +187494,11 @@ class BililiveDownloader extends EventEmitter$j {
187331
187494
  if (timeMatch) {
187332
187495
  time = timeMatch[1];
187333
187496
  }
187497
+ const spaceMath = line.match(/下载进度:\s*([\d.]+\s*MB)\s*/);
187498
+ if (spaceMath) {
187499
+ const space = spaceMath[1];
187500
+ time = time ? `${time} ${space}` : space;
187501
+ }
187334
187502
  return {
187335
187503
  time,
187336
187504
  };
@@ -187590,7 +187758,7 @@ class FFmpegDownloader extends EventEmitter$j {
187590
187758
  let time = null;
187591
187759
  const timeMatch = line.match(/time=([0-9:.]+)/);
187592
187760
  if (timeMatch) {
187593
- time = timeMatch[1];
187761
+ time = timeMatch[1].split(".")[0];
187594
187762
  }
187595
187763
  return {
187596
187764
  time,
@@ -187694,12 +187862,6 @@ function getBililivePath() {
187694
187862
  return bililivePath;
187695
187863
  }
187696
187864
 
187697
- function ensureFolderExist$4(fileOrFolderPath) {
187698
- const folder = path$y.dirname(fileOrFolderPath);
187699
- if (!fs$D.existsSync(folder)) {
187700
- fs$D.mkdirSync(folder, { recursive: true });
187701
- }
187702
- }
187703
187865
  const uuid$1 = () => {
187704
187866
  return crypto$c.randomUUID();
187705
187867
  };
@@ -195043,6 +195205,7 @@ const checkLiveStatusAndRecord$4 = async function ({ getSavePath, banLiveId, isM
195043
195205
  startTime: opts.startTime,
195044
195206
  liveStartTime,
195045
195207
  recordStartTime,
195208
+ extraMs: opts.extraMs,
195046
195209
  }),
195047
195210
  disableDanma: this.disableProvideCommentsWhenRecording,
195048
195211
  videoFormat: this.videoFormat ?? "auto",
@@ -195052,20 +195215,6 @@ const checkLiveStatusAndRecord$4 = async function ({ getSavePath, banLiveId, isM
195052
195215
  const info = await getInfo$4(this.channelId);
195053
195216
  return info;
195054
195217
  });
195055
- const savePath = getSavePath({
195056
- owner,
195057
- title,
195058
- startTime: Date.now(),
195059
- liveStartTime,
195060
- recordStartTime,
195061
- });
195062
- try {
195063
- ensureFolderExist$4(savePath);
195064
- }
195065
- catch (err) {
195066
- this.state = "idle";
195067
- throw err;
195068
- }
195069
195218
  const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
195070
195219
  this.emit("videoFileCreated", { filename, cover, rawFilename });
195071
195220
  if (title && this?.liveInfo) {
@@ -195277,7 +195426,7 @@ const checkLiveStatusAndRecord$4 = async function ({ getSavePath, banLiveId, isM
195277
195426
  recorderType: downloader.type,
195278
195427
  url: stream.url,
195279
195428
  downloaderArgs,
195280
- savePath: savePath,
195429
+ savePath: downloader.videoFilePath,
195281
195430
  stop,
195282
195431
  cut,
195283
195432
  };
@@ -196180,12 +196329,6 @@ const requester$2 = axios.create({
196180
196329
  proxy: false,
196181
196330
  });
196182
196331
 
196183
- function ensureFolderExist$3(fileOrFolderPath) {
196184
- const folder = path$y.dirname(fileOrFolderPath);
196185
- if (!fs$D.existsSync(folder)) {
196186
- fs$D.mkdirSync(folder, { recursive: true });
196187
- }
196188
- }
196189
196332
  function assert$l(assertion, msg) {
196190
196333
  if (!assertion) {
196191
196334
  throw new Error(msg);
@@ -211223,6 +211366,7 @@ const checkLiveStatusAndRecord$3 = async function ({ getSavePath, banLiveId, isM
211223
211366
  startTime: opts.startTime,
211224
211367
  liveStartTime,
211225
211368
  recordStartTime,
211369
+ extraMs: opts.extraMs,
211226
211370
  }),
211227
211371
  disableDanma: this.disableProvideCommentsWhenRecording,
211228
211372
  videoFormat: this.videoFormat ?? "auto",
@@ -211234,20 +211378,6 @@ const checkLiveStatusAndRecord$3 = async function ({ getSavePath, banLiveId, isM
211234
211378
  const info = await getInfo$3(this.channelId);
211235
211379
  return info;
211236
211380
  });
211237
- const savePath = getSavePath({
211238
- owner,
211239
- title,
211240
- startTime: Date.now(),
211241
- liveStartTime,
211242
- recordStartTime,
211243
- });
211244
- try {
211245
- ensureFolderExist$3(savePath);
211246
- }
211247
- catch (err) {
211248
- this.state = "idle";
211249
- throw err;
211250
- }
211251
211381
  const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
211252
211382
  this.emit("videoFileCreated", { filename, cover, rawFilename });
211253
211383
  if (title && this?.liveInfo) {
@@ -211376,7 +211506,7 @@ const checkLiveStatusAndRecord$3 = async function ({ getSavePath, banLiveId, isM
211376
211506
  recorderType: downloader.type,
211377
211507
  url: stream.url,
211378
211508
  downloaderArgs,
211379
- savePath: savePath,
211509
+ savePath: downloader.videoFilePath,
211380
211510
  stop,
211381
211511
  cut,
211382
211512
  };
@@ -211413,12 +211543,6 @@ const provider$3 = {
211413
211543
  },
211414
211544
  };
211415
211545
 
211416
- function ensureFolderExist$2(fileOrFolderPath) {
211417
- const folder = path$y.dirname(fileOrFolderPath);
211418
- if (!fs$D.existsSync(folder)) {
211419
- fs$D.mkdirSync(folder, { recursive: true });
211420
- }
211421
- }
211422
211546
  function assert$j(assertion, msg) {
211423
211547
  if (!assertion) {
211424
211548
  throw new Error(msg);
@@ -212924,6 +213048,7 @@ const checkLiveStatusAndRecord$2 = async function ({ getSavePath, isManualStart,
212924
213048
  startTime: opts.startTime,
212925
213049
  liveStartTime: liveStartTime,
212926
213050
  recordStartTime,
213051
+ extraMs: opts.extraMs,
212927
213052
  }),
212928
213053
  formatName: streamOptions.format_name,
212929
213054
  disableDanma: this.disableProvideCommentsWhenRecording,
@@ -212936,20 +213061,6 @@ const checkLiveStatusAndRecord$2 = async function ({ getSavePath, isManualStart,
212936
213061
  const info = await getInfo$2(this.channelId);
212937
213062
  return info;
212938
213063
  });
212939
- const savePath = getSavePath({
212940
- owner,
212941
- title,
212942
- startTime: Date.now(),
212943
- liveStartTime: liveStartTime,
212944
- recordStartTime,
212945
- });
212946
- try {
212947
- ensureFolderExist$2(savePath);
212948
- }
212949
- catch (err) {
212950
- this.state = "idle";
212951
- throw err;
212952
- }
212953
213064
  const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
212954
213065
  this.emit("videoFileCreated", { filename, cover, rawFilename });
212955
213066
  if (title && this?.liveInfo) {
@@ -213052,7 +213163,7 @@ const checkLiveStatusAndRecord$2 = async function ({ getSavePath, isManualStart,
213052
213163
  recorderType: downloader.type,
213053
213164
  url: stream.url,
213054
213165
  downloaderArgs,
213055
- savePath: savePath,
213166
+ savePath: downloader.videoFilePath,
213056
213167
  stop,
213057
213168
  cut,
213058
213169
  };
@@ -213109,12 +213220,6 @@ function singleton(fn) {
213109
213220
  return promise;
213110
213221
  };
213111
213222
  }
213112
- function ensureFolderExist$1(fileOrFolderPath) {
213113
- const folder = path$y.dirname(fileOrFolderPath);
213114
- if (!fs$D.existsSync(folder)) {
213115
- fs$D.mkdirSync(folder, { recursive: true });
213116
- }
213117
- }
213118
213223
  function assert$i(assertion, msg) {
213119
213224
  if (!assertion) {
213120
213225
  throw new Error(msg);
@@ -249016,6 +249121,7 @@ const checkLiveStatusAndRecord$1 = async function ({ getSavePath, banLiveId, isM
249016
249121
  startTime: opts.startTime,
249017
249122
  liveStartTime: liveStartTime,
249018
249123
  recordStartTime,
249124
+ extraMs: opts.extraMs,
249019
249125
  }),
249020
249126
  disableDanma: this.disableProvideCommentsWhenRecording,
249021
249127
  videoFormat: this.videoFormat ?? "auto",
@@ -249030,20 +249136,6 @@ const checkLiveStatusAndRecord$1 = async function ({ getSavePath, banLiveId, isM
249030
249136
  });
249031
249137
  return info;
249032
249138
  });
249033
- const savePath = getSavePath({
249034
- owner,
249035
- title,
249036
- startTime: Date.now(),
249037
- liveStartTime,
249038
- recordStartTime,
249039
- });
249040
- try {
249041
- ensureFolderExist$1(savePath);
249042
- }
249043
- catch (err) {
249044
- this.state = "idle";
249045
- throw err;
249046
- }
249047
249139
  const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
249048
249140
  this.emit("videoFileCreated", { filename, cover, rawFilename });
249049
249141
  if (title && this?.liveInfo) {
@@ -249280,7 +249372,7 @@ const checkLiveStatusAndRecord$1 = async function ({ getSavePath, banLiveId, isM
249280
249372
  recorderType: downloader.type,
249281
249373
  url: stream.url,
249282
249374
  downloaderArgs,
249283
- savePath: savePath,
249375
+ savePath: downloader.videoFilePath,
249284
249376
  stop,
249285
249377
  cut,
249286
249378
  };
@@ -290180,13 +290272,6 @@ async function getStream(opts) {
290180
290272
  };
290181
290273
  }
290182
290274
 
290183
- function ensureFolderExist(fileOrFolderPath) {
290184
- const folder = path$y.dirname(fileOrFolderPath);
290185
- if (!fs$D.existsSync(folder)) {
290186
- fs$D.mkdirSync(folder, { recursive: true });
290187
- }
290188
- }
290189
-
290190
290275
  function createRecorder(opts) {
290191
290276
  // 内部实现时,应该只有 proxy 包裹的那一层会使用这个 recorder 标识符,不应该有直接通过
290192
290277
  // 此标志来操作这个对象的地方,不然会跳过 proxy 的拦截。
@@ -290357,6 +290442,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
290357
290442
  startTime: opts.startTime,
290358
290443
  liveStartTime,
290359
290444
  recordStartTime,
290445
+ extraMs: opts.extraMs,
290360
290446
  }),
290361
290447
  disableDanma: this.disableProvideCommentsWhenRecording,
290362
290448
  videoFormat: this.videoFormat ?? "auto",
@@ -290365,20 +290451,6 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
290365
290451
  const info = await getInfo(roomId);
290366
290452
  return info;
290367
290453
  });
290368
- const savePath = getSavePath({
290369
- owner,
290370
- title,
290371
- startTime: Date.now(),
290372
- liveStartTime,
290373
- recordStartTime,
290374
- });
290375
- try {
290376
- ensureFolderExist(savePath);
290377
- }
290378
- catch (err) {
290379
- this.state = "idle";
290380
- throw err;
290381
- }
290382
290454
  const handleVideoCreated = async ({ filename, title, cover, rawFilename }) => {
290383
290455
  this.emit("videoFileCreated", { filename, cover, rawFilename });
290384
290456
  if (title && this?.liveInfo) {
@@ -290445,7 +290517,7 @@ const checkLiveStatusAndRecord = async function ({ getSavePath, banLiveId, isMan
290445
290517
  recorderType: downloader.type,
290446
290518
  url: stream.url,
290447
290519
  downloaderArgs,
290448
- savePath: savePath,
290520
+ savePath: downloader.videoFilePath,
290449
290521
  stop,
290450
290522
  cut,
290451
290523
  };