tools_batch_files 1.0.8 → 1.0.10
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/README.md +1 -2
- package/index.js +88 -37
- package/package.json +5 -3
package/README.md
CHANGED
package/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#!/usr/bin/env node
|
1
2
|
const XLSX = require("xlsx");
|
2
3
|
const ffmpeg = require("fluent-ffmpeg");
|
3
4
|
const fs = require("fs");
|
@@ -6,6 +7,7 @@ const fs_asnyc = require("fs").promises;
|
|
6
7
|
const archiver = require("archiver");
|
7
8
|
const axios = require("axios");
|
8
9
|
const generateUniqueHash = require("./utils/index");
|
10
|
+
const FormData = require("form-data");
|
9
11
|
|
10
12
|
//执行目录
|
11
13
|
const exeDir = __dirname;
|
@@ -25,11 +27,12 @@ const SCREENSHOT_DIR = "screenshots";
|
|
25
27
|
const ZIP_WATERMARK_VIDEO_DIR = "zip_watermark_video";
|
26
28
|
const ZIP_SCREENSHOT_DIR = "screenshot_watermark";
|
27
29
|
const SOURCE_VIDEO_DIR = "source_video";
|
30
|
+
const ZIP_FILES_DIR = "zip";
|
28
31
|
|
29
32
|
//并发数量
|
30
33
|
const queueCount = 1;
|
31
34
|
|
32
|
-
|
35
|
+
//起始任务下标
|
33
36
|
let taskIndex = 0;
|
34
37
|
|
35
38
|
/**
|
@@ -160,7 +163,7 @@ const compressVideo = (fileName, outputFileDir, inputFilePath) => {
|
|
160
163
|
resolve(outputFilePath);
|
161
164
|
})
|
162
165
|
.on("error", (err) => {
|
163
|
-
logger("视频压缩出错:"
|
166
|
+
logger("视频压缩出错:" + err);
|
164
167
|
reject(err);
|
165
168
|
})
|
166
169
|
.run();
|
@@ -181,6 +184,8 @@ const compressVideo400p = (fileName, outputFileDir, inputFilePath) => {
|
|
181
184
|
ensureDirSync(path.dirname(outputFilePath));
|
182
185
|
return new Promise((resolve, reject) => {
|
183
186
|
comand
|
187
|
+
.seekInput(0)
|
188
|
+
.inputOptions("-t 10")
|
184
189
|
.videoCodec("libx264")
|
185
190
|
.size("400x?")
|
186
191
|
|
@@ -329,10 +334,13 @@ const watermarkScreenshots = (indexFilePath) => {
|
|
329
334
|
const archiveZip = (fileName, inputPath) => {
|
330
335
|
const sourceVideoPath = path.join(workDir, "video", fileName);
|
331
336
|
const zipDir = path.join(inputPath, "zip");
|
337
|
+
const timestamp = new Date().getTime();
|
332
338
|
|
333
339
|
ensureDirSync(zipDir);
|
334
340
|
// create a file to stream archive data to.
|
335
|
-
const zipStream = fs.createWriteStream(
|
341
|
+
const zipStream = fs.createWriteStream(
|
342
|
+
path.join(zipDir, `package${timestamp}.zip`)
|
343
|
+
);
|
336
344
|
const archive = archiver("zip", {
|
337
345
|
zlib: { level: 9 }, // Sets the compression level.
|
338
346
|
});
|
@@ -371,7 +379,7 @@ const archiveZip = (fileName, inputPath) => {
|
|
371
379
|
SCREENSHOT_DIR,
|
372
380
|
ZIP_WATERMARK_VIDEO_DIR,
|
373
381
|
ZIP_SCREENSHOT_DIR,
|
374
|
-
ZIP_VIDEO_DIR_400
|
382
|
+
ZIP_VIDEO_DIR_400,
|
375
383
|
];
|
376
384
|
|
377
385
|
directories.forEach((dir) => {
|
@@ -390,7 +398,11 @@ const archiveZip = (fileName, inputPath) => {
|
|
390
398
|
/**
|
391
399
|
* 获取 元数据
|
392
400
|
*/
|
393
|
-
const getMetadata = async (
|
401
|
+
const getMetadata = async (
|
402
|
+
fileName,
|
403
|
+
indexFilePath,
|
404
|
+
{ rowFileName, title, keyword }
|
405
|
+
) => {
|
394
406
|
const inputFilePath = path.join(workDir, "video", fileName);
|
395
407
|
//第一张截图
|
396
408
|
const photoInputPath = path.join(
|
@@ -402,14 +414,25 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
402
414
|
const videoMetadataComand = ffmpeg(inputFilePath);
|
403
415
|
const photoMetadataComand = ffmpeg(photoInputPath);
|
404
416
|
const metaDataParams = {
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
417
|
+
userid: 1003,
|
418
|
+
username: "美好景象",
|
419
|
+
pixel_width: "",
|
420
|
+
pixel_height: "",
|
421
|
+
size: "",
|
422
|
+
duration: "",
|
423
|
+
video_id: rowFileName,
|
424
|
+
title,
|
425
|
+
keyword,
|
426
|
+
pr: 90,
|
427
|
+
format: "mp4",
|
428
|
+
category_id: 4,
|
429
|
+
demand_kind: 23,
|
430
|
+
source_from: 71,
|
431
|
+
plate_id: 5,
|
432
|
+
tag_id: 158,
|
433
|
+
is_government: 0,
|
434
|
+
preview_width: "",
|
435
|
+
preview_height: "",
|
413
436
|
};
|
414
437
|
await new Promise((resolve, reject) => {
|
415
438
|
videoMetadataComand.ffprobe(function (err, metadata) {
|
@@ -418,10 +441,10 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
418
441
|
);
|
419
442
|
const formatStream = metadata.format;
|
420
443
|
|
421
|
-
metaDataParams.
|
422
|
-
metaDataParams.
|
423
|
-
metaDataParams.
|
424
|
-
metaDataParams.
|
444
|
+
metaDataParams.pixel_width = videoStream.width;
|
445
|
+
metaDataParams.pixel_height = videoStream.height;
|
446
|
+
metaDataParams.duration = videoStream.duration;
|
447
|
+
metaDataParams.size = formatStream.size;
|
425
448
|
resolve();
|
426
449
|
});
|
427
450
|
});
|
@@ -432,8 +455,8 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
432
455
|
(s) => s.codec_type === "video"
|
433
456
|
);
|
434
457
|
|
435
|
-
metaDataParams.
|
436
|
-
metaDataParams.
|
458
|
+
metaDataParams.preview_width = photoStream.width;
|
459
|
+
metaDataParams.preview_height = photoStream.height;
|
437
460
|
resolve();
|
438
461
|
});
|
439
462
|
});
|
@@ -444,18 +467,30 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
444
467
|
/**
|
445
468
|
* 接口
|
446
469
|
*/
|
447
|
-
const postData = (
|
470
|
+
const postData = (dataParams, indexFilePath) => {
|
471
|
+
const formData = new FormData();
|
472
|
+
//风险:确保文件夹中只要一个zip文件,(因为时间戳,老的文件不会被覆盖)
|
473
|
+
const zipFiles = fs
|
474
|
+
.readdirSync(path.join(indexFilePath, ZIP_FILES_DIR))
|
475
|
+
.find((file) => file.endsWith(".zip"));
|
476
|
+
|
477
|
+
const packageZip = path.join(indexFilePath, ZIP_FILES_DIR, zipFiles);
|
478
|
+
|
479
|
+
formData.append("file", fs.createReadStream(packageZip));
|
480
|
+
for (const key in dataParams) {
|
481
|
+
if (Object.hasOwnProperty.call(dataParams, key)) {
|
482
|
+
const value = dataParams[key];
|
483
|
+
formData.append(key, value);
|
484
|
+
}
|
485
|
+
}
|
486
|
+
|
448
487
|
logger("等待接口返回结果……");
|
449
488
|
|
450
|
-
return axios.post(
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
"Content-Type": "multipart/form-data",
|
456
|
-
},
|
457
|
-
}
|
458
|
-
);
|
489
|
+
return axios.post("http://192.168.101.149:9999/upload/video", formData, {
|
490
|
+
headers: {
|
491
|
+
"Content-Type": "multipart/form-data",
|
492
|
+
},
|
493
|
+
});
|
459
494
|
};
|
460
495
|
|
461
496
|
/**
|
@@ -466,13 +501,22 @@ const task = async (row, index) => {
|
|
466
501
|
"**************************" + row.fileName + "**************************"
|
467
502
|
);
|
468
503
|
// Excel的列名分别为: fileName title keyword
|
469
|
-
|
470
|
-
|
504
|
+
// 表格中文件名无后缀,遂手动添加写死为mp4
|
505
|
+
let fileName = row.fileName;
|
506
|
+
const rowFileName = row.fileName;
|
507
|
+
const title = row.title;
|
508
|
+
const keyword = row.keyword;
|
509
|
+
|
510
|
+
if (!fileName.includes(".")) {
|
511
|
+
fileName = row.fileName + ".mp4";
|
512
|
+
}
|
513
|
+
|
514
|
+
// 源视频文件路径
|
471
515
|
const originFilePath = findFileInDir(
|
472
516
|
path.join(workDir, ORIGIN_FILE_DIR),
|
473
517
|
fileName
|
474
|
-
);
|
475
|
-
console.log("
|
518
|
+
);
|
519
|
+
console.log("源视频文件路径");
|
476
520
|
console.log(originFilePath);
|
477
521
|
|
478
522
|
//index文件夹 output/0
|
@@ -487,20 +531,27 @@ const task = async (row, index) => {
|
|
487
531
|
await watermarkVideo(fileName, indexFilePath);
|
488
532
|
await watermarkScreenshots(indexFilePath);
|
489
533
|
await archiveZip(fileName, indexFilePath);
|
490
|
-
const dataParams = await getMetadata(fileName, indexFilePath
|
491
|
-
|
534
|
+
const dataParams = await getMetadata(fileName, indexFilePath, {
|
535
|
+
rowFileName,
|
536
|
+
title,
|
537
|
+
keyword,
|
538
|
+
});
|
539
|
+
console.log("dataParams参数");
|
492
540
|
console.log(dataParams);
|
493
541
|
|
494
|
-
|
542
|
+
const resData = await postData(dataParams, indexFilePath);
|
543
|
+
logger(resData.data);
|
495
544
|
logger(
|
496
545
|
`----------------------------------------第${index}条结束---------------------------------end`
|
497
546
|
);
|
547
|
+
|
498
548
|
} catch (error) {
|
499
549
|
// 可以约定code,来表示不同的错误信息
|
500
550
|
if (error.code === "ENOENT") {
|
501
551
|
logger(`视频文件 ${fileName} 不存在`);
|
502
552
|
} else {
|
503
|
-
logger("
|
553
|
+
logger("视频处理失败:");
|
554
|
+
logger(error);
|
504
555
|
}
|
505
556
|
disposeError(hash, fileName);
|
506
557
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "tools_batch_files",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.10",
|
4
4
|
"description": "批处理视频工具",
|
5
5
|
"keywords": [
|
6
6
|
"utils",
|
@@ -10,11 +10,13 @@
|
|
10
10
|
],
|
11
11
|
"main": "index.js",
|
12
12
|
"bin": {
|
13
|
-
"tbf": "index.js"
|
13
|
+
"tbf": "./index.js"
|
14
14
|
},
|
15
15
|
"scripts": {
|
16
16
|
"test": "echo \"Error: no test specified\" && exit 1",
|
17
|
-
"start": "node index.js"
|
17
|
+
"start": "node index.js",
|
18
|
+
"batch-video": "node index.js",
|
19
|
+
"batch-photo": "node src/photoBatch.js"
|
18
20
|
},
|
19
21
|
"author": "zephyr",
|
20
22
|
"license": "ISC",
|