tools_batch_files 1.0.7 → 1.0.9
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 +123 -36
- package/package.json +5 -3
- package/utils/index.js +0 -0
package/README.md
CHANGED
package/index.js
CHANGED
@@ -6,6 +6,7 @@ const fs_asnyc = require("fs").promises;
|
|
6
6
|
const archiver = require("archiver");
|
7
7
|
const axios = require("axios");
|
8
8
|
const generateUniqueHash = require("./utils/index");
|
9
|
+
const FormData = require("form-data");
|
9
10
|
|
10
11
|
//执行目录
|
11
12
|
const exeDir = __dirname;
|
@@ -20,15 +21,17 @@ const watermarkImage = path.join(__dirname, "imgs", "miz-watermark.png");
|
|
20
21
|
const SCREENSHOT_COUNT = 5;
|
21
22
|
const ORIGIN_FILE_DIR = "video";
|
22
23
|
const ZIP_VIDEO_DIR = "zip_video";
|
23
|
-
const
|
24
|
+
const ZIP_VIDEO_DIR_400 = "small_video";
|
25
|
+
const SCREENSHOT_DIR = "screenshots";
|
24
26
|
const ZIP_WATERMARK_VIDEO_DIR = "zip_watermark_video";
|
25
27
|
const ZIP_SCREENSHOT_DIR = "screenshot_watermark";
|
26
28
|
const SOURCE_VIDEO_DIR = "source_video";
|
29
|
+
const ZIP_FILES_DIR = "zip";
|
27
30
|
|
28
31
|
//并发数量
|
29
32
|
const queueCount = 1;
|
30
33
|
|
31
|
-
|
34
|
+
//起始任务下标
|
32
35
|
let taskIndex = 0;
|
33
36
|
|
34
37
|
/**
|
@@ -158,6 +161,42 @@ const compressVideo = (fileName, outputFileDir, inputFilePath) => {
|
|
158
161
|
logger("视频压缩完成!");
|
159
162
|
resolve(outputFilePath);
|
160
163
|
})
|
164
|
+
.on("error", (err) => {
|
165
|
+
logger("视频压缩出错:" + err);
|
166
|
+
reject(err);
|
167
|
+
})
|
168
|
+
.run();
|
169
|
+
});
|
170
|
+
};
|
171
|
+
|
172
|
+
/**
|
173
|
+
* 压缩400p视频
|
174
|
+
*/
|
175
|
+
const compressVideo400p = (fileName, outputFileDir, inputFilePath) => {
|
176
|
+
const outputFilePath = path.join(
|
177
|
+
outputFileDir,
|
178
|
+
ZIP_VIDEO_DIR_400,
|
179
|
+
`zip-${fileName}`
|
180
|
+
);
|
181
|
+
const comand = ffmpeg(inputFilePath);
|
182
|
+
|
183
|
+
ensureDirSync(path.dirname(outputFilePath));
|
184
|
+
return new Promise((resolve, reject) => {
|
185
|
+
comand
|
186
|
+
.seekInput(0)
|
187
|
+
.inputOptions("-t 10")
|
188
|
+
.videoCodec("libx264")
|
189
|
+
.size("400x?")
|
190
|
+
|
191
|
+
.output(outputFilePath)
|
192
|
+
|
193
|
+
.on("start", () => {
|
194
|
+
logger("400p视频开始压缩……");
|
195
|
+
})
|
196
|
+
.on("end", () => {
|
197
|
+
logger("400p视频压缩完成!");
|
198
|
+
resolve(outputFilePath);
|
199
|
+
})
|
161
200
|
.on("error", (err) => {
|
162
201
|
logger("视频压缩出错:", err);
|
163
202
|
reject(err);
|
@@ -294,10 +333,13 @@ const watermarkScreenshots = (indexFilePath) => {
|
|
294
333
|
const archiveZip = (fileName, inputPath) => {
|
295
334
|
const sourceVideoPath = path.join(workDir, "video", fileName);
|
296
335
|
const zipDir = path.join(inputPath, "zip");
|
336
|
+
const timestamp = new Date().getTime();
|
297
337
|
|
298
338
|
ensureDirSync(zipDir);
|
299
339
|
// create a file to stream archive data to.
|
300
|
-
const zipStream = fs.createWriteStream(
|
340
|
+
const zipStream = fs.createWriteStream(
|
341
|
+
path.join(zipDir, `package${timestamp}.zip`)
|
342
|
+
);
|
301
343
|
const archive = archiver("zip", {
|
302
344
|
zlib: { level: 9 }, // Sets the compression level.
|
303
345
|
});
|
@@ -336,6 +378,7 @@ const archiveZip = (fileName, inputPath) => {
|
|
336
378
|
SCREENSHOT_DIR,
|
337
379
|
ZIP_WATERMARK_VIDEO_DIR,
|
338
380
|
ZIP_SCREENSHOT_DIR,
|
381
|
+
ZIP_VIDEO_DIR_400,
|
339
382
|
];
|
340
383
|
|
341
384
|
directories.forEach((dir) => {
|
@@ -354,7 +397,11 @@ const archiveZip = (fileName, inputPath) => {
|
|
354
397
|
/**
|
355
398
|
* 获取 元数据
|
356
399
|
*/
|
357
|
-
const getMetadata = async (
|
400
|
+
const getMetadata = async (
|
401
|
+
fileName,
|
402
|
+
indexFilePath,
|
403
|
+
{ rowFileName, title, keyword }
|
404
|
+
) => {
|
358
405
|
const inputFilePath = path.join(workDir, "video", fileName);
|
359
406
|
//第一张截图
|
360
407
|
const photoInputPath = path.join(
|
@@ -366,14 +413,25 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
366
413
|
const videoMetadataComand = ffmpeg(inputFilePath);
|
367
414
|
const photoMetadataComand = ffmpeg(photoInputPath);
|
368
415
|
const metaDataParams = {
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
416
|
+
userid: 1003,
|
417
|
+
username: "美好景象",
|
418
|
+
pixel_width: "",
|
419
|
+
pixel_height: "",
|
420
|
+
size: "",
|
421
|
+
duration: "",
|
422
|
+
video_id: rowFileName,
|
423
|
+
title,
|
424
|
+
keyword,
|
425
|
+
pr: 90,
|
426
|
+
format: "mp4",
|
427
|
+
category_id: 4,
|
428
|
+
demand_kind: 23,
|
429
|
+
source_from: 71,
|
430
|
+
plate_id: 5,
|
431
|
+
tag_id: 158,
|
432
|
+
is_government: 0,
|
433
|
+
preview_width: "",
|
434
|
+
preview_height: "",
|
377
435
|
};
|
378
436
|
await new Promise((resolve, reject) => {
|
379
437
|
videoMetadataComand.ffprobe(function (err, metadata) {
|
@@ -382,10 +440,10 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
382
440
|
);
|
383
441
|
const formatStream = metadata.format;
|
384
442
|
|
385
|
-
metaDataParams.
|
386
|
-
metaDataParams.
|
387
|
-
metaDataParams.
|
388
|
-
metaDataParams.
|
443
|
+
metaDataParams.pixel_width = videoStream.width;
|
444
|
+
metaDataParams.pixel_height = videoStream.height;
|
445
|
+
metaDataParams.duration = videoStream.duration;
|
446
|
+
metaDataParams.size = formatStream.size;
|
389
447
|
resolve();
|
390
448
|
});
|
391
449
|
});
|
@@ -396,8 +454,8 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
396
454
|
(s) => s.codec_type === "video"
|
397
455
|
);
|
398
456
|
|
399
|
-
metaDataParams.
|
400
|
-
metaDataParams.
|
457
|
+
metaDataParams.preview_width = photoStream.width;
|
458
|
+
metaDataParams.preview_height = photoStream.height;
|
401
459
|
resolve();
|
402
460
|
});
|
403
461
|
});
|
@@ -408,18 +466,30 @@ const getMetadata = async (fileName, indexFilePath) => {
|
|
408
466
|
/**
|
409
467
|
* 接口
|
410
468
|
*/
|
411
|
-
const postData = (
|
469
|
+
const postData = (dataParams, indexFilePath) => {
|
470
|
+
const formData = new FormData();
|
471
|
+
//风险:确保文件夹中只要一个zip文件,(因为时间戳,老的文件不会被覆盖)
|
472
|
+
const zipFiles = fs
|
473
|
+
.readdirSync(path.join(indexFilePath, ZIP_FILES_DIR))
|
474
|
+
.find((file) => file.endsWith(".zip"));
|
475
|
+
|
476
|
+
const packageZip = path.join(indexFilePath, ZIP_FILES_DIR, zipFiles);
|
477
|
+
|
478
|
+
formData.append("file", fs.createReadStream(packageZip));
|
479
|
+
for (const key in dataParams) {
|
480
|
+
if (Object.hasOwnProperty.call(dataParams, key)) {
|
481
|
+
const value = dataParams[key];
|
482
|
+
formData.append(key, value);
|
483
|
+
}
|
484
|
+
}
|
485
|
+
|
412
486
|
logger("等待接口返回结果……");
|
413
487
|
|
414
|
-
return axios.post(
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
"Content-Type": "multipart/form-data",
|
420
|
-
},
|
421
|
-
}
|
422
|
-
);
|
488
|
+
return axios.post("http://192.168.101.149:9999/upload/video", formData, {
|
489
|
+
headers: {
|
490
|
+
"Content-Type": "multipart/form-data",
|
491
|
+
},
|
492
|
+
});
|
423
493
|
};
|
424
494
|
|
425
495
|
/**
|
@@ -430,13 +500,22 @@ const task = async (row, index) => {
|
|
430
500
|
"**************************" + row.fileName + "**************************"
|
431
501
|
);
|
432
502
|
// Excel的列名分别为: fileName title keyword
|
433
|
-
|
434
|
-
|
503
|
+
// 表格中文件名无后缀,遂手动添加写死为mp4
|
504
|
+
let fileName = row.fileName;
|
505
|
+
const rowFileName = row.fileName;
|
506
|
+
const title = row.title;
|
507
|
+
const keyword = row.keyword;
|
508
|
+
|
509
|
+
if (!fileName.includes(".")) {
|
510
|
+
fileName = row.fileName + ".mp4";
|
511
|
+
}
|
512
|
+
|
513
|
+
// 源视频文件路径
|
435
514
|
const originFilePath = findFileInDir(
|
436
515
|
path.join(workDir, ORIGIN_FILE_DIR),
|
437
516
|
fileName
|
438
|
-
);
|
439
|
-
console.log("
|
517
|
+
);
|
518
|
+
console.log("源视频文件路径");
|
440
519
|
console.log(originFilePath);
|
441
520
|
|
442
521
|
//index文件夹 output/0
|
@@ -446,24 +525,32 @@ const task = async (row, index) => {
|
|
446
525
|
await fs_asnyc.access(originFilePath, fs_asnyc.constants.F_OK);
|
447
526
|
logFileSize(originFilePath);
|
448
527
|
await compressVideo(fileName, indexFilePath, originFilePath);
|
528
|
+
await compressVideo400p(fileName, indexFilePath, originFilePath);
|
449
529
|
await get5Screenshots(fileName, indexFilePath, originFilePath);
|
450
530
|
await watermarkVideo(fileName, indexFilePath);
|
451
531
|
await watermarkScreenshots(indexFilePath);
|
452
532
|
await archiveZip(fileName, indexFilePath);
|
453
|
-
const dataParams = await getMetadata(fileName, indexFilePath
|
454
|
-
|
533
|
+
const dataParams = await getMetadata(fileName, indexFilePath, {
|
534
|
+
rowFileName,
|
535
|
+
title,
|
536
|
+
keyword,
|
537
|
+
});
|
538
|
+
console.log("dataParams参数");
|
455
539
|
console.log(dataParams);
|
456
540
|
|
457
|
-
|
541
|
+
const resData = await postData(dataParams, indexFilePath);
|
542
|
+
logger(resData.data);
|
458
543
|
logger(
|
459
544
|
`----------------------------------------第${index}条结束---------------------------------end`
|
460
545
|
);
|
546
|
+
|
461
547
|
} catch (error) {
|
462
548
|
// 可以约定code,来表示不同的错误信息
|
463
549
|
if (error.code === "ENOENT") {
|
464
550
|
logger(`视频文件 ${fileName} 不存在`);
|
465
551
|
} else {
|
466
|
-
logger("
|
552
|
+
logger("视频处理失败:");
|
553
|
+
logger(error);
|
467
554
|
}
|
468
555
|
disposeError(hash, fileName);
|
469
556
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "tools_batch_files",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.9",
|
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": "
|
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",
|
package/utils/index.js
CHANGED
File without changes
|