bililive-cli 3.22.2 → 4.0.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.
@@ -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-CWkwaDmT.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-Cl9Q2SkN.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
  };
@@ -74046,7 +74069,7 @@ router$b.get("/ws/danma-test", async (ctx) => {
74046
74069
  };
74047
74070
  });
74048
74071
  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");
74072
+ 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", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "api");
74050
74073
  const data = await recorderService.addRecorder(args);
74051
74074
  ctx.body = { payload: data };
74052
74075
  });
@@ -74075,7 +74098,7 @@ router$b.post("/:id/stream", async (ctx) => {
74075
74098
  });
74076
74099
  router$b.put("/:id", (ctx) => {
74077
74100
  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");
74101
+ 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", "onlyAudio", "useServerTimestamp", "handleTime", "debugLevel", "convert2Mp4", "api");
74079
74102
  ctx.body = { payload: recorderService.updateRecorder({ id, ...patch }) };
74080
74103
  });
74081
74104
  /**
@@ -74495,6 +74518,20 @@ router$a.post("/formatTitle", async (ctx) => {
74495
74518
  const title = index$1.formatTitle(data.options, template);
74496
74519
  ctx.body = title;
74497
74520
  });
74521
+ router$a.post("/formatSeasonTitle", async (ctx) => {
74522
+ const { template, mediaTitleTemplate } = ctx.request.body;
74523
+ const options = {
74524
+ title: "标题",
74525
+ username: "主播名",
74526
+ time: new Date().toISOString(),
74527
+ roomId: 123456,
74528
+ filename: "文件名",
74529
+ };
74530
+ ctx.body = index$1.formatSeasonTitle({
74531
+ ...options,
74532
+ mediaTitle: index$1.formatTitle(options, mediaTitleTemplate || options.title),
74533
+ }, template);
74534
+ });
74498
74535
  router$a.post("/formatPartTitle", async (ctx) => {
74499
74536
  const data = ctx.request.body;
74500
74537
  const template = (data.template || "");
@@ -77251,6 +77288,7 @@ class ConfigManager {
77251
77288
  const appConfigAll = this.getAppConfigAll();
77252
77289
  const roomSetting = appConfigAll.webhook?.rooms?.[roomId];
77253
77290
  const danmu = this.getRoomSetting("danmu", roomSetting) ?? false;
77291
+ const burnWithoutDanmu = this.getRoomSetting("burnWithoutDanmu", roomSetting) ?? false;
77254
77292
  const mergePart = this.getRoomSetting("autoPartMerge", roomSetting) ?? false;
77255
77293
  const minSize = this.getRoomSetting("minSize", roomSetting) ?? 10;
77256
77294
  const uploadPresetId = this.getRoomSetting("uploadPresetId", roomSetting) || "default";
@@ -77312,6 +77350,7 @@ class ConfigManager {
77312
77350
  const open = this.canRoomOpen(roomSetting, appConfigAll?.webhook?.blacklist, roomId);
77313
77351
  return {
77314
77352
  danmu,
77353
+ burnWithoutDanmu,
77315
77354
  mergePart,
77316
77355
  minSize,
77317
77356
  uploadPresetId,
@@ -78428,7 +78467,8 @@ class WebhookHandler {
78428
78467
  async processDanmuVideo(context, options, config, xmlFilePath) {
78429
78468
  try {
78430
78469
  // 验证弹幕文件
78431
- if (!(await index$1.fs.pathExists(xmlFilePath)) || (await index$1.isEmptyDanmu(xmlFilePath))) {
78470
+ const hasDanmu = (await index$1.fs.pathExists(xmlFilePath)) && !(await index$1.isEmptyDanmu(xmlFilePath));
78471
+ if (!hasDanmu && !config.burnWithoutDanmu) {
78432
78472
  context.part.recordStatus = "handled";
78433
78473
  context.part.uploadStatus = "pending";
78434
78474
  index$1.logObj.warn(`弹幕文件不存在或为空,跳过弹幕压制: ${xmlFilePath}`);
@@ -78453,6 +78493,7 @@ class WebhookHandler {
78453
78493
  danmaOptions: danmuConfig.config,
78454
78494
  ffmpegOptions: ffmpegPreset.config,
78455
78495
  hasHotProgress: config.hotProgress,
78496
+ ignoreDanmu: !hasDanmu,
78456
78497
  hotProgressOptions: {
78457
78498
  interval: config.hotProgressSample || 30,
78458
78499
  color: config.hotProgressColor || "#f9f5f3",
@@ -78465,7 +78506,7 @@ class WebhookHandler {
78465
78506
  });
78466
78507
  context.part.filePath = output;
78467
78508
  context.part.recordStatus = "handled";
78468
- return { conversionSuccessful: true, danmuConversionSuccessful: true };
78509
+ return { conversionSuccessful: true, danmuConversionSuccessful: hasDanmu };
78469
78510
  }
78470
78511
  catch (error) {
78471
78512
  index$1.logObj.error(error);
@@ -79373,7 +79414,6 @@ let handler;
79373
79414
  let appConfig;
79374
79415
  let container;
79375
79416
  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
79417
  const authMiddleware = (passKey) => {
79378
79418
  return async (ctx, next) => {
79379
79419
  const authHeader = ctx.headers["authorization"] || ctx.request.query.auth;
package/lib/index.cjs CHANGED
@@ -3715,7 +3715,7 @@ const {
3715
3715
  Help,
3716
3716
  } = commander;
3717
3717
 
3718
- var version = "3.22.2";
3718
+ var version = "4.0.0";
3719
3719
 
3720
3720
  process.on("uncaughtException", function (error) {
3721
3721
  console.error(`${new Date().toISOString()} uncaughtException`, error);
@@ -3741,8 +3741,8 @@ program
3741
3741
  throw new Error(`${c.configFolder}参数不存在,请先重新运行 config gen 命令`);
3742
3742
  }
3743
3743
  // 下面两行顺序不能换(
3744
- const { init } = await Promise.resolve().then(function () { return require('./index-Bqpkb00O.cjs'); }).then(function (n) { return n.index; });
3745
- const { serverStart } = await Promise.resolve().then(function () { return require('./index-yHivC5bo.cjs'); }).then(function (n) { return n.index; });
3744
+ const { init } = await Promise.resolve().then(function () { return require('./index-CWkwaDmT.cjs'); }).then(function (n) { return n.index; });
3745
+ const { serverStart } = await Promise.resolve().then(function () { return require('./index-DonNRzzv.cjs'); }).then(function (n) { return n.index; });
3746
3746
  const globalConfig = {
3747
3747
  ffmpegPresetPath: path$1.join(c.configFolder, "ffmpeg_presets.json"),
3748
3748
  videoPresetPath: path$1.join(c.configFolder, "presets.json"),
@@ -4,7 +4,7 @@ var os$3 = require('node:os');
4
4
  var path$5 = require('node:path');
5
5
  var fs$3 = require('node:fs');
6
6
  var crypto = require('node:crypto');
7
- var index = require('./index-Bqpkb00O.cjs');
7
+ var index = require('./index-CWkwaDmT.cjs');
8
8
  var require$$0$1 = require('fs');
9
9
  var require$$0 = require('path');
10
10
  var require$$0$2 = require('child_process');
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "bililive-cli",
3
- "version": "3.22.2",
3
+ "version": "4.0.0",
4
4
  "type": "module",
5
5
  "description": "biliLive-tools的cli程序",
6
6
  "main": "./lib/index.js",
7
7
  "author": "renmu123",
8
8
  "license": "GPL-3.0",
9
9
  "homepage": "https://github.com/renmu123/biliLive-tools",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/renmu123/biliLive-tools",
13
+ "directory": "packages/CLI"
14
+ },
10
15
  "pkg": {
11
16
  "assets": "./lib/node_modules/**"
12
17
  },
@@ -25,8 +30,8 @@
25
30
  ],
26
31
  "dependencies": {
27
32
  "@napi-rs/canvas": "^1.0.9",
28
- "font-ls": "0.6.6",
29
- "better-sqlite3": "12.11.1",
33
+ "font-ls": "0.6.7",
34
+ "better-sqlite3": "13.0.3",
30
35
  "shazamio-core": "^1.3.1",
31
36
  "music-segment-detector": "^0.3.1"
32
37
  },
@@ -41,9 +46,9 @@
41
46
  "commander": "^12.1.0",
42
47
  "rimraf": "^6.0.1",
43
48
  "tsx": "^4.19.2",
44
- "@biliLive-tools/shared": "3.22.2",
45
- "@biliLive-tools/http": "3.22.2",
46
- "@biliLive-tools/types": "3.22.2"
49
+ "@biliLive-tools/shared": "4.0.0",
50
+ "@biliLive-tools/types": "4.0.0",
51
+ "@biliLive-tools/http": "4.0.0"
47
52
  },
48
53
  "scripts": {
49
54
  "start": "tsx src/index.ts",