bililive-cli 3.22.2 → 4.1.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.
@@ -2,8 +2,8 @@
2
2
 
3
3
  var require$$0 = require('fs');
4
4
  var require$$0$1 = require('path');
5
- var index$1 = require('./index-Bqpkb00O.cjs');
6
- var index = require('./index-yHivC5bo.cjs');
5
+ var index$1 = require('./index-CyQ_VJuq.cjs');
6
+ var index = require('./index-BfVtxagW.cjs');
7
7
  require('node:dns');
8
8
  require('constants');
9
9
  require('stream');
@@ -1,10 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var path$3 = require('node:path');
4
3
  var http$4 = require('node:http');
5
- var urlLib = require('node:url');
6
4
  var https = require('node:https');
7
- var index$1 = require('./index-Bqpkb00O.cjs');
5
+ var index$1 = require('./index-CyQ_VJuq.cjs');
8
6
  var require$$0$5 = require('tty');
9
7
  var require$$1$4 = require('util');
10
8
  var require$$0$b = require('assert');
@@ -20,7 +18,9 @@ var require$$1$2 = require('http');
20
18
  var require$$4$1 = require('net');
21
19
  var require$$5$1 = require('querystring');
22
20
  var require$$17 = require('async_hooks');
21
+ var urlLib = require('node:url');
23
22
  var require$$1$5 = require('string_decoder');
23
+ var path$3 = require('node:path');
24
24
  var os$1 = require('node:os');
25
25
  var require$$1$6 = require('os');
26
26
  var require$$1$1 = require('node:child_process');
@@ -38,7 +38,6 @@ var require$$0$d = require('node:stream');
38
38
  var web = require('node:stream/web');
39
39
  var shazamioCore = require('shazamio-core');
40
40
 
