-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
129 lines (119 loc) · 4.48 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const fs = require('fs-extra');
const path = require('path');
const crypto = require('crypto');
const cmd = require('shelljs');
const cachePath = './cache.json';
const hardTypeSet = new Set(["none", "qsv", "cuda"]);
const supportVideoTypeSet = new Set(["mkv", "mp4"]);
const replaceTextArr = ['h264', 'H264', 'x264', 'X264'];
let cache = {};
let timer = setInterval(saveFile, 5000);
function saveFile () {
console.log("保存数据");
fs.writeFileSync(cachePath, JSON.stringify(cache));
}
(async () => {
if (fs.existsSync(cachePath)) {
cache = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
}
await deal("Z:\\userData\\视频", 3000, true, "cuda");
if (timer) {
clearInterval(timer);
}
saveFile();
})();
/**
*
* @param {*} basePath 处理路径
* @param {int} maxBitRate 最大码率,默认2500
* @param {boolean} changeName 是否改名(true会将h264,x264变更为h265,或者在文件结尾插入h265,其他名称相同额文件也会处理)
* @param {*} hardType 硬件加速类型,空/none:不使用加速;qsv:使用intel核显qsv加速;cuda:使用nvdia cuda加速
* @returns
*/
async function deal (basePath, maxBitRate = 2500, changeName = false, hardType) {
let hwType = hardType == 'qsv' ? "-hwaccel qsv" : hardType == 'cuda' ? "-hwaccel cuda" : "";
let decodeType = hardType == 'qsv' ? "-c:v h264_qsv" : hardType == 'cuda' ? "-c:v h264_cuvid" : "";
let encodeType = hardType == 'qsv' ? "-c:v hevc_qsv" : hardType == 'cuda' ? "-c:v hevc_nvenc" : "";
if (hardType && !hardTypeSet.has(hardType)) {
throw new Error("不支持的加速方案:" + hardType + ",仅支持:空," + JSON.stringify(hardTypeSet));
}
let fileList = fs.readdirSync(basePath);
for (let i in fileList) {
let name = fileList[i];
let filePath = path.join(basePath, name);
if (!fs.existsSync(filePath)) {
continue;
}
if ((await fs.stat(filePath)).isDirectory()) {
//如果为文件夹递归处理
await deal(filePath, maxBitRate, changeName, hardType);
}
const md5Str = crypto.createHash('md5').update(filePath).digest('hex');
if (cache[md5Str]) {
continue;
}
cache[md5Str] = true;
if (!supportVideoTypeSet.has(name.substring(name.lastIndexOf(".") + 1))) {
continue;
}
console.log("---------开始处理:" + name);
let res = JSON.parse(cmd.exec(`ffprobe.exe "${filePath}" -show_streams -select_streams v -show_format -print_format json`, { encoding: 'utf-8' }).stdout);
if (!res.format || !res.streams || res.streams.length == 0) {
console.log("无法识别的格式:" + JSON.stringify(res));
continue;
}
let isH264 = res.streams.filter(item => item.codec_name === 'h264').length > 0;
if (!isH264) {
console.log("非h264,不处理");
continue;
}
let bitRate = res.format.bit_rate;
if (!bitRate) {
console.log("未获取到帧率,不处理", JSON.stringify(res));
continue;
}
let is10Bit = res.streams.filter(item => item.bits_per_raw_sample === '10').length > 0;
let originBitRate = Math.round(parseInt(bitRate) / 1000);
bitRate = originBitRate > maxBitRate ? maxBitRate : originBitRate * 0.7;
let newName = null;
replaceTextArr.forEach(item => {
if (newName == null && name.indexOf(item) > -1) {
newName = name.replace(item, 'h265');
}
})
if (newName == null) {
let index = name.lastIndexOf('.');
newName = name.substr(0, index) + ".h265" + name.substr(index);
}
let newFilePath = path.join(basePath, newName);
let cmdStr = `ffmpeg.exe ${hwType} ${is10Bit ? "" : decodeType} -i "${filePath}" -map 0 ${encodeType} -maxrate ${bitRate}K -c:a copy -c:s copy -y "${newFilePath}"`;
console.log(cmdStr);
let cmdRes = await cmd.exec(cmdStr);
let index = cmdRes.stderr.indexOf("video:");
if (index == -1) {
throw Error(cmdRes.stderr);
} else {
console.log("转换倍率:" + cmdRes.stderr.substring(index - 20));
}
if (!fs.existsSync(newFilePath) || fs.statSync(newFilePath).size <= 10000 || cmdRes.stderr.indexOf('Error') > -1) {
throw new Error("未知错误,文件转换失败");
}
if (changeName) {
//字幕,nfo文件重命名
let namePart1 = name.substr(0, name.lastIndexOf('.'));
let newNamePart1 = newName.substr(0, newName.lastIndexOf('.'));
fileList.forEach(item => {
if (item.startsWith(namePart1) && item != name) {
let temp = item.replace(namePart1, newNamePart1);
if (item != temp) {
fs.renameSync(path.join(basePath, item), path.join(basePath, temp));
}
}
})
}
await fs.remove(filePath);
if (!changeName) {
await fs.move(newFilePath, filePath);
}
}
}