tools_batch_files 1.0.33 → 1.0.35
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 +1 -1
- package/src/audioFn/audioBatch.js +133 -43
- package/utils/logger.js +11 -7
- package/utils/settleFiles.js +20 -4
package/package.json
CHANGED
@@ -13,6 +13,7 @@ const {
|
|
13
13
|
ensureDirSync,
|
14
14
|
isExist,
|
15
15
|
readTxt,
|
16
|
+
removeDirectory,
|
16
17
|
} = require("../../utils/settleFiles");
|
17
18
|
const ffmpeg = require("fluent-ffmpeg");
|
18
19
|
const fs = require("fs");
|
@@ -28,12 +29,22 @@ const queueCount = 10;
|
|
28
29
|
//起始任务下标
|
29
30
|
let taskIndex = 0;
|
30
31
|
|
32
|
+
//已完成数量
|
33
|
+
let completeCount = 0;
|
34
|
+
|
35
|
+
//错误文件重试次数
|
36
|
+
let retryError = 0;
|
37
|
+
|
31
38
|
//执行目录
|
32
39
|
const exeDir = __dirname;
|
33
40
|
//当前工作目录
|
34
41
|
const workDir = process.cwd();
|
35
|
-
|
36
|
-
|
42
|
+
|
43
|
+
// 表格目录,从excel文件夹中查找
|
44
|
+
const excelFiles = fs
|
45
|
+
.readdirSync(path.join(workDir, "excel"))
|
46
|
+
.find((file) => file.endsWith(".xlsx"));
|
47
|
+
const excelDir = path.join(workDir, "excel", excelFiles);
|
37
48
|
|
38
49
|
const ORIGIN_FILE_DIR = "audio";
|
39
50
|
const WM_AUDIO_DIR = "watermark_audio";
|
@@ -43,7 +54,13 @@ const ZIP_FILES_DIR = "zip";
|
|
43
54
|
//拷贝 - 存放上传失败的文件
|
44
55
|
const Error_Files_Dir = "failed_audio";
|
45
56
|
//水印
|
46
|
-
const watermarkAudioPath = path.join(
|
57
|
+
const watermarkAudioPath = path.join(
|
58
|
+
__dirname,
|
59
|
+
"..",
|
60
|
+
"..",
|
61
|
+
"vocal_print",
|
62
|
+
"mz.mp3"
|
63
|
+
);
|
47
64
|
const longWatermarkAudioPath = path.join(
|
48
65
|
__dirname,
|
49
66
|
"..",
|
@@ -72,7 +89,7 @@ const watermarkAudio = (indexFilePath, originFilePath, fileName, duration) => {
|
|
72
89
|
`[1:a]atrim=0:duration=${duration},volume=1.5[a1]`, // 对声纹音频流进行截取操作,并设置音量,重命名为a1
|
73
90
|
`[a0][a1]amix=inputs=2[a]`, // 合并两个音频流为一个输出流,重命名为a
|
74
91
|
`[a]volume=3.0`, // 设置输出音频的音量
|
75
|
-
]
|
92
|
+
];
|
76
93
|
|
77
94
|
if (duration <= 5) {
|
78
95
|
//直接合并,放在末尾,下次补上
|
@@ -103,7 +120,7 @@ const watermarkAudio = (indexFilePath, originFilePath, fileName, duration) => {
|
|
103
120
|
.input(originFilePath)
|
104
121
|
.input(vocalPath) // 声纹音频文件
|
105
122
|
|
106
|
-
.complexFilter(complexFilter)
|
123
|
+
.complexFilter(complexFilter.join(";"))
|
107
124
|
.output(outputFile)
|
108
125
|
.on("error", (err) => {
|
109
126
|
logger("添加声纹出错: " + err);
|
@@ -201,7 +218,7 @@ const archiveZip = (fileName, inputPath, originFilePath) => {
|
|
201
218
|
*/
|
202
219
|
const getMetadata = async (
|
203
220
|
originFilePath,
|
204
|
-
{ rowFileName, title, keyword,
|
221
|
+
{ rowFileName, title, keyword, anotherId }
|
205
222
|
) => {
|
206
223
|
//源音频数据
|
207
224
|
const photoMetadataComand = ffmpeg(originFilePath);
|
@@ -219,7 +236,7 @@ const getMetadata = async (
|
|
219
236
|
duration: "",
|
220
237
|
tag_ids: "3",
|
221
238
|
source_from: "sound_1",
|
222
|
-
anotherId
|
239
|
+
anotherId,
|
223
240
|
};
|
224
241
|
|
225
242
|
await new Promise((resolve, reject) => {
|
@@ -247,7 +264,7 @@ const getMetadata = async (
|
|
247
264
|
/**
|
248
265
|
* 接口
|
249
266
|
*/
|
250
|
-
const postData = (dataParams, indexFilePath) => {
|
267
|
+
const postData = (dataParams, indexFilePath, index) => {
|
251
268
|
const formData = new FormData();
|
252
269
|
|
253
270
|
const zipFiles = fs
|
@@ -264,11 +281,11 @@ const postData = (dataParams, indexFilePath) => {
|
|
264
281
|
}
|
265
282
|
}
|
266
283
|
|
267
|
-
logger(
|
284
|
+
logger(`第${index}条等待接口返回结果……`);
|
268
285
|
|
269
286
|
// return axios.post("http://192.168.102.61:9999/upload/sound", formData, {
|
270
|
-
// return axios.post("http://
|
271
|
-
return axios.post("http://
|
287
|
+
// return axios.post("http://192.168.101.149:9999/upload/sound", formData, {
|
288
|
+
return axios.post("http://127.0.0.1:9999/upload/sound", formData, {
|
272
289
|
headers: {
|
273
290
|
"Content-Type": "multipart/form-data",
|
274
291
|
},
|
@@ -284,24 +301,26 @@ async function postDataWithRetry(
|
|
284
301
|
indexFilePath,
|
285
302
|
index,
|
286
303
|
fileName,
|
287
|
-
hash
|
304
|
+
hash,
|
305
|
+
type
|
288
306
|
) {
|
289
307
|
let retryCount = 0; // 当前重试次数
|
290
308
|
|
291
309
|
while (retryCount < maxRetries) {
|
292
310
|
try {
|
293
|
-
const resData = await postData(dataParams, indexFilePath);
|
311
|
+
const resData = await postData(dataParams, indexFilePath, index);
|
294
312
|
if (resData.data.code === 200) {
|
295
313
|
logger("请求成功!");
|
296
314
|
logger(resData.data.code);
|
297
315
|
// 文件名和索引值
|
298
|
-
successLogger(hash, index, fileName);
|
299
|
-
|
316
|
+
successLogger(hash, index, fileName, type);
|
317
|
+
removeDirectory(indexFilePath);
|
300
318
|
return;
|
301
319
|
} else if (resData.data.code === 300) {
|
302
320
|
// 重复上传,不捕获此错误
|
321
|
+
logger(resData.data.code);
|
303
322
|
logger(`第${index}条文件-${index}重复上传!`);
|
304
|
-
|
323
|
+
removeDirectory(indexFilePath);
|
305
324
|
return;
|
306
325
|
} else {
|
307
326
|
logger(`请求失败,重试中... (${retryCount + 1}/${maxRetries})`);
|
@@ -321,13 +340,18 @@ async function postDataWithRetry(
|
|
321
340
|
/**
|
322
341
|
* 任务
|
323
342
|
*/
|
324
|
-
const task = async (row, index, hash) => {
|
343
|
+
const task = async (row, index, hash, type) => {
|
325
344
|
//index文件夹 output/0
|
326
345
|
const indexFilePath = path.join(workDir, "output", index + "");
|
327
346
|
let fileName = row.fileName;
|
328
347
|
const rowFileName = row.fileName;
|
329
348
|
const title = row.title;
|
330
349
|
const keyword = row.keyword;
|
350
|
+
/**
|
351
|
+
* 唯一标识符id,仅错误excel中有 anotherI d 列
|
352
|
+
*/
|
353
|
+
const anotherId = row.anotherId ? row.anotherId : excelFiles + index;
|
354
|
+
|
331
355
|
try {
|
332
356
|
logger(
|
333
357
|
"**************************" + row.fileName + "**************************"
|
@@ -370,7 +394,7 @@ const task = async (row, index, hash) => {
|
|
370
394
|
rowFileName,
|
371
395
|
title,
|
372
396
|
keyword,
|
373
|
-
|
397
|
+
anotherId,
|
374
398
|
});
|
375
399
|
await wavAudio(indexFilePath, originFilePath, fileName);
|
376
400
|
await watermarkAudio(
|
@@ -382,7 +406,14 @@ const task = async (row, index, hash) => {
|
|
382
406
|
await archiveZip(fileName, indexFilePath, originFilePath);
|
383
407
|
|
384
408
|
// 重试机制
|
385
|
-
await postDataWithRetry(
|
409
|
+
await postDataWithRetry(
|
410
|
+
dataParams,
|
411
|
+
indexFilePath,
|
412
|
+
index,
|
413
|
+
fileName,
|
414
|
+
hash,
|
415
|
+
type
|
416
|
+
);
|
386
417
|
|
387
418
|
logger(
|
388
419
|
`----------------------------------------第${index}条结束---------------------------------end`
|
@@ -394,8 +425,8 @@ const task = async (row, index, hash) => {
|
|
394
425
|
} else {
|
395
426
|
logger("音频任务失败(最外层catch):" + error);
|
396
427
|
}
|
397
|
-
|
398
|
-
disposeError(hash, { fileName, keyword, title });
|
428
|
+
removeDirectory(indexFilePath);
|
429
|
+
disposeError(hash, { fileName, keyword, title, anotherId });
|
399
430
|
|
400
431
|
//失败的时候,复制文件到错误文件夹中
|
401
432
|
// const failPath = path.join(workDir, Error_Files_Dir, fileName);
|
@@ -403,32 +434,41 @@ const task = async (row, index, hash) => {
|
|
403
434
|
}
|
404
435
|
};
|
405
436
|
|
406
|
-
const run = (index, data, hash) => {
|
437
|
+
const run = (index, data, hash, type) => {
|
407
438
|
try {
|
408
439
|
logger(
|
409
440
|
`run-------------------------------------第${index}条开始------------------------------------`
|
410
441
|
);
|
411
442
|
const row = data[index];
|
412
443
|
|
413
|
-
if (
|
444
|
+
if (completeCount >= data.length) {
|
414
445
|
taskIndex = 0;
|
415
|
-
logger(
|
446
|
+
logger(
|
447
|
+
index +
|
448
|
+
"=========================当前任务,最后一条已结束!========================="
|
449
|
+
);
|
450
|
+
|
451
|
+
successLogger(hash, index, "done");
|
416
452
|
|
417
453
|
// 是否存在错误列表? 存在的话,继续遍历
|
418
|
-
const
|
419
|
-
if (
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
logger("跑干了!");
|
454
|
+
const status = runErrorList(taskIndex, hash);
|
455
|
+
if (!status) {
|
456
|
+
logger(
|
457
|
+
"》》》》》》》》》》音频批量任务任务结束《《《《《《《《《《" + hash
|
458
|
+
);
|
424
459
|
}
|
425
460
|
|
426
461
|
return;
|
427
462
|
}
|
428
463
|
|
429
|
-
|
464
|
+
if (!row) {
|
465
|
+
return;
|
466
|
+
}
|
467
|
+
|
468
|
+
task(row, index, hash, type)
|
430
469
|
.then(() => {
|
431
470
|
taskIndex++;
|
471
|
+
completeCount++;
|
432
472
|
run(taskIndex, data, hash);
|
433
473
|
})
|
434
474
|
.catch((err) => {
|
@@ -436,15 +476,52 @@ const run = (index, data, hash) => {
|
|
436
476
|
});
|
437
477
|
} catch (error) {
|
438
478
|
logger("捕获错误!" + error);
|
479
|
+
completeCount++;
|
439
480
|
taskIndex++;
|
440
481
|
run(taskIndex, data, hash);
|
441
482
|
}
|
442
483
|
};
|
443
484
|
|
444
|
-
const queue = (
|
445
|
-
|
446
|
-
|
485
|
+
const queue = (index, jsonData, hash, type) => {
|
486
|
+
const rest = jsonData.length - index;
|
487
|
+
const count = queueCount > rest ? rest : queueCount;
|
488
|
+
const queueList = [];
|
489
|
+
completeCount = index;
|
490
|
+
|
491
|
+
for (let i = 0; i < count; i++) {
|
492
|
+
queueList.push(run(i + index, jsonData, hash, type));
|
447
493
|
}
|
494
|
+
|
495
|
+
taskIndex += count - 1;
|
496
|
+
return Promise.all(queueList);
|
497
|
+
};
|
498
|
+
|
499
|
+
//yunxing cuowu wenjian
|
500
|
+
const runErrorList = (index, hash, parentHash) => {
|
501
|
+
const fileHash = parentHash || hash;
|
502
|
+
const errorExcelPath = path.join(workDir, `error${fileHash}.xlsx`);
|
503
|
+
|
504
|
+
if (retryError > 5) {
|
505
|
+
console.log("出现无法解析的错误");
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
|
509
|
+
taskIndex = index;
|
510
|
+
let taskHash = hash;
|
511
|
+
//新的运行任务-重新赋予新的任务id
|
512
|
+
if (index === 0) {
|
513
|
+
taskHash = generateUniqueHash().slice(0, 8);
|
514
|
+
}
|
515
|
+
|
516
|
+
if (isExist(errorExcelPath)) {
|
517
|
+
retryError++;
|
518
|
+
|
519
|
+
logger("开始运行错误列表");
|
520
|
+
jsonData = readExcel(errorExcelPath); // 数据来源于error excel
|
521
|
+
queue(index, jsonData, taskHash, fileHash);
|
522
|
+
return true;
|
523
|
+
}
|
524
|
+
return false;
|
448
525
|
};
|
449
526
|
|
450
527
|
const main = () => {
|
@@ -459,18 +536,31 @@ const main = () => {
|
|
459
536
|
|
460
537
|
const successPath = path.join(workDir, "success.txt");
|
461
538
|
if (isExist(successPath)) {
|
462
|
-
const { loghash, lastItemIndex } =
|
463
|
-
|
464
|
-
logger("成功日志存在,异常中断或者跑完了。");
|
539
|
+
const { loghash, lastItemIndex, fileName, parentHash } =
|
540
|
+
readTxt(successPath);
|
465
541
|
|
466
542
|
hash = loghash;
|
467
|
-
taskIndex = lastItemIndex + 1; // lastItemIndex为最后一项,所有要+1
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
543
|
+
taskIndex = parseInt(lastItemIndex) + 1; // lastItemIndex为最后一项,所有要+1
|
544
|
+
|
545
|
+
//当前任务已经结束
|
546
|
+
if (fileName === "done") {
|
547
|
+
//找寻是否存在未上传的错误文件列表
|
548
|
+
const status = runErrorList(0, hash);
|
549
|
+
if (!status) {
|
550
|
+
logger(
|
551
|
+
"》》》》》》》》》》音频批量任务任务结束《《《《《《《《《《" + hash
|
552
|
+
);
|
553
|
+
}
|
472
554
|
} else {
|
473
|
-
|
555
|
+
//当前任务异常中断
|
556
|
+
|
557
|
+
//中断的任务类型为错误任务
|
558
|
+
if (parentHash) {
|
559
|
+
runErrorList(taskIndex, hash, parentHash);
|
560
|
+
} else {
|
561
|
+
jsonData = readExcel(excelDir);
|
562
|
+
queue(taskIndex, jsonData, hash);
|
563
|
+
}
|
474
564
|
}
|
475
565
|
} else {
|
476
566
|
hash = generateUniqueHash().slice(0, 8);
|
package/utils/logger.js
CHANGED
@@ -17,17 +17,21 @@ const logger = (log) => {
|
|
17
17
|
* 成功日志
|
18
18
|
* @param {*} 日志内容 hash index fileName
|
19
19
|
*/
|
20
|
-
const successLogger = (hash, index, fileName) => {
|
20
|
+
const successLogger = (hash, index, fileName, type = "") => {
|
21
21
|
console.log(fileName);
|
22
|
-
fs.writeFileSync(
|
23
|
-
|
24
|
-
|
22
|
+
fs.writeFileSync(
|
23
|
+
"success.txt",
|
24
|
+
hash + " " + index + " " + fileName + " " + type + "\n",
|
25
|
+
{
|
26
|
+
flag: "a",
|
27
|
+
}
|
28
|
+
);
|
25
29
|
};
|
26
30
|
|
27
31
|
//错误日志- xlsx
|
28
|
-
const disposeError = (hash, { fileName, keyword, title }) => {
|
32
|
+
const disposeError = (hash, { fileName, keyword, title, anotherId }) => {
|
29
33
|
// 构建 Excel 数据
|
30
|
-
const data = [[fileName, keyword, title]]; // 不包含表头
|
34
|
+
const data = [[fileName, keyword, title, anotherId]]; // 不包含表头
|
31
35
|
|
32
36
|
// 读取已存在的 Excel 文件
|
33
37
|
let existingData = [];
|
@@ -41,7 +45,7 @@ const disposeError = (hash, { fileName, keyword, title }) => {
|
|
41
45
|
} catch (error) {
|
42
46
|
logger("No existing file found, creating new one.");
|
43
47
|
// 如果文件不存在,添加表头
|
44
|
-
existingData.push(["fileName", "keyword", "title"]);
|
48
|
+
existingData.push(["fileName", "keyword", "title", "anotherId"]);
|
45
49
|
}
|
46
50
|
|
47
51
|
// 合并已有数据和新数据
|
package/utils/settleFiles.js
CHANGED
@@ -49,7 +49,7 @@ function isExist(filePath) {
|
|
49
49
|
console.log("存在");
|
50
50
|
return true;
|
51
51
|
} catch (err) {
|
52
|
-
console.log("
|
52
|
+
console.log("不存在");
|
53
53
|
console.error(err);
|
54
54
|
return false;
|
55
55
|
}
|
@@ -86,15 +86,30 @@ function readTxt(path) {
|
|
86
86
|
|
87
87
|
const lastItem = filteredArray[filteredArray.length - 1];
|
88
88
|
|
89
|
-
const loghash = lastItem.split(" ")
|
90
|
-
|
91
|
-
return { loghash, lastItemIndex };
|
89
|
+
const [loghash, lastItemIndex, fileName, parentHash] = lastItem.split(" ");
|
90
|
+
return { loghash, lastItemIndex, fileName, parentHash };
|
92
91
|
} catch (error) {
|
93
92
|
console.error("readErrorTxt函数出错:", error);
|
94
93
|
return {};
|
95
94
|
}
|
96
95
|
}
|
97
96
|
|
97
|
+
/**
|
98
|
+
* 确保文件存在,再删除
|
99
|
+
*/
|
100
|
+
function removeDirectory(directoryPath) {
|
101
|
+
try {
|
102
|
+
if (fs.existsSync(directoryPath)) {
|
103
|
+
fs.rmdirSync(directoryPath, { recursive: true });
|
104
|
+
console.log(`文件已删除: ${directoryPath}`);
|
105
|
+
} else {
|
106
|
+
console.log(`Directory does not exist: ${directoryPath}`);
|
107
|
+
}
|
108
|
+
} catch (error) {
|
109
|
+
console.error(`Error removing directory ${directoryPath}: ${error}`);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
98
113
|
module.exports = {
|
99
114
|
findFileInDir,
|
100
115
|
logFileSize,
|
@@ -102,4 +117,5 @@ module.exports = {
|
|
102
117
|
moveFailFiles,
|
103
118
|
isExist,
|
104
119
|
readTxt,
|
120
|
+
removeDirectory,
|
105
121
|
};
|