41
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
42
41
  /**
43
42
  * 百度网盘上传类
44
43
  * 使用 BaiduPCS-Go 工具进行文件上传
@@ -48296,17 +48295,18 @@ router$h.post("/import", upload$1.single("file"), async (ctx) => {
48296
48295
  // 如果filename是 appConfig.json,那么替换掉ffmpegPath、ffprobePath、danmuFactoryPath配置
48297
48296
  if (filename === "appConfig.json") {
48298
48297
  const data = await index$1.fs.readJSON(path$3.join(userDataPath, `${filename}.backup`));
48299
- const appConfig = await index$1.fs.readJSON(configPath);
48300
- appConfig.ffmpegPath = data.ffmpegPath;
48301
- appConfig.ffprobePath = data.ffprobePath;
48302
- appConfig.danmuFactoryPath = data.danmuFactoryPath;
48303
- appConfig.mesioPath = data.mesioPath;
48304
- appConfig.bililiveRecorderPath = data.bililiveRecorderPath;
48305
- appConfig.audiowaveformPath = data.audiowaveformPath;
48306
- appConfig.webhook.recoderFolder = data.webhook.recoderFolder;
48307
- appConfig.recorder.savePath = data.recorder.savePath;
48308
- appConfig.losslessCutPath = data.losslessCutPath;
48309
- await index$1.fs.writeJSON(filePath, appConfig);
48298
+ const importedConfig = await index$1.fs.readJSON(configPath);
48299
+ importedConfig.ffmpegPath = data.ffmpegPath;
48300
+ importedConfig.ffprobePath = data.ffprobePath;
48301
+ importedConfig.danmuFactoryPath = data.danmuFactoryPath;
48302
+ importedConfig.mesioPath = data.mesioPath;
48303
+ importedConfig.bililiveRecorderPath = data.bililiveRecorderPath;
48304
+ importedConfig.audiowaveformPath = data.audiowaveformPath;
48305
+ importedConfig.webhook.recoderFolder = data.webhook.recoderFolder;
48306
+ importedConfig.recorder.savePath = data.recorder.savePath;
48307
+ importedConfig.losslessCutPath = data.losslessCutPath;
48308
+ await index$1.fs.writeJSON(filePath, importedConfig);
48309
+ appConfig.getAll();
48310
48310
  }
48311
48311
  }
48312
48312
  else if (filename === "app.db") {
@@ -62606,7 +62606,7 @@ class MultipartBody {
62606
62606
  let fileFromPathWarned = false;
62607
62607
  async function fileFromPath(path, ...args) {
62608
62608
  // this import fails in environments that don't handle export maps correctly, like old versions of Jest
62609
- const { fileFromPath: _fileFromPath } = await Promise.resolve().then(function () { return require('./fileFromPath-BycXkXgu.cjs'); });
62609
+ const { fileFromPath: _fileFromPath } = await Promise.resolve().then(function () { return require('./fileFromPath-DN6n6hnT.cjs'); });
62610
62610
  if (!fileFromPathWarned) {
62611
62611
  console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path)}) instead`);
62612
62612
  fileFromPathWarned = true;
@@ -73737,6 +73737,28 @@ const getRecordDuration = (record) => {
73737
73737
  return 0;
73738
73738
  };
73739
73739
  const toSessionKey = (record) => record.live_id || UNKNOWN_LIVE_ID;
73740
+ const parseDanmaTimeline = (value) => {
73741
+ if (!value)
73742
+ return undefined;
73743
+ try {
73744
+ const parsed = JSON.parse(value);
73745
+ const interval = parsed.danmaTimeline?.interval;
73746
+ const data = parsed.danmaTimeline?.data;
73747
+ if (typeof interval !== "number" ||
73748
+ !Number.isFinite(interval) ||
73749
+ interval <= 0 ||
73750
+ !Array.isArray(data)) {
73751
+ return undefined;
73752
+ }
73753
+ return {
73754
+ interval,
73755
+ data: data.map((item) => typeof item === "number" && Number.isFinite(item) && item >= 0 ? Math.round(item) : 0),
73756
+ };
73757
+ }
73758
+ catch {
73759
+ return undefined;
73760
+ }
73761
+ };
73740
73762
  const toSessionCard = (records) => {
73741
73763
  const sortedRecords = [...records].sort((left, right) => right.record_start_time - left.record_start_time);
73742
73764
  const latestRecord = sortedRecords[0] || null;
@@ -73771,6 +73793,7 @@ const toSessionCard = (records) => {
73771
73793
  video_duration: item.video_duration,
73772
73794
  danma_num: item.danma_num,
73773
73795
  interact_num: item.interact_num,
73796
+ danmaTimeline: parseDanmaTimeline(item.danma_stats_json),
73774
73797
  quick_hash: item.quick_hash,
73775
73798
  })),
73776
73799
  };
@@ -73838,8 +73861,15 @@ function queryStreamerDetail(args) {
73838
73861
  data: pagedCards,
73839
73862
  };
73840
73863
  }
73864
+ function queryRecordStartTimes(args) {
73865
+ const streamer = index$1.streamerService.query({ room_id: args.room_id, platform: args.platform });
73866
+ if (!streamer || args.startTime === undefined || args.endTime === undefined)
73867
+ return [];
73868
+ return index$1.recordHistoryService.getRecordStartTimes(streamer.id, args.startTime, args.endTime);
73869
+ }
73841
73870
  var streamerDetailService = {
73842
73871
  queryStreamerDetail,
73872
+ queryRecordStartTimes,
73843
73873
  };
73844
73874
 
73845
73875
  const router$b = new Router$1({
@@ -74030,6 +74060,43 @@ router$b.get("/detail", async (ctx) => {
74030
74060
  },
74031
74061
  };
74032
74062
  });
74063
+ router$b.get("/calendar", (ctx) => {
74064
+ const recorderId = getSingleQueryValue$1(ctx.request.query.recorderId);
74065
+ const startTime = Number(getSingleQueryValue$1(ctx.request.query.startTime));
74066
+ const endTime = Number(getSingleQueryValue$1(ctx.request.query.endTime));
74067
+ if (!recorderId ||
74068
+ !Number.isSafeInteger(startTime) ||
74069
+ !Number.isSafeInteger(endTime) ||
74070
+ startTime < 0 ||
74071
+ endTime <= startTime ||
74072
+ endTime - startTime > 32 * 24 * 60 * 60 * 1000) {
74073
+ ctx.status = 400;
74074
+ ctx.body = { message: "录制器和有效的月份时间范围不能为空" };
74075
+ return;
74076
+ }
74077
+ let recorder;
74078
+ try {
74079
+ recorder = recorderService.getRecorder({ id: recorderId });
74080
+ }
74081
+ catch {
74082
+ ctx.status = 404;
74083
+ ctx.body = { message: "录制器不存在" };
74084
+ return;
74085
+ }
74086
+ if (!recorder) {
74087
+ ctx.status = 404;
74088
+ ctx.body = { message: "录制器不存在" };
74089
+ return;
74090
+ }
74091
+ ctx.body = {
74092
+ payload: streamerDetailService.queryRecordStartTimes({
74093
+ room_id: recorder.channelId,
74094
+ platform: recorder.providerId,
74095
+ startTime,
74096
+ endTime,
74097
+ }),
74098
+ };
74099
+ });
74033
74100
  router$b.get("/ws/danma-test", async (ctx) => {
74034
74101
  ctx.status = 426;
74035
74102
  ctx.body = {
@@ -74046,7 +74113,7 @@ router$b.get("/ws/danma-test", async (ctx) => {
74046
74113
  };
74047
74114
  });
74048
74115
  router$b.post("/add", async (ctx) => {
74049
- const args = index$1.pick((ctx.request.body ?? {}), "providerId", "channelId", "remarks", "disableAutoCheck", "quality", "streamPriorities", "sourcePriorities", "extra", "noGlobalFollowFields", "line", "disableProvideCommentsWhenRecording", "saveGiftDanma", "saveSCDanma", "segment", "sendToWebhook", "uid", "saveCover", "convert2Mp4", "qualityRetry", "formatName", "useM3U8Proxy", "customHost", "codecName", "titleKeywords", "segmentOnTitleChange", "liveStartNotification", "chargeLiveNotification", "liveEndNotification", "weight", "source", "videoFormat", "recorderType", "cookie", "doubleScreen", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "api");
74116
+ const args = index$1.pick((ctx.request.body ?? {}), "providerId", "channelId", "remarks", "disableAutoCheck", "quality", "streamPriorities", "sourcePriorities", "extra", "noGlobalFollowFields", "line", "disableProvideCommentsWhenRecording", "saveGiftDanma", "saveSCDanma", "saveDanmaStats2DB", "segment", "sendToWebhook", "uid", "saveCover", "convert2Mp4", "qualityRetry", "formatName", "useM3U8Proxy", "customHost", "codecName", "titleKeywords", "segmentOnTitleChange", "liveStartNotification", "chargeLiveNotification", "liveEndNotification", "weight", "source", "videoFormat", "recorderType", "cookie", "doubleScreen", "cookieMode", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "api");
74050
74117
  const data = await recorderService.addRecorder(args);
74051
74118
  ctx.body = { payload: data };
74052
74119
  });
@@ -74075,7 +74142,7 @@ router$b.post("/:id/stream", async (ctx) => {
74075
74142
  });
74076
74143
  router$b.put("/:id", (ctx) => {
74077
74144
  const { id } = ctx.params;
74078
- const patch = index$1.pick(ctx.request.body, "remarks", "disableAutoCheck", "quality", "streamPriorities", "sourcePriorities", "noGlobalFollowFields", "line", "disableProvideCommentsWhenRecording", "saveGiftDanma", "saveSCDanma", "saveCover", "segment", "sendToWebhook", "uid", "qualityRetry", "formatName", "useM3U8Proxy", "customHost", "codecName", "titleKeywords", "segmentOnTitleChange", "liveStartNotification", "chargeLiveNotification", "liveEndNotification", "weight", "source", "videoFormat", "recorderType", "cookie", "doubleScreen", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "convert2Mp4", "api");
74145
+ const patch = index$1.pick(ctx.request.body, "remarks", "disableAutoCheck", "quality", "streamPriorities", "sourcePriorities", "noGlobalFollowFields", "line", "disableProvideCommentsWhenRecording", "saveGiftDanma", "saveSCDanma", "saveDanmaStats2DB", "saveCover", "segment", "sendToWebhook", "uid", "qualityRetry", "formatName", "useM3U8Proxy", "customHost", "codecName", "titleKeywords", "segmentOnTitleChange", "liveStartNotification", "chargeLiveNotification", "liveEndNotification", "weight", "source", "videoFormat", "recorderType", "cookie", "doubleScreen", "cookieMode", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "convert2Mp4", "api");
74079
74146
  ctx.body = { payload: recorderService.updateRecorder({ id, ...patch }) };
74080
74147
  });
74081
74148
  /**
@@ -74447,9 +74514,16 @@ router$a.post("/login", async (ctx) => {
74447
74514
  });
74448
74515
  tv.on("completed", async (res) => {
74449
74516
  loginObj[id].res = JSON.stringify(res);
74450
- loginObj[id].status = "completed";
74451
- const data = res.data;
74452
- await index$1.biliApi.addUser(data);
74517
+ try {
74518
+ const data = res.data;
74519
+ await index$1.biliApi.addUser(data);
74520
+ loginObj[id].uid = data.mid;
74521
+ loginObj[id].status = "completed";
74522
+ }
74523
+ catch (error) {
74524
+ loginObj[id].failReason = error instanceof Error ? error.message : String(error);
74525
+ loginObj[id].status = "error";
74526
+ }
74453
74527
  });
74454
74528
  const url = await tv.login();
74455
74529
  ctx.body = {
@@ -74495,6 +74569,20 @@ router$a.post("/formatTitle", async (ctx) => {
74495
74569
  const title = index$1.formatTitle(data.options, template);
74496
74570
  ctx.body = title;
74497
74571
  });
74572
+ router$a.post("/formatSeasonTitle", async (ctx) => {
74573
+ const { template, mediaTitleTemplate } = ctx.request.body;
74574
+ const options = {
74575
+ title: "标题",
74576
+ username: "主播名",
74577
+ time: new Date().toISOString(),
74578
+ roomId: 123456,
74579
+ filename: "文件名",
74580
+ };
74581
+ ctx.body = index$1.formatSeasonTitle({
74582
+ ...options,
74583
+ mediaTitle: index$1.formatTitle(options, mediaTitleTemplate || options.title),
74584
+ }, template);
74585
+ });
74498
74586
  router$a.post("/formatPartTitle", async (ctx) => {
74499
74587
  const data = ctx.request.body;
74500
74588
  const template = (data.template || "");
@@ -74568,7 +74656,7 @@ router$9.get("/login/poll", async (ctx) => {
74568
74656
  if (result.status === "completed") {
74569
74657
  index$1.writeDouyuUser(result.user);
74570
74658
  sessions.delete(id);
74571
- ctx.body = { status: "completed" };
74659
+ ctx.body = { status: "completed", uid: result.user.uid };
74572
74660
  return;
74573
74661
  }
74574
74662
  if (result.status === "error")
@@ -77251,6 +77339,7 @@ class ConfigManager {
77251
77339
  const appConfigAll = this.getAppConfigAll();
77252
77340
  const roomSetting = appConfigAll.webhook?.rooms?.[roomId];
77253
77341
  const danmu = this.getRoomSetting("danmu", roomSetting) ?? false;
77342
+ const burnWithoutDanmu = this.getRoomSetting("burnWithoutDanmu", roomSetting) ?? false;
77254
77343
  const mergePart = this.getRoomSetting("autoPartMerge", roomSetting) ?? false;
77255
77344
  const minSize = this.getRoomSetting("minSize", roomSetting) ?? 10;
77256
77345
  const uploadPresetId = this.getRoomSetting("uploadPresetId", roomSetting) || "default";
@@ -77312,6 +77401,7 @@ class ConfigManager {
77312
77401
  const open = this.canRoomOpen(roomSetting, appConfigAll?.webhook?.blacklist, roomId);
77313
77402
  return {
77314
77403
  danmu,
77404
+ burnWithoutDanmu,
77315
77405
  mergePart,
77316
77406
  minSize,
77317
77407
  uploadPresetId,
@@ -78428,7 +78518,8 @@ class WebhookHandler {
78428
78518
  async processDanmuVideo(context, options, config, xmlFilePath) {
78429
78519
  try {
78430
78520
  // 验证弹幕文件
78431
- if (!(await index$1.fs.pathExists(xmlFilePath)) || (await index$1.isEmptyDanmu(xmlFilePath))) {
78521
+ const hasDanmu = (await index$1.fs.pathExists(xmlFilePath)) && !(await index$1.isEmptyDanmu(xmlFilePath));
78522
+ if (!hasDanmu && !config.burnWithoutDanmu) {
78432
78523
  context.part.recordStatus = "handled";
78433
78524
  context.part.uploadStatus = "pending";
78434
78525
  index$1.logObj.warn(`弹幕文件不存在或为空,跳过弹幕压制: ${xmlFilePath}`);
@@ -78453,6 +78544,7 @@ class WebhookHandler {
78453
78544
  danmaOptions: danmuConfig.config,
78454
78545
  ffmpegOptions: ffmpegPreset.config,
78455
78546
  hasHotProgress: config.hotProgress,
78547
+ ignoreDanmu: !hasDanmu,
78456
78548
  hotProgressOptions: {
78457
78549
  interval: config.hotProgressSample || 30,
78458
78550
  color: config.hotProgressColor || "#f9f5f3",
@@ -78465,7 +78557,7 @@ class WebhookHandler {
78465
78557
  });
78466
78558
  context.part.filePath = output;
78467
78559
  context.part.recordStatus = "handled";
78468
- return { conversionSuccessful: true, danmuConversionSuccessful: true };
78560
+ return { conversionSuccessful: true, danmuConversionSuccessful: hasDanmu };
78469
78561
  }
78470
78562
  catch (error) {
78471
78563
  index$1.logObj.error(error);
@@ -79373,7 +79465,6 @@ let handler;
79373
79465
  let appConfig;
79374
79466
  let container;
79375
79467
  const fileCache = createFileCache();
79376
- path$3.dirname(urlLib.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index-yHivC5bo.cjs', document.baseURI).href))));
79377
79468
  const authMiddleware = (passKey) => {
79378
79469
  return async (ctx, next) => {
79379
79470
  const authHeader = ctx.headers["authorization"] || ctx.request.query.auth;