tools_batch_files 1.0.30 → 1.0.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tools_batch_files",
3
- "version": "1.0.30",
3
+ "version": "1.0.32",
4
4
  "description": "批处理视频工具",
5
5
  "keywords": [
6
6
  "utils",
@@ -34,8 +34,10 @@
34
34
  "files": [
35
35
  "index.js",
36
36
  "imgs",
37
+ "vocal_print",
37
38
  "点我批量上传视频.bat",
38
39
  "点我批量上传图片.bat",
40
+ "点我批量上传音频.bat",
39
41
  "package.json",
40
42
  "package-lock.json",
41
43
  "utils",
@@ -1,11 +1,19 @@
1
- const generateUniqueHash = require("../utils/index");
2
- const { disposeError, readExcel, logger } = require("../utils/logger");
1
+ #!/usr/bin/env node
2
+ const generateUniqueHash = require("../../utils/index");
3
+ const {
4
+ disposeError,
5
+ readExcel,
6
+ logger,
7
+ successLogger,
8
+ } = require("../../utils/logger");
3
9
 
4
10
  const {
5
11
  findFileInDir,
6
12
  logFileSize,
7
13
  ensureDirSync,
8
- } = require("../utils/settleFiles");
14
+ isExist,
15
+ readTxt,
16
+ } = require("../../utils/settleFiles");
9
17
  const ffmpeg = require("fluent-ffmpeg");
10
18
  const fs = require("fs");
11
19
  const path = require("path");
@@ -15,7 +23,7 @@ const axios = require("axios");
15
23
  const FormData = require("form-data");
16
24
 
17
25
  //并发数量
18
- const queueCount = 1;
26
+ const queueCount = 10;
19
27
 
20
28
  //起始任务下标
21
29
  let taskIndex = 0;
@@ -39,12 +47,12 @@ const watermarkAudioPath = path.join(__dirname, "..", "vocal_print", "mz.mp3");
39
47
  const longWatermarkAudioPath = path.join(
40
48
  __dirname,
41
49
  "..",
50
+ "..",
42
51
  "vocal_print",
43
52
  "800a.mp3"
44
53
  );
45
54
 
46
55
  const maxRetries = 1; // 最大重试次数
47
- let retryCount = 0; // 当前重试次数
48
56
 
49
57
  /**
50
58
  * 声纹
@@ -259,9 +267,9 @@ const postData = (dataParams, indexFilePath) => {
259
267
 
260
268
  logger("等待接口返回结果……");
261
269
 
262
- // return axios.post("http://127.0.0.1:9999/upload/photo", formData, {
263
270
  // return axios.post("http://192.168.102.61:9999/upload/sound", formData, {
264
- return axios.post("http://192.168.101.149:9999/upload/sound", formData, {
271
+ // return axios.post("http://192.168.101.149:9999/upload/sound", formData, {
272
+ return axios.post("http://127.0.0.1:9999/upload/sound", formData, {
265
273
  headers: {
266
274
  "Content-Type": "multipart/form-data",
267
275
  },
@@ -272,30 +280,42 @@ const postData = (dataParams, indexFilePath) => {
272
280
  /**
273
281
  * 接口重试机制
274
282
  */
275
- async function postDataWithRetry(dataParams, indexFilePath) {
283
+ async function postDataWithRetry(
284
+ dataParams,
285
+ indexFilePath,
286
+ index,
287
+ fileName,
288
+ hash
289
+ ) {
290
+ let retryCount = 0; // 当前重试次数
291
+
276
292
  while (retryCount < maxRetries) {
277
293
  try {
278
294
  const resData = await postData(dataParams, indexFilePath);
279
295
  if (resData.data.code === 200) {
280
296
  logger("请求成功!");
281
- logger(resData.data);
297
+ logger(resData.data.code);
298
+ // 文件名和索引值
299
+ successLogger(hash, index, fileName);
282
300
  fs.rmdirSync(indexFilePath, { recursive: true });
283
- return; // 请求成功,结束循环
301
+ return;
284
302
  } else if (resData.data.code === 300) {
285
303
  // 重复上传,不捕获此错误
286
304
  logger(`第${index}条文件-${index}重复上传!`);
287
305
  fs.rmdirSync(indexFilePath, { recursive: true });
288
- return; // 结束循环
306
+ return;
289
307
  } else {
290
308
  // 其他错误,抛出异常
291
- throw new Error("请求失败!" + resData.data);
309
+ throw new Error(
310
+ "请求code!==200:" + resData.data.code + resData.data.msg
311
+ );
292
312
  }
293
313
  } catch (error) {
294
314
  logger(`请求失败,重试中... (${retryCount + 1}/${maxRetries})`);
295
315
  logger(error);
296
316
  retryCount++;
297
317
  // 延时等待一段时间后再进行重试
298
- await new Promise((resolve) => setTimeout(resolve, 100)); // 等待1秒
318
+ await new Promise((resolve) => setTimeout(resolve, 100)); // 等待0.1秒
299
319
  }
300
320
  }
301
321
  // 如果达到最大重试次数仍然失败,则抛出异常
@@ -305,7 +325,7 @@ async function postDataWithRetry(dataParams, indexFilePath) {
305
325
  /**
306
326
  * 任务
307
327
  */
308
- const task = async (row, index) => {
328
+ const task = async (row, index, hash) => {
309
329
  try {
310
330
  logger(
311
331
  "**************************" + row.fileName + "**************************"
@@ -313,12 +333,11 @@ const task = async (row, index) => {
313
333
  // Excel的列名分别为: fileName title keyword
314
334
  let fileName = row.fileName;
315
335
  const title = row.title;
336
+ const keyword = row.keyword;
316
337
  // const keywordArr = row.keyword.split(",");
317
338
  // const filteredArray = keywordArr.filter((item) => item.trim() !== "");
318
339
  // const keyword = filteredArray.join(" ");
319
340
 
320
- const keyword = row.keyword;
321
-
322
341
  if (!fileName.includes(".")) {
323
342
  fileName = row.fileName + ".mp3";
324
343
  }
@@ -348,7 +367,6 @@ const task = async (row, index) => {
348
367
  //index文件夹 output/0
349
368
  const indexFilePath = path.join(workDir, "output", index + "");
350
369
 
351
- const workStartTime = new Date();
352
370
  await fs_asnyc.access(originFilePath, fs_asnyc.constants.F_OK);
353
371
  logFileSize(originFilePath);
354
372
  const dataParams = await getMetadata(
@@ -368,14 +386,9 @@ const task = async (row, index) => {
368
386
  dataParams.duration
369
387
  );
370
388
  await archiveZip(fileName, indexFilePath, originFilePath);
371
- const workEndTime = new Date();
372
- const timeInSeconds = ((workEndTime - workStartTime) / 1000).toFixed(2);
373
-
374
- logger(`第${index}条4090处理总时间:${timeInSeconds}秒`);
375
- logger(`-------------------${new Date()}------------------`);
376
389
 
377
390
  // 重试机制
378
- await postDataWithRetry(dataParams, indexFilePath);
391
+ await postDataWithRetry(dataParams, indexFilePath, index, fileName, hash);
379
392
 
380
393
  logger(
381
394
  `----------------------------------------第${index}条结束---------------------------------end`
@@ -385,55 +398,92 @@ const task = async (row, index) => {
385
398
  if (error.code === "ENOENT") {
386
399
  logger(`音频文件 ${fileName} 不存在`);
387
400
  } else {
388
- logger("音频任务处理失败:" + error);
401
+ logger("音频任务失败(最外层catch):" + error);
389
402
  }
390
403
  fs.rmdirSync(indexFilePath, { recursive: true });
391
- disposeError(fileName);
404
+ disposeError(hash, { fileName, keyword, title });
392
405
 
393
406
  //失败的时候,复制文件到错误文件夹中
394
- const failPath = path.join(workDir, Error_Files_Dir, fileName);
395
- moveFailFiles(originFilePath, failPath);
407
+ // const failPath = path.join(workDir, Error_Files_Dir, fileName);
408
+ // moveFailFiles(originFilePath, failPath);
409
+ }
410
+ };
411
+
412
+ const run = (index, data, hash) => {
413
+ try {
414
+ logger(
415
+ `run-------------------------------------第${index}条开始------------------------------------`
416
+ );
417
+ const row = data[index];
418
+
419
+ if (!row) {
420
+ taskIndex = 0;
421
+ logger("当前任务,最后一条已结束!");
422
+
423
+ // 是否存在错误列表? 存在的话,继续遍历
424
+ const errorExcelPath = path.join(workDir, `error${hash}.xlsx`);
425
+ if (isExist(errorExcelPath)) {
426
+ const jsonData2 = readExcel(errorExcelPath);
427
+ queue(taskIndex, jsonData2, hash);
428
+ } else {
429
+ logger("跑干了!");
430
+ }
431
+
432
+ return;
433
+ }
434
+
435
+ task(row, index)
436
+ .then(() => {
437
+ taskIndex++;
438
+ run(taskIndex, data, hash);
439
+ })
440
+ .catch((err) => {
441
+ throw new Error("task失败:" + err);
442
+ });
443
+ } catch (error) {
444
+ logger("捕获错误!" + error);
445
+ taskIndex++;
446
+ run(taskIndex, data, hash);
447
+ }
448
+ };
449
+
450
+ const queue = (taskIndex, jsonData, hash) => {
451
+ for (let i = 0; i < queueCount; i++) {
452
+ run(i + taskIndex, jsonData, hash);
396
453
  }
397
454
  };
398
455
 
399
456
  const main = () => {
400
457
  //当前任务hash
401
- const hashOrigin = generateUniqueHash();
402
- const hash = hashOrigin.slice(0, 8);
458
+ let hash = "";
459
+ let jsonData = [];
403
460
  logger("音频批量任务任务开始---" + hash);
404
- logger("当前目录: " + workDir + "工作目录: " + __dirname);
461
+ logger("当前目录: " + workDir + ";工作目录: " + exeDir);
405
462
 
406
- const jsonData = readExcel(excelDir);
463
+ // 读取success.txt,判断是否是 异常中断,
464
+ // 并根据success日志获取最后一行的hash,找到对应的error_hash_excel
407
465
 
408
- const run = (index) => {
409
- try {
410
- logger(
411
- `run-------------------------------------第${index}条开始------------------------------------`
412
- );
413
- const row = jsonData[index];
466
+ const successPath = path.join(workDir, "success.txt");
467
+ if (isExist(successPath)) {
468
+ const { loghash, lastItemIndex } = readTxt(successPath);
469
+ const errorExcelPath = path.join(workDir, `error${loghash}.xlsx`);
470
+ logger("成功日志存在,异常中断或者跑完了。");
414
471
 
415
- if (!row) {
416
- logger("最后一条已结束!");
417
- return;
418
- }
419
- task(row, index)
420
- .then(() => {
421
- taskIndex++;
422
- run(taskIndex);
423
- })
424
- .catch(() => {
425
- taskIndex++;
426
- run(taskIndex);
427
- });
428
- } catch (error) {
429
- logger("捕获错误!" + error);
430
- taskIndex++;
431
- run(taskIndex);
472
+ hash = loghash;
473
+ taskIndex = lastItemIndex + 1; // lastItemIndex为最后一项,所有要+1
474
+
475
+ if (isExist(errorExcelPath)) {
476
+ jsonData = readExcel(errorExcelPath); // 数据来源于error excel
477
+ queue(taskIndex, jsonData, hash);
478
+ } else {
479
+ logger("跑干了!");
432
480
  }
433
- };
481
+ } else {
482
+ hash = generateUniqueHash().slice(0, 8);
483
+ logger("成功日志不存在,开始新任务");
434
484
 
435
- for (let i = 0; i < queueCount; i++) {
436
- run(i + taskIndex);
485
+ jsonData = readExcel(excelDir);
486
+ queue(taskIndex, jsonData, hash);
437
487
  }
438
488
  };
439
489
 
package/utils/logger.js CHANGED
@@ -13,17 +13,53 @@ const logger = (log) => {
13
13
  });
14
14
  };
15
15
 
16
- //错误日志
17
- const disposeError = (err) => {
18
- logger("---任务失败---" + err);
19
- logger(
20
- `******************************************************************end`
21
- );
22
- fs.writeFileSync("error.txt", err + "\n", {
16
+ /**
17
+ * 成功日志
18
+ * @param {*} 日志内容 hash index fileName
19
+ */
20
+ const successLogger = (hash, index, fileName) => {
21
+ console.log(log);
22
+ fs.writeFileSync("success.txt", hash + " " + index + " " + fileName + "\n", {
23
23
  flag: "a",
24
24
  });
25
25
  };
26
26
 
27
+ //错误日志- xlsx
28
+ const disposeError = (hash, { fileName, keyword, title }) => {
29
+ // 构建 Excel 数据
30
+ const data = [[fileName, keyword, title]]; // 不包含表头
31
+
32
+ // 读取已存在的 Excel 文件
33
+ let existingData = [];
34
+ let existingWb;
35
+ try {
36
+ existingWb = XLSX.readFile(`error${hash}.xlsx`);
37
+ existingData = XLSX.utils.sheet_to_json(
38
+ existingWb.Sheets[existingWb.SheetNames[0]],
39
+ { header: 1 }
40
+ );
41
+ } catch (error) {
42
+ logger("No existing file found, creating new one.");
43
+ // 如果文件不存在,添加表头
44
+ existingData.push(["fileName", "keyword", "title"]);
45
+ }
46
+
47
+ // 合并已有数据和新数据
48
+ const combinedData = existingData.concat(data);
49
+
50
+ // 创建新的 sheet
51
+ const newWs = XLSX.utils.aoa_to_sheet(combinedData);
52
+
53
+ // 创建新的 workbook
54
+ const wb = XLSX.utils.book_new();
55
+
56
+ // 将新的 sheet 添加到 workbook
57
+ XLSX.utils.book_append_sheet(wb, newWs, "Error Details");
58
+
59
+ // 保存 Excel 文件
60
+ XLSX.writeFile(wb, `error${hash}.xlsx`);
61
+ };
62
+
27
63
  /**
28
64
  * 读取Excel
29
65
  * @param {*} path Excel路径
@@ -45,4 +81,5 @@ module.exports = {
45
81
  readExcel,
46
82
  logger,
47
83
  disposeError,
84
+ successLogger,
48
85
  };
@@ -40,6 +40,19 @@ function ensureDirSync(dirpath) {
40
40
  }
41
41
  }
42
42
 
43
+ /**
44
+ * 判断文件是否存在
45
+ */
46
+ function isExist(filePath) {
47
+ fs.access(filePath, fs.constants.F_OK, (err) => {
48
+ if (err) {
49
+ return false;
50
+ } else {
51
+ return true;
52
+ }
53
+ });
54
+ }
55
+
43
56
  /**
44
57
  * 上传失败后,存入新文件夹(手动创建)
45
58
  */
@@ -50,9 +63,27 @@ const moveFailFiles = (originFilePath, failPath) => {
50
63
  }
51
64
  };
52
65
 
66
+ //数组 item为:hash index fileName
67
+ function readTxt(path) {
68
+ try {
69
+ const data = fs.readFileSync(path, "utf-8");
70
+ const arr = data.split("\n").map((line) => line.trim()); // 删除每行两侧的空白符
71
+ const lastItem = arr[arr.length - 1];
72
+
73
+ const loghash = lastItem.split(" ")[0];
74
+ const lastItemIndex = lastItem.split(" ")[1];
75
+ return { loghash, lastItemIndex };
76
+ } catch (error) {
77
+ console.error("readErrorTxt函数出错:", error);
78
+ return {};
79
+ }
80
+ }
81
+
53
82
  module.exports = {
54
83
  findFileInDir,
55
84
  logFileSize,
56
85
  ensureDirSync,
57
86
  moveFailFiles,
87
+ isExist,
88
+ readTxt,
58
89
  };
Binary file
Binary file
Binary file