crabatool 1.0.849 → 1.0.853
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 +4 -3
- package/tool/evsockettool.js +79 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crabatool",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.853",
|
|
4
4
|
"description": "crabatool",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"sale-doc": "node ./test/test.js -convertJavadoc -targetPath F:/docs/sale -outPath F:/docs/sale.json",
|
|
14
14
|
"start": "node run.js",
|
|
15
15
|
"test": "node ./test/test.js",
|
|
16
|
-
"checkSale":"node ./test/test.js -checkjs -modName sale -webPath F:/sale/web/src/main/resources/static/sale -ignoreCheck /js/biz.js,/js/jquery.min.js,/_Sys/UI/SkinConfig.js,/_Sys/UI/SkinConfig.gspx,/Main.js,/js/content.min.js,/analysiscloud/ProductComboStatistics.js,/eshoporder/js/init.js,jarvis/js/biz/common.js,/jarvis/js/biz.js,/analysiscloud/LazyGrid.js,/analysiscloud/ProductComboStatistics.js,/analysiscloud/component/BaseQuery.js,/analysiscloud/js/init.js,/analysiscloud/component/ExtendCheckedQuery.js,/analysiscloud/Demob.js,/eshoporder/advance/,/analysiscloud/component/,/js/qrcode.min.js -globals recordsheet,AMap,shopsale -progress 0",
|
|
16
|
+
"checkSale": "node ./test/test.js -checkjs -modName sale -webPath F:/sale/web/src/main/resources/static/sale -ignoreCheck /js/biz.js,/js/jquery.min.js,/_Sys/UI/SkinConfig.js,/_Sys/UI/SkinConfig.gspx,/Main.js,/js/content.min.js,/analysiscloud/ProductComboStatistics.js,/eshoporder/js/init.js,jarvis/js/biz/common.js,/jarvis/js/biz.js,/analysiscloud/LazyGrid.js,/analysiscloud/ProductComboStatistics.js,/analysiscloud/component/BaseQuery.js,/analysiscloud/js/init.js,/analysiscloud/component/ExtendCheckedQuery.js,/analysiscloud/Demob.js,/eshoporder/advance/,/analysiscloud/component/,/js/qrcode.min.js -globals recordsheet,AMap,shopsale -progress 0",
|
|
17
17
|
"test_git": "node ./test/git.js -webPath F:/basicweb/www",
|
|
18
18
|
"run": "node ./test/test.js -run -webPath F:/basicweb/www -refresh true -proxy \"{'/shell/framework/':{'target':'http://127.0.0.1:8339','changeOrigin':true,'logLevel':'debug'}}\"",
|
|
19
19
|
"mergeinitjs": "node ./test/test.js -mergeinitjs",
|
|
@@ -84,7 +84,8 @@
|
|
|
84
84
|
"uglify-js": "^3.15.1",
|
|
85
85
|
"uglifycss": "^0.0.29",
|
|
86
86
|
"xml-js": "^1.6.11",
|
|
87
|
-
"xml-minifier": "^1.0.1"
|
|
87
|
+
"xml-minifier": "^1.0.1",
|
|
88
|
+
"qiniu": "^3.1.1"
|
|
88
89
|
},
|
|
89
90
|
"repository": {
|
|
90
91
|
"type": "git",
|
package/tool/evsockettool.js
CHANGED
|
@@ -12,7 +12,8 @@ var evConfig = {
|
|
|
12
12
|
watcher: null,
|
|
13
13
|
conn: null,
|
|
14
14
|
startTime: null,
|
|
15
|
-
connectTime: null
|
|
15
|
+
connectTime: null,
|
|
16
|
+
qiniuToken: null
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
// 监控的文件
|
|
@@ -42,6 +43,16 @@ function handleEvRecord(conn, message) {
|
|
|
42
43
|
startEvRecording(conn);
|
|
43
44
|
} else if (message.action === 'stop') {
|
|
44
45
|
stopEvRecording(conn);
|
|
46
|
+
} else if (message.action === 'setQiNiuToken') {
|
|
47
|
+
// 正确处理前端发送的token
|
|
48
|
+
var token = message.token;
|
|
49
|
+
log('收到七牛token:', token ? '已设置' : '空值');
|
|
50
|
+
evConfig.qiniuToken = token;
|
|
51
|
+
if (token) {
|
|
52
|
+
sendEvMessage(conn, 'msg', '七牛token已设置,请开始录制音视频;录制完成会自动上传七牛,并自动关联当前教学步骤。');
|
|
53
|
+
} else {
|
|
54
|
+
sendEvMessage(conn, 'error', '获取七牛token失败,无法上传音/视频到七牛,请联系服务中心。');
|
|
55
|
+
}
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
|
|
@@ -74,10 +85,10 @@ function startEvRecording(conn) {
|
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
log('找到ev录屏工具:', evPath);
|
|
77
|
-
|
|
88
|
+
|
|
78
89
|
// 无论启动成功还是失败,都先开始监听存储目录的变动
|
|
79
90
|
watchEvOutput(conn);
|
|
80
|
-
|
|
91
|
+
|
|
81
92
|
// 启动ev录屏工具
|
|
82
93
|
try {
|
|
83
94
|
// 使用spawn替代exec,避免编码问题
|
|
@@ -85,15 +96,15 @@ function startEvRecording(conn) {
|
|
|
85
96
|
windowsHide: true,
|
|
86
97
|
detached: true
|
|
87
98
|
});
|
|
88
|
-
|
|
99
|
+
|
|
89
100
|
var startupError = false;
|
|
90
|
-
|
|
101
|
+
|
|
91
102
|
child.on('error', function(error) {
|
|
92
103
|
startupError = true;
|
|
93
104
|
log('启动ev录屏工具失败:', error.message);
|
|
94
105
|
sendEvMessage(conn, 'started', '请手动启动,启动ev录屏工具失败: ' + error.message);
|
|
95
106
|
});
|
|
96
|
-
|
|
107
|
+
|
|
97
108
|
// 对于GUI应用程序,进程会在后台运行,不会立即退出
|
|
98
109
|
// 所以我们直接认为启动成功
|
|
99
110
|
setTimeout(function() {
|
|
@@ -102,7 +113,7 @@ function startEvRecording(conn) {
|
|
|
102
113
|
sendEvMessage(conn, 'started', 'ev录屏工具已启动,请开始录制');
|
|
103
114
|
}
|
|
104
115
|
}, 1000);
|
|
105
|
-
|
|
116
|
+
|
|
106
117
|
// 分离子进程,让它在后台运行
|
|
107
118
|
child.unref();
|
|
108
119
|
} catch (ex) {
|
|
@@ -158,7 +169,7 @@ function watchEvOutput(conn) {
|
|
|
158
169
|
var ext = path.extname(filePath).toLowerCase();
|
|
159
170
|
if (ext === '.mp3' || ext === '.wav' || ext === '.mp4') {
|
|
160
171
|
log('发现新的媒体文件:', filePath);
|
|
161
|
-
|
|
172
|
+
|
|
162
173
|
// 检查文件创建时间是否大于启动时间
|
|
163
174
|
try {
|
|
164
175
|
var stats = fs.statSync(filePath);
|
|
@@ -190,7 +201,11 @@ function watchEvOutput(conn) {
|
|
|
190
201
|
// 如果文件还没有被监控,开始监控
|
|
191
202
|
if (!monitoringFiles[filePath]) {
|
|
192
203
|
log('开始监控文件:', filePath, '当前大小:', stats.size, 'bytes');
|
|
204
|
+
// 先标记为监控中,防止短时间内重复触发
|
|
205
|
+
monitoringFiles[filePath] = true;
|
|
193
206
|
startMonitoringFile(conn, filePath);
|
|
207
|
+
} else {
|
|
208
|
+
log('文件已在监控中,跳过:', filePath);
|
|
194
209
|
}
|
|
195
210
|
} else {
|
|
196
211
|
log('文件创建时间不符合要求,跳过:', filePath);
|
|
@@ -208,27 +223,34 @@ function watchEvOutput(conn) {
|
|
|
208
223
|
|
|
209
224
|
// 监控文件大小变化,判断录制是否真正结束
|
|
210
225
|
function startMonitoringFile(conn, filePath) {
|
|
211
|
-
|
|
226
|
+
// 如果已经是一个有效的interval,说明已经在监控中
|
|
227
|
+
if (monitoringFiles[filePath] && monitoringFiles[filePath] !== true) {
|
|
228
|
+
log('文件已在监控中,跳过:', filePath);
|
|
212
229
|
return;
|
|
213
230
|
}
|
|
214
231
|
|
|
215
232
|
var lastSize = 0;
|
|
216
233
|
var stableCount = 0;
|
|
217
234
|
var hasGrowth = false;
|
|
218
|
-
|
|
235
|
+
|
|
219
236
|
// 根据文件类型设置不同的阈值
|
|
220
237
|
var ext = path.extname(filePath).toLowerCase();
|
|
221
238
|
var isVideo = ext === '.mp4';
|
|
222
239
|
var isAudio = ext === '.mp3' || ext === '.wav';
|
|
223
|
-
|
|
240
|
+
|
|
224
241
|
// MP4视频:帧率20fps,文件增长快,检查间隔1秒,稳定3次(3秒)即可判定完成
|
|
225
242
|
// MP3音频:码率128kbps,文件增长慢,检查间隔3秒,稳定2次(6秒)即可判定完成
|
|
226
243
|
var checkInterval = isVideo ? 1000 : (isAudio ? 3000 : 2000); // MP4: 1秒, MP3: 3秒, 其他: 2秒
|
|
227
244
|
var stableThreshold = isVideo ? 3 : (isAudio ? 2 : 3); // MP4: 3次(3秒), MP3: 2次(6秒), 其他: 3次
|
|
228
245
|
var minFileSize = isVideo ? 5000 : (isAudio ? 3000 : 1000); // MP4: 5KB, MP3: 3KB, 其他: 1KB
|
|
229
|
-
|
|
230
|
-
log('开始监控文件:', path.basename(filePath), '类型:', isVideo ? '视频' : (isAudio ? '音频' : '其他'),
|
|
231
|
-
|
|
246
|
+
|
|
247
|
+
log('开始监控文件:', path.basename(filePath), '类型:', isVideo ? '视频' : (isAudio ? '音频' : '其他'),
|
|
248
|
+
'检查间隔:', checkInterval + 'ms', '稳定阈值:', stableThreshold + '次');
|
|
249
|
+
|
|
250
|
+
// 清除之前的标记,设置为真正的interval
|
|
251
|
+
if (monitoringFiles[filePath] === true) {
|
|
252
|
+
delete monitoringFiles[filePath];
|
|
253
|
+
}
|
|
232
254
|
|
|
233
255
|
monitoringFiles[filePath] = setInterval(function() {
|
|
234
256
|
try {
|
|
@@ -263,46 +285,56 @@ function startMonitoringFile(conn, filePath) {
|
|
|
263
285
|
|
|
264
286
|
// 处理ev生成的文件
|
|
265
287
|
function processEvFile(conn, filePath) {
|
|
266
|
-
//
|
|
288
|
+
// 检查是否有七牛token
|
|
289
|
+
if (!evConfig.qiniuToken) {
|
|
290
|
+
log('没有七牛token,无法上传文件');
|
|
291
|
+
sendEvMessage(conn, 'error', '录制完成,但没有七牛token,无法上传文件');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
267
295
|
var fileName = path.basename(filePath);
|
|
268
296
|
var fileExt = path.extname(fileName);
|
|
269
297
|
var timestamp = new Date().getTime();
|
|
270
298
|
var qiniuFileName = 'ev-recording/' + timestamp + fileExt;
|
|
271
299
|
|
|
272
|
-
// 模拟七牛服务器返回的URL
|
|
273
|
-
var audioUrl = 'https://cdn.example.com/' + qiniuFileName;
|
|
274
|
-
|
|
275
|
-
// 这里应该实现真正的七牛上传逻辑
|
|
276
|
-
// 例如使用qiniu SDK上传文件
|
|
277
|
-
// const qiniu = require('qiniu');
|
|
278
|
-
// const formUploader = new qiniu.form_up.FormUploader();
|
|
279
|
-
// const putExtra = new qiniu.form_up.PutExtra();
|
|
280
|
-
// const bucket = 'your-bucket';
|
|
281
|
-
// const key = qiniuFileName;
|
|
282
|
-
// formUploader.putFile(uploadToken, key, filePath, putExtra, function(respErr, respBody, respInfo) {
|
|
283
|
-
// if (respErr) {
|
|
284
|
-
// sendEvMessage(conn, 'error', '上传失败: ' + respErr.message);
|
|
285
|
-
// } else {
|
|
286
|
-
// if (respInfo.statusCode == 200) {
|
|
287
|
-
// var audioUrl = 'https://cdn.example.com/' + respBody.key;
|
|
288
|
-
// sendEvMessage(conn, 'completed', '录制完成', { audioUrl: audioUrl });
|
|
289
|
-
// } else {
|
|
290
|
-
// sendEvMessage(conn, 'error', '上传失败: ' + respInfo.statusCode);
|
|
291
|
-
// }
|
|
292
|
-
// }
|
|
293
|
-
// });
|
|
294
|
-
|
|
295
|
-
// 模拟上传成功
|
|
296
|
-
log('模拟上传文件到七牛服务器:', filePath, '->', audioUrl);
|
|
297
|
-
|
|
298
300
|
// 确定文件类型
|
|
299
301
|
var fileType = fileExt.toLowerCase() === '.mp4' ? 'video' : 'audio';
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
// 尝试加载七牛SDK
|
|
305
|
+
var qiniu = require('qiniu');
|
|
306
|
+
var formUploader = new qiniu.form_up.FormUploader();
|
|
307
|
+
var putExtra = new qiniu.form_up.PutExtra();
|
|
308
|
+
|
|
309
|
+
log('开始上传文件到七牛服务器:', filePath);
|
|
310
|
+
|
|
311
|
+
// 上传文件
|
|
312
|
+
formUploader.putFile(evConfig.qiniuToken, qiniuFileName, filePath, putExtra, function(respErr, respBody, respInfo) {
|
|
313
|
+
if (respErr) {
|
|
314
|
+
log('上传失败:', respErr.message);
|
|
315
|
+
sendEvMessage(conn, 'error', '上传失败: ' + respErr.message);
|
|
316
|
+
} else {
|
|
317
|
+
if (respInfo.statusCode == 200) {
|
|
318
|
+
// 构建文件URL - 使用配置的CDN域名或从上传结果获取
|
|
319
|
+
var cdnDomain = config.qiniuCdnDomain || 'https://cdn.example.com';
|
|
320
|
+
var audioUrl = cdnDomain + '/' + respBody.key;
|
|
321
|
+
log('上传成功:', filePath, '->', audioUrl);
|
|
322
|
+
|
|
323
|
+
// 发送文件URL给前端,包含文件类型
|
|
324
|
+
sendEvMessage(conn, 'completed', '录制完成', {
|
|
325
|
+
audioUrl: audioUrl,
|
|
326
|
+
fileType: fileType
|
|
327
|
+
});
|
|
328
|
+
} else {
|
|
329
|
+
log('上传失败,状态码:', respInfo.statusCode);
|
|
330
|
+
sendEvMessage(conn, 'error', '上传失败: ' + respInfo.statusCode);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
} catch (ex) {
|
|
335
|
+
log('七牛上传失败:', ex.message);
|
|
336
|
+
sendEvMessage(conn, 'error', '七牛上传失败');
|
|
337
|
+
}
|
|
306
338
|
|
|
307
339
|
// 保持监控状态,等待下一次录制
|
|
308
340
|
}
|