ucservice 1.8.0 → 1.8.2
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/dist/ucservice.common.js +16 -1
- package/dist/ucservice.common.js.gz +0 -0
- package/dist/ucservice.common.js.map +1 -1
- package/dist/ucservice.css +1 -1
- package/dist/ucservice.umd.js +16 -1
- package/dist/ucservice.umd.js.gz +0 -0
- package/dist/ucservice.umd.js.map +1 -1
- package/dist/ucservice.umd.min.js +1 -1
- package/dist/ucservice.umd.min.js.gz +0 -0
- package/dist/ucservice.umd.min.js.map +1 -1
- package/package.json +4 -1
- package/index.js +0 -1268
- package/src/common-request.js +0 -162
- package/src/config.js +0 -15
- package/src/css/scooper.video.css +0 -343
- package/src/lib/cometd.js +0 -3286
- package/src/lib/janus.js +0 -3413
- package/src/lib/sha256.js +0 -250
- package/src/net_url/account_net_url.js +0 -481
- package/src/net_url/aduio_net_url.js +0 -337
- package/src/net_url/aduio_video_net_url.js +0 -187
- package/src/net_url/dept_ry_url.js +0 -479
- package/src/net_url/dept_url.js +0 -455
- package/src/net_url/location_url.js +0 -288
- package/src/net_url/meet_url.js +0 -413
- package/src/net_url/message_url.js +0 -432
- package/src/net_url/record_url.js +0 -228
- package/src/net_url/video_net_url.js +0 -79
- package/src/scooper-video-new.js +0 -3695
- package/src/scooper.dispatch.js +0 -3107
- package/src/scooper.video.js +0 -3937
- package/vue.config.js +0 -32
package/src/scooper.video.js
DELETED
|
@@ -1,3937 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* video工具类
|
|
4
|
-
* @author xiyongqiang
|
|
5
|
-
* @version 1.4.3
|
|
6
|
-
* @update 2019-12-13
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
(function (root, factory) {
|
|
10
|
-
if (typeof define === 'function' && define.amd) {
|
|
11
|
-
// AMD
|
|
12
|
-
define(['jquery', './lib/janus', 'webrtc-adapter'], factory);
|
|
13
|
-
} else if (typeof exports === 'object') {
|
|
14
|
-
// Node, CommonJS之类的
|
|
15
|
-
module.exports = factory(require('jquery'), require('./lib/janus'), require('webrtc-adapter'));
|
|
16
|
-
} else {
|
|
17
|
-
// 浏览器全局变量(root 即 window)
|
|
18
|
-
root.scooper = root.scooper || {};
|
|
19
|
-
|
|
20
|
-
root.scooper.video = factory(root.jQuery, root.Janus, root.adapter);
|
|
21
|
-
}
|
|
22
|
-
}(this, function ($, Janus, adapter) {
|
|
23
|
-
console.log(Janus);
|
|
24
|
-
console.log(adapter);
|
|
25
|
-
Janus = Janus.default;
|
|
26
|
-
adapter = adapter.default;
|
|
27
|
-
console.log("=====after default====");
|
|
28
|
-
console.log(Janus);
|
|
29
|
-
console.log(adapter);
|
|
30
|
-
"use strict";
|
|
31
|
-
|
|
32
|
-
window.console = window.console || (function(){
|
|
33
|
-
let c = {}; c.log = c.warn = c.debug = c.info = c.error = c.time = c.dir = c.profile
|
|
34
|
-
= c.clear = c.exception = c.trace = c.assert = function(){};
|
|
35
|
-
return c;
|
|
36
|
-
})();
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 立即执行函数形式
|
|
40
|
-
* 兼容IE8 indexOf
|
|
41
|
-
*/
|
|
42
|
-
(function () {
|
|
43
|
-
if(Array.prototype.indexOf) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
Array.prototype.indexOf = function(item) {
|
|
47
|
-
let len = this.length >>> 0; //保证结构为非负数
|
|
48
|
-
|
|
49
|
-
for(let i = 0; i<len ; i++) {
|
|
50
|
-
if(i in this && this[i] === item) {
|
|
51
|
-
return i;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return -1;
|
|
55
|
-
}
|
|
56
|
-
})();
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 闭包
|
|
60
|
-
* 为事件添加唯一标识字符串
|
|
61
|
-
*/
|
|
62
|
-
let guid = (function() {
|
|
63
|
-
let id = 1;
|
|
64
|
-
return function() {
|
|
65
|
-
return 'SCVIDEO_ID_'+ (++id).toString();
|
|
66
|
-
}
|
|
67
|
-
})();
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* 公共方法
|
|
71
|
-
* 判断是否为IE
|
|
72
|
-
*/
|
|
73
|
-
function isIE() {
|
|
74
|
-
return !!window.ActiveXObject || "ActiveXObject" in window;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 公共方法
|
|
79
|
-
* 克隆对象
|
|
80
|
-
* 让新出来的对象是独立的
|
|
81
|
-
*/
|
|
82
|
-
function cloneObj(obj) {
|
|
83
|
-
let str, newObj = $.isArray(obj)?[]:{};
|
|
84
|
-
if ( typeof obj != 'object' ) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (window.JSON) {
|
|
89
|
-
str = JSON.stringify(obj);
|
|
90
|
-
newObj = JSON.parse(str);
|
|
91
|
-
} else {
|
|
92
|
-
$.each(obj,function(key,val) {
|
|
93
|
-
newObj[key] = typeof val == 'object' ? cloneObj(val) : val;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return newObj;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 公共方法
|
|
101
|
-
* 提示
|
|
102
|
-
*/
|
|
103
|
-
let showPrompt = true;
|
|
104
|
-
function promptSuccess(msg, type) {
|
|
105
|
-
console.log(msg);
|
|
106
|
-
//panduanpromptView弹层对象是否引入
|
|
107
|
-
'undefined' != typeof(promptView) && showPrompt && promptView.showSuccess(msg);
|
|
108
|
-
}
|
|
109
|
-
function promptFailed(msg, type) {
|
|
110
|
-
console.error(msg);
|
|
111
|
-
'undefined' != typeof(promptView) && showPrompt && promptView.showFailed(msg);
|
|
112
|
-
}
|
|
113
|
-
function promptAlarm(msg, type) {
|
|
114
|
-
console.info(msg);
|
|
115
|
-
'undefined' != typeof(promptView) && showPrompt && promptView.showAlarm(msg);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* 公共方法
|
|
120
|
-
* 判断能否获取本地声卡设备
|
|
121
|
-
*/
|
|
122
|
-
function checkUserMediaAvailable() {
|
|
123
|
-
return Janus.isGetUserMediaAvailable() && !checkIsHttp() && window.hasAudioInputDevices;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* 公共方法
|
|
128
|
-
* 是否有声卡设备
|
|
129
|
-
* 异步方法 结果保存在window.hasAudioInputDevices中 true or false
|
|
130
|
-
*/
|
|
131
|
-
function hasMediaDevices() {
|
|
132
|
-
//参数初始化,防止为空报错
|
|
133
|
-
window.checkAudioDevicesStatus = false;
|
|
134
|
-
window.hasAudioInputDevices = false;
|
|
135
|
-
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
|
|
136
|
-
console.log("Not support enumerateDevices() .");
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
let startTime = new Date().getTime();
|
|
140
|
-
// 列出相机和麦克风.
|
|
141
|
-
navigator.mediaDevices.enumerateDevices()
|
|
142
|
-
.then(function(devices) {
|
|
143
|
-
devices.forEach(function(device) {
|
|
144
|
-
if (device.kind == "audioinput") {
|
|
145
|
-
//判断到1个就返回true
|
|
146
|
-
window.hasAudioInputDevices = true;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
window.checkAudioDevicesStatus = true;
|
|
150
|
-
console.log("检查音频输入设备总计耗时: " + (new Date().getTime() - startTime) + "ms");
|
|
151
|
-
})
|
|
152
|
-
.catch(function(err) {
|
|
153
|
-
console.log(err.name + ": " + err.message);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* 公共方法
|
|
159
|
-
* 判断是否是http
|
|
160
|
-
*/
|
|
161
|
-
function checkIsHttp() {
|
|
162
|
-
let protocolStr = document.location.protocol;
|
|
163
|
-
if(protocolStr == "http:" && window.location.hostname != "localhost" ) return true;
|
|
164
|
-
return false;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 公共方法
|
|
169
|
-
* 判断是否是https 和检测http分开的目的是还有本地打开的情况(前缀为file:)
|
|
170
|
-
* webrtc规定打开摄像头、麦克风需要加密传输 所以需要再https环境下, 本地打开不需要加密 可以正常获取
|
|
171
|
-
* 这也是分开的另一个目的
|
|
172
|
-
*/
|
|
173
|
-
function checkIsHttps() {
|
|
174
|
-
let protocolStr = document.location.protocol;
|
|
175
|
-
if(protocolStr == "https:") return true;
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* 事件对象包装类,通过事件type,加载必要的属性
|
|
181
|
-
* @class
|
|
182
|
-
*/
|
|
183
|
-
function VideoEvent(type,target) {
|
|
184
|
-
this.type = type;
|
|
185
|
-
this.returnValue = true;
|
|
186
|
-
this.target = target || null;
|
|
187
|
-
this.currentTarget = null;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 轮巡工具类
|
|
192
|
-
*/
|
|
193
|
-
let PollTimer = /** @class */ (function () {
|
|
194
|
-
function PollTimer(cb, time) {
|
|
195
|
-
cb(true); // 首次执行
|
|
196
|
-
this.timerId = setInterval(cb, time * 1000);
|
|
197
|
-
}
|
|
198
|
-
PollTimer.prototype.stop = function () {
|
|
199
|
-
if (!this.timerId)
|
|
200
|
-
return;
|
|
201
|
-
clearInterval(this.timerId);
|
|
202
|
-
this.timerId = 0;
|
|
203
|
-
|
|
204
|
-
if (waitTimerId) {
|
|
205
|
-
clearTimeout(waitTimerId);
|
|
206
|
-
waitTimerId = null;
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
return PollTimer;
|
|
210
|
-
}());
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
let waitTimerId = 0;
|
|
214
|
-
function wait(time) {
|
|
215
|
-
return new Promise(function(resolve, reject) {
|
|
216
|
-
if (waitTimerId) {
|
|
217
|
-
clearTimeout(waitTimerId);
|
|
218
|
-
waitTimerId = null;
|
|
219
|
-
}
|
|
220
|
-
waitTimerId = setTimeout(resolve, time);
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* 事件
|
|
226
|
-
*/
|
|
227
|
-
function Listener() {
|
|
228
|
-
// 在构造函数中进行初始化
|
|
229
|
-
this._listeners = {};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
Listener.prototype = {
|
|
233
|
-
|
|
234
|
-
constructor: Listener,
|
|
235
|
-
/**
|
|
236
|
-
* 添加事件
|
|
237
|
-
*/
|
|
238
|
-
addListener: function(type, handler, key){
|
|
239
|
-
if (typeof handler != 'function') {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
let t = this._listeners,id;
|
|
243
|
-
if (typeof key == "string" && key) {
|
|
244
|
-
if (/[^\w\-]/.test(key)) {
|
|
245
|
-
throw("nonstandard key:" + key);
|
|
246
|
-
} else {
|
|
247
|
-
handler.hashCode = key;
|
|
248
|
-
id = key;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
type.indexOf("on") != 0 && (type = "on" + type);
|
|
252
|
-
typeof t[type] != "object" && (t[type] = {});
|
|
253
|
-
id = id || guid();
|
|
254
|
-
handler.hashCode = id;
|
|
255
|
-
t[type][id] = handler;
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* 删除事件
|
|
260
|
-
*/
|
|
261
|
-
removeListener: function(type, handler){
|
|
262
|
-
type.indexOf("on") != 0 && (type = "on" + type);
|
|
263
|
-
let t = this._listeners;
|
|
264
|
-
if (!t[type]) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
if (handler) {
|
|
268
|
-
if (typeof handler == 'function') {
|
|
269
|
-
handler = handler.hashCode;
|
|
270
|
-
}else if (typeof key != "string"){
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
t[type][handler] && delete t[type][handler];
|
|
274
|
-
}else{
|
|
275
|
-
t[type] = {};
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* 派发事件
|
|
281
|
-
*/
|
|
282
|
-
dispatch: function(e, options){
|
|
283
|
-
if (typeof e == 'string') {
|
|
284
|
-
e = new VideoEvent(e);
|
|
285
|
-
}
|
|
286
|
-
options = options || {};
|
|
287
|
-
for (let i in options) {
|
|
288
|
-
e[i] = options[i];
|
|
289
|
-
}
|
|
290
|
-
let i, t = this._listeners, p = e.type;
|
|
291
|
-
e.target || (e.target = this);
|
|
292
|
-
e.currentTarget = this;
|
|
293
|
-
p.indexOf("on") != 0 && (p = "on" + p);
|
|
294
|
-
typeof this[p] == 'function' && this[p].apply(this, arguments);
|
|
295
|
-
if (typeof t[p] == "object") {
|
|
296
|
-
for (i in t[p]) {
|
|
297
|
-
t[p][i].call(this, e);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return e.returnValue;
|
|
301
|
-
},
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* 清空事件
|
|
305
|
-
*/
|
|
306
|
-
removeAllListeners: function () {
|
|
307
|
-
this._listeners = {};
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
let videoListener = new Listener();
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* 使用ocx方式的video工具类
|
|
315
|
-
* @author savage
|
|
316
|
-
* @version 1.0.0
|
|
317
|
-
*/
|
|
318
|
-
function VideoOcx($dom, opts){
|
|
319
|
-
if (!isIE()) {
|
|
320
|
-
console.log('视频控件不支持非IE浏览器');
|
|
321
|
-
return this._getTipObj();
|
|
322
|
-
}
|
|
323
|
-
if (!opts) {
|
|
324
|
-
console.error('VideoOcx的参数opts不能为空');
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
this._init($dom,opts);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* 使用ocx方式的视频播放的方法
|
|
332
|
-
*/
|
|
333
|
-
VideoOcx.prototype = {
|
|
334
|
-
|
|
335
|
-
constructor: VideoOcx,
|
|
336
|
-
/**
|
|
337
|
-
* 播放视频
|
|
338
|
-
* 参数:index(视频窗口编号,从0开始) video(视频设备id,即devId) id(标识,空的话使用设备id) opts(其他参数)
|
|
339
|
-
* 返回true/false
|
|
340
|
-
*/
|
|
341
|
-
play: function(index, video, id, opts){
|
|
342
|
-
/*if (!$.isNumeric(video*1)) {
|
|
343
|
-
throw new Error('video is not number,id = '+id);
|
|
344
|
-
}*/
|
|
345
|
-
console.log("play >>> " + "video=" + video + "; id=" + id + "; index=" + index);
|
|
346
|
-
this.dispatch('beforeplay',{index:index, video:video, id:id});
|
|
347
|
-
|
|
348
|
-
this._obj.SCWebSetCurrentWindow(index);
|
|
349
|
-
let playId = this._obj.SCWebRealPlay(video, this._opts.streamType);
|
|
350
|
-
console.log("play = " + playId);
|
|
351
|
-
|
|
352
|
-
opts = opts || {};
|
|
353
|
-
playId > 0 && (this.videoStatus[index] = {
|
|
354
|
-
video: video,
|
|
355
|
-
id: id,
|
|
356
|
-
playId: playId,
|
|
357
|
-
opts:opts
|
|
358
|
-
},this.dispatch('playsuccess', this.videoStatus[index]));
|
|
359
|
-
|
|
360
|
-
if (playId < 0) {
|
|
361
|
-
let name = opts.name || '视频';
|
|
362
|
-
promptFailed(name + '播放失败!');
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return playId > 0;
|
|
366
|
-
},
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* 在序号最小的空闲窗口播放视频
|
|
370
|
-
* 参数:index(视频窗口编号,从0开始) video(视频设备id,即devId) opts(其他参数)
|
|
371
|
-
* 返回true/false
|
|
372
|
-
*/
|
|
373
|
-
playByOrder: function(video, id, opts){
|
|
374
|
-
let freeWindow = this._getMinIndexFreeWindow(0);
|
|
375
|
-
|
|
376
|
-
if(freeWindow == -1 ||
|
|
377
|
-
(this._getChoiceWindow() != -1 && !this.getInChoiceVideo())){
|
|
378
|
-
return this.playInChoice(video,id,opts);
|
|
379
|
-
}
|
|
380
|
-
return this.play(freeWindow,video,id,opts);
|
|
381
|
-
},
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* 扩展视频窗口数的播放方式
|
|
385
|
-
*/
|
|
386
|
-
playByOrderExpandWindow: function(video,id,opts){
|
|
387
|
-
|
|
388
|
-
let freeWindow = this._getMinIndexFreeWindow(0);
|
|
389
|
-
|
|
390
|
-
let maxWindows = this._opts.windowsNum || 16;
|
|
391
|
-
|
|
392
|
-
while (this._opts.windows < maxWindows && freeWindow == -1) {
|
|
393
|
-
let zoom = Math.sqrt(this._opts.windows*1)+1;
|
|
394
|
-
|
|
395
|
-
if (this._opts.windows == 6) {
|
|
396
|
-
this.setWindowsNum(9);
|
|
397
|
-
} else {
|
|
398
|
-
this.setWindowsNum(Math.pow(zoom,2));
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
freeWindow = this._getMinIndexFreeWindow(zoom-1);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if(freeWindow == -1 ||
|
|
405
|
-
(this._getChoiceWindow() != -1 && !this.getInChoiceVideo())){
|
|
406
|
-
return this.playInChoice(video,id,opts);
|
|
407
|
-
}
|
|
408
|
-
return this.play(freeWindow,video,id,opts);
|
|
409
|
-
},
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* 播放所有视频
|
|
413
|
-
*/
|
|
414
|
-
playAll: function(array){
|
|
415
|
-
if (array.length > this._opts.windows) {
|
|
416
|
-
throw new Error('windows is not enough');
|
|
417
|
-
}
|
|
418
|
-
let me = this;
|
|
419
|
-
me.closeAll();
|
|
420
|
-
$.each(array,function(i,obj){
|
|
421
|
-
me.play(i,obj.video,obj.id,obj.opts);
|
|
422
|
-
});
|
|
423
|
-
},
|
|
424
|
-
/**
|
|
425
|
-
* 在鼠标选中的窗口中播放视频
|
|
426
|
-
*/
|
|
427
|
-
playInChoice: function(video,id,opts){
|
|
428
|
-
console.log("==调用playInChoice播放===")
|
|
429
|
-
let index = this._obj.SCWebGetCurrentWindowIndex();
|
|
430
|
-
this.videoStatus[index] && this.close(index);
|
|
431
|
-
return this.play(index,video,id,opts);
|
|
432
|
-
},
|
|
433
|
-
/**
|
|
434
|
-
* 如果被指定的窗口有视频id,则播放
|
|
435
|
-
*/
|
|
436
|
-
playMulWindows: function(indexs) {
|
|
437
|
-
let me = this;
|
|
438
|
-
$.each(indexs,function(i,index){
|
|
439
|
-
me.videoStatus[index] && me.play(index,me.videoStatus[index].video,me.videoStatus[index].id);
|
|
440
|
-
});
|
|
441
|
-
},
|
|
442
|
-
/**
|
|
443
|
-
* 检索当前点的视频是否被播放,被播放则返回播放的视频窗口
|
|
444
|
-
*/
|
|
445
|
-
isPlaying: function(id){
|
|
446
|
-
let index = -1;
|
|
447
|
-
$.each(this.videoStatus,function(key,val){
|
|
448
|
-
if (id == val.id) {
|
|
449
|
-
index = key;
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
return index;
|
|
454
|
-
},
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* 判断指定窗口是否正在播放视频
|
|
458
|
-
*/
|
|
459
|
-
isPlayingByIndex: function(index){
|
|
460
|
-
return this.videoStatus[index] && true;
|
|
461
|
-
},
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* 获取视频数据
|
|
465
|
-
*/
|
|
466
|
-
getVideoData: function(){
|
|
467
|
-
return this.videoStatus;
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* 关闭语音
|
|
472
|
-
* @param index
|
|
473
|
-
*/
|
|
474
|
-
closeVoice: function(index) {
|
|
475
|
-
this._obj.SCWebVoiceComControl(this.videoStatus[index].video, this.videoStatus[index].playId, 0);
|
|
476
|
-
},
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* 根据playId获取窗口
|
|
480
|
-
* @param playId
|
|
481
|
-
* IE下才有该方法
|
|
482
|
-
*/
|
|
483
|
-
getWindowByPlayId: function(playId) {
|
|
484
|
-
let index = -1;
|
|
485
|
-
$.each(this.videoStatus,function(key,val){
|
|
486
|
-
if (playId == val.playId) {
|
|
487
|
-
index = key;
|
|
488
|
-
return false;
|
|
489
|
-
}
|
|
490
|
-
});
|
|
491
|
-
return index;
|
|
492
|
-
},
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* 根据窗口获取playId
|
|
496
|
-
* @param index
|
|
497
|
-
* IE下才有该方法
|
|
498
|
-
*/
|
|
499
|
-
getPlayIdBywindow : function(index) {
|
|
500
|
-
return this.videoStatus[index].playId;
|
|
501
|
-
},
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* 关闭指定窗口的视频
|
|
505
|
-
*/
|
|
506
|
-
close: function(index, isSave){
|
|
507
|
-
|
|
508
|
-
if (!this.videoStatus[index] || index >= this._opts.windows || this._disableClosed.indexOf(index*1) > -1 ) {
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
this._obj.SCWebSetCurrentWindow(index);
|
|
512
|
-
let close = this._obj.SCWebStopRealPlay(this.videoStatus[index].playId);
|
|
513
|
-
console.log("close = "+close);
|
|
514
|
-
|
|
515
|
-
if (!isSave) {
|
|
516
|
-
this.dispatch('afterclose',this.videoStatus[index]);
|
|
517
|
-
delete this.videoStatus[index];
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
},
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* 关闭指定视频编号正在播放的视频
|
|
524
|
-
*/
|
|
525
|
-
closeByVideo: function(video, isSave){
|
|
526
|
-
let me = this;
|
|
527
|
-
|
|
528
|
-
if (video == undefined) {
|
|
529
|
-
console.info('video参数错误');
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
let videoData = me.videoStatus;
|
|
534
|
-
if (!videoData || videoData.length == 0) {
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
for (let i in videoData) {
|
|
539
|
-
if (video == videoData[i].video) {
|
|
540
|
-
me.close(videoData[i].index);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
*
|
|
547
|
-
*/
|
|
548
|
-
closeHistory: function(playId) {
|
|
549
|
-
let close = this._obj.SCWebStopRealPlay(playId);
|
|
550
|
-
console.log("close = "+close);
|
|
551
|
-
let index = this._getChoiceWindow();
|
|
552
|
-
delete this.videoStatus[index];
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* 关闭所有视频
|
|
557
|
-
* TODO 不可关闭
|
|
558
|
-
*/
|
|
559
|
-
closeAll: function(isSave){
|
|
560
|
-
let me = this;
|
|
561
|
-
isSave || (this._disableClosed = []);
|
|
562
|
-
let windows = me._obj.SCWebGetRealPlayWindows();
|
|
563
|
-
console.log('要关闭的视频窗:' + windows);
|
|
564
|
-
if (windows) {
|
|
565
|
-
$.each(windows.split(','),function(i,index){
|
|
566
|
-
me.close(index,isSave);
|
|
567
|
-
console.log('窗口:' + i);
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* 获取视频窗口
|
|
574
|
-
* @returns
|
|
575
|
-
*/
|
|
576
|
-
getWindowsPlay : function() {
|
|
577
|
-
let me = this;
|
|
578
|
-
let windows = me._obj.SCWebGetRealPlayWindows();
|
|
579
|
-
return windows;
|
|
580
|
-
},
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* 设置鼠标选中窗口
|
|
584
|
-
*/
|
|
585
|
-
setChoiceWindow: function(index) {
|
|
586
|
-
this._obj.SCWebSetCurrentWindow(index);
|
|
587
|
-
},
|
|
588
|
-
/**
|
|
589
|
-
* 获取视频窗口数
|
|
590
|
-
*/
|
|
591
|
-
getWindowsNum: function() {
|
|
592
|
-
return this._opts.windows;
|
|
593
|
-
},
|
|
594
|
-
|
|
595
|
-
/**
|
|
596
|
-
* 是否还有空闲窗口
|
|
597
|
-
*/
|
|
598
|
-
hasFreeWindow: function() {
|
|
599
|
-
return this._obj.SCWebGetFreeWindows() != '';
|
|
600
|
-
},
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* 设置视频窗口数
|
|
604
|
-
*/
|
|
605
|
-
setWindowsNum: function(num,extra) {
|
|
606
|
-
let me = this;
|
|
607
|
-
num = num*1;
|
|
608
|
-
let result;
|
|
609
|
-
if (extra) {
|
|
610
|
-
result = me._obj.SCWebDecoderSetExtraScreenMode(num);
|
|
611
|
-
} else {
|
|
612
|
-
result = me._obj.SCWebDecoderSetScreenMode(num);
|
|
613
|
-
}
|
|
614
|
-
console.log("setWindowsNum >>> " + "result=" + result);
|
|
615
|
-
/*extra
|
|
616
|
-
? me._obj.SCWebDecoderSetExtraScreenMode(num)
|
|
617
|
-
: me._obj.SCWebDecoderSetScreenMode(num);*/
|
|
618
|
-
num = num == 66 ? 6 : num;
|
|
619
|
-
me._changeWindowsAction(num);
|
|
620
|
-
me.dispatch('screenchange',{windowNums: num});
|
|
621
|
-
me._opts.windows = num;
|
|
622
|
-
me._opts.extra = extra;
|
|
623
|
-
},
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* 询问是否无可用窗口
|
|
627
|
-
*/
|
|
628
|
-
isUnavailable: function() {
|
|
629
|
-
return this._opts.windows == 16 && !this.hasFreeWindow();
|
|
630
|
-
},
|
|
631
|
-
|
|
632
|
-
disableClosed: function(num){
|
|
633
|
-
$.isNumeric(num) ? this._disableClosed.push(num) :
|
|
634
|
-
$.isArray(num) && (this._disableClosed = this._disableClosed.concat(num));
|
|
635
|
-
|
|
636
|
-
},
|
|
637
|
-
|
|
638
|
-
enableClosed: function(){
|
|
639
|
-
this._disableClosed = [];
|
|
640
|
-
},
|
|
641
|
-
|
|
642
|
-
//轮巡就是建立一个轮巡数组,然后根据最大屏幕数去遍历数组,记录当前轮巡下标,并标记该视频已被打开,如果视频关闭后 将视频标记为未关闭,建立一个定时器反复去执行这些动作。
|
|
643
|
-
//如果要执行之前视频的记录保存,那么关闭轮巡的关闭方法就需要重新写,或者关闭的时候加一个参数去判断。
|
|
644
|
-
|
|
645
|
-
//云台就是调用 dataHolder方法
|
|
646
|
-
/**
|
|
647
|
-
* 执行轮巡
|
|
648
|
-
*/
|
|
649
|
-
startPoll: function(array,time) {
|
|
650
|
-
if (!array || array.length == 0) {
|
|
651
|
-
promptAlarm('请选择视频设备!');
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
time = $.isNumeric(time) ? time : this._opts.pollInterval;
|
|
656
|
-
this._pollArray = array;
|
|
657
|
-
let me = this,
|
|
658
|
-
windowNum = me._opts.windows,
|
|
659
|
-
maxNum = array.length,
|
|
660
|
-
nowNum = 0 ;
|
|
661
|
-
me.saveList();
|
|
662
|
-
|
|
663
|
-
//延迟
|
|
664
|
-
me.delayTimeId = 0;
|
|
665
|
-
|
|
666
|
-
me._polltimer = new PollTimer(function(firstRun){
|
|
667
|
-
me.closeAll();
|
|
668
|
-
|
|
669
|
-
if (me.delayTimeId) {
|
|
670
|
-
clearTimeout(me.delayTimeId);
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
me.delayTimeId = setTimeout(function() {
|
|
674
|
-
for(let i = 0; i < windowNum; i++) {
|
|
675
|
-
if(nowNum == maxNum){
|
|
676
|
-
nowNum = 0;
|
|
677
|
-
if(maxNum < windowNum) {
|
|
678
|
-
break;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
me.playByOrder(array[nowNum].video, array[nowNum].id, array[nowNum].opts);
|
|
683
|
-
nowNum++;
|
|
684
|
-
}
|
|
685
|
-
if (firstRun) {
|
|
686
|
-
me.dispatch('startpoll', array);
|
|
687
|
-
}
|
|
688
|
-
}, 1000)
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}, time);
|
|
692
|
-
},
|
|
693
|
-
|
|
694
|
-
/**
|
|
695
|
-
* 结束轮巡
|
|
696
|
-
*/
|
|
697
|
-
stopPoll: function() {
|
|
698
|
-
if(!this._polltimer){
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
this._polltimer.stop();
|
|
702
|
-
this._polltimer = undefined;
|
|
703
|
-
console.log('------> 轮巡结束 <-------');
|
|
704
|
-
this.dispatch('stoppoll', {});
|
|
705
|
-
//恢复之前打开的视频
|
|
706
|
-
this.playSaveList();
|
|
707
|
-
},
|
|
708
|
-
|
|
709
|
-
/**
|
|
710
|
-
* 获取是否在轮巡
|
|
711
|
-
*/
|
|
712
|
-
isPolling: function() {
|
|
713
|
-
return !!this._polltimer;
|
|
714
|
-
},
|
|
715
|
-
|
|
716
|
-
/**
|
|
717
|
-
* 云台控制
|
|
718
|
-
* up 上
|
|
719
|
-
* down 下
|
|
720
|
-
* left 左
|
|
721
|
-
* right 右
|
|
722
|
-
* upleft 上左
|
|
723
|
-
* upright 上右
|
|
724
|
-
* downleft 下左
|
|
725
|
-
* downright 下右
|
|
726
|
-
* zoomin 倍率变大
|
|
727
|
-
* zoomout 倍率变下
|
|
728
|
-
* focusnear 焦点+
|
|
729
|
-
* focusfar 焦点-
|
|
730
|
-
* irisopen 光圈+
|
|
731
|
-
* irisclose 光圈-
|
|
732
|
-
* pointset 设置预置点
|
|
733
|
-
* pointdel 删除预置点
|
|
734
|
-
* pointgoto 到预置点
|
|
735
|
-
* scansetleft 自动扫描左边界
|
|
736
|
-
* scansetright 自动扫描又边界
|
|
737
|
-
* scansetspeed 设置扫描速度
|
|
738
|
-
* scanrun 自动扫描运行
|
|
739
|
-
* cruiseadd 添加巡航点
|
|
740
|
-
* cruisedel 删除巡航点
|
|
741
|
-
* cruisespeed 设置巡航点速度
|
|
742
|
-
* cruisepausetime 设置巡航滞留时间
|
|
743
|
-
* cruiserun 启动巡航
|
|
744
|
-
*/
|
|
745
|
-
holder: function(type, opts, isStop) {
|
|
746
|
-
let index = this._getChoiceWindow();
|
|
747
|
-
if( !this.videoStatus[index] ){
|
|
748
|
-
promptAlarm('未选中播放的视频!');
|
|
749
|
-
return;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
let holdType = 'up down left right upleft upright downleft downright zoomin zoomout focusnear focusfar irisopen irisclose pointset pointdel pointgoto '+
|
|
753
|
-
'scansetleft scansetright scansetspeed scanrun cruiseadd cruisedel cruisespeed cruisepausetime cruiserun';
|
|
754
|
-
|
|
755
|
-
let typeVal = (Number(holdType.split(' ').indexOf(type))+Number(1));
|
|
756
|
-
console.log("holdType:" + typeVal + " type:" + type + (isStop ? ' 停止' : ''));
|
|
757
|
-
|
|
758
|
-
if (!typeVal || typeVal <= 0) {
|
|
759
|
-
console.error('异常PTZ指令:' + typeVal);
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
let video = this.videoStatus[index].video;
|
|
763
|
-
|
|
764
|
-
if(isStop) {
|
|
765
|
-
//let playerId = this._obj.SCWebGetCurrentPlayID();
|
|
766
|
-
let result = this._obj.SCWebPTZControl(video,1,typeVal,0,0,0,0);
|
|
767
|
-
//let result = this._obj.SCWebPTZControlEx(playerId, 4, 1, 1);
|
|
768
|
-
console.log(">>>>yuntai control,stop, video=" + video + ", result=" + result);
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
let _opts = {
|
|
772
|
-
speed: 200,
|
|
773
|
-
group: 0,
|
|
774
|
-
present: 0,
|
|
775
|
-
time:0
|
|
776
|
-
}
|
|
777
|
-
$.extend(_opts,opts);
|
|
778
|
-
this._obj.SCWebPTZControl(video, 0,
|
|
779
|
-
typeVal, _opts.speed, _opts.group, 1, _opts.time);
|
|
780
|
-
console.log('设备号:'+ video +', 云台移动-->'+ type);
|
|
781
|
-
},
|
|
782
|
-
|
|
783
|
-
/**
|
|
784
|
-
* 视频回放
|
|
785
|
-
* @param startTime [YYYY-MM-DDTHH:mm:ss]
|
|
786
|
-
* @param endTime
|
|
787
|
-
* @return playId
|
|
788
|
-
*/
|
|
789
|
-
playHistory: function(video,startTime,endTime,opts) {
|
|
790
|
-
let me = this;
|
|
791
|
-
let playId = me._obj.SCWebHistoryPlay(video, startTime, endTime);
|
|
792
|
-
console.log("play = " + playId);
|
|
793
|
-
|
|
794
|
-
if (playId < 0) {
|
|
795
|
-
let name = opts.name || '视频';
|
|
796
|
-
promptFailed(name + '播放失败!');
|
|
797
|
-
return playId;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
let index = me._getChoiceWindow();
|
|
801
|
-
|
|
802
|
-
opts = opts || {};
|
|
803
|
-
playId > 0 && (me.videoStatus[index] = {
|
|
804
|
-
video: video,
|
|
805
|
-
id: video,
|
|
806
|
-
playId: playId,
|
|
807
|
-
opts: opts,
|
|
808
|
-
isPlayBack: true
|
|
809
|
-
}, me.dispatch('playsuccess', me.videoStatus[index]));
|
|
810
|
-
|
|
811
|
-
return playId;
|
|
812
|
-
},
|
|
813
|
-
|
|
814
|
-
/**
|
|
815
|
-
* 历史流控制
|
|
816
|
-
* @param {number} playId
|
|
817
|
-
* @param {string} playType 播放类型(play && pause)
|
|
818
|
-
* @param {numner} playSpeed 播放速率
|
|
819
|
-
* @param {string} startTime 回放时间(暂时无用)
|
|
820
|
-
*/
|
|
821
|
-
historyControl: function(playId, playType, playSpeed, startTime) {
|
|
822
|
-
let contorlType = {
|
|
823
|
-
play: 1,
|
|
824
|
-
pause: 2
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
let playCommand = contorlType[playType];
|
|
828
|
-
if (!playCommand) {
|
|
829
|
-
console.error('unsupported type: ', playType);
|
|
830
|
-
return;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
this._obj.SCWebHistoryControl(playId, playCommand, playSpeed, startTime);
|
|
834
|
-
},
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* 历史流控制(原)
|
|
838
|
-
*/
|
|
839
|
-
_historyControl: function(playId,type,speed,startTime) {
|
|
840
|
-
let contorlType = {
|
|
841
|
-
normal: 1,
|
|
842
|
-
pause: 2,
|
|
843
|
-
'continue': 3,
|
|
844
|
-
};
|
|
845
|
-
let commad = 1;
|
|
846
|
-
|
|
847
|
-
type == 'speed' ? speed && speed < 1 ? (commad = 7 , speed = 1/speed) : commad = 6
|
|
848
|
-
: commad = contorlType[type];
|
|
849
|
-
|
|
850
|
-
this._obj.SCWebHistoryControl(playId,commad,speed);
|
|
851
|
-
|
|
852
|
-
},
|
|
853
|
-
|
|
854
|
-
/**
|
|
855
|
-
* 跳转历史流
|
|
856
|
-
*/
|
|
857
|
-
skipHistory: function(playId,time) {
|
|
858
|
-
this._obj.SCWebHistorySeekPlay(playId,time);
|
|
859
|
-
},
|
|
860
|
-
|
|
861
|
-
/**
|
|
862
|
-
* 抓图
|
|
863
|
-
* @return 0:失败|1:成功
|
|
864
|
-
*/
|
|
865
|
-
capturePicture: function(playId) {
|
|
866
|
-
let videoCapImagePath = this._opts.videoCapImagePath ? this._opts.videoCapImagePath : '';
|
|
867
|
-
return this._obj.SCWebCapturePicture(playId, videoCapImagePath, '');
|
|
868
|
-
},
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
saveList: function() {
|
|
872
|
-
this._saveList = cloneObj(this.videoStatus);
|
|
873
|
-
},
|
|
874
|
-
|
|
875
|
-
playSaveList: function() {
|
|
876
|
-
if (!this._saveList) {
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
this.closeAll();
|
|
880
|
-
let me = this;
|
|
881
|
-
$.each(this._saveList,function(index,obj){
|
|
882
|
-
me.play(index, obj.video, obj.id, obj.opts);
|
|
883
|
-
});
|
|
884
|
-
},
|
|
885
|
-
|
|
886
|
-
/**
|
|
887
|
-
* 获取当前选择窗口的视频video
|
|
888
|
-
*/
|
|
889
|
-
getInChoiceVideo: function() {
|
|
890
|
-
return this.videoStatus[this._obj.SCWebGetCurrentWindowIndex()];
|
|
891
|
-
},
|
|
892
|
-
|
|
893
|
-
/**
|
|
894
|
-
* 获取当前选择的窗口的playId
|
|
895
|
-
*/
|
|
896
|
-
getInChoicePlayId: function() {
|
|
897
|
-
return this._obj.SCWebGetCurrentPlayID();
|
|
898
|
-
},
|
|
899
|
-
|
|
900
|
-
/**
|
|
901
|
-
* 设置全屏
|
|
902
|
-
*/
|
|
903
|
-
setFullScreen: function() {
|
|
904
|
-
this._obj.ScWebFullScreen(1);
|
|
905
|
-
},
|
|
906
|
-
|
|
907
|
-
/**
|
|
908
|
-
* 获取当前视频控件的配置项
|
|
909
|
-
*/
|
|
910
|
-
getVideoControllerOpts: function() {
|
|
911
|
-
return this._opts;
|
|
912
|
-
},
|
|
913
|
-
|
|
914
|
-
/**
|
|
915
|
-
* 获取截屏数据
|
|
916
|
-
*/
|
|
917
|
-
getScreenCaptureData: function(index, callback) {
|
|
918
|
-
let msg = 'IE下暂不支持获取截屏数据!';
|
|
919
|
-
console.log(msg)
|
|
920
|
-
throw Error(msg);
|
|
921
|
-
},
|
|
922
|
-
|
|
923
|
-
/**
|
|
924
|
-
* 添加事件
|
|
925
|
-
*/
|
|
926
|
-
addListener: function(type,handler,key){
|
|
927
|
-
this.videoListener.addListener(type,handler,key);
|
|
928
|
-
},
|
|
929
|
-
|
|
930
|
-
/**
|
|
931
|
-
* 删除事件
|
|
932
|
-
*/
|
|
933
|
-
removeListener: function(type,handler){
|
|
934
|
-
this.videoListener.removeListener(type,handler);
|
|
935
|
-
},
|
|
936
|
-
/**
|
|
937
|
-
* 派发事件
|
|
938
|
-
*/
|
|
939
|
-
dispatch: function(e,options){
|
|
940
|
-
this.videoListener.dispatch(e,options);
|
|
941
|
-
},
|
|
942
|
-
|
|
943
|
-
/**
|
|
944
|
-
* 获取ocx的版本信息
|
|
945
|
-
*/
|
|
946
|
-
getOcxVersion: function() {
|
|
947
|
-
return this._obj.SCWebDecoderGetVersion();
|
|
948
|
-
},
|
|
949
|
-
|
|
950
|
-
/*
|
|
951
|
-
* 总的初始化
|
|
952
|
-
* 参数示例:
|
|
953
|
-
* let opts = {
|
|
954
|
-
windows: 4, //初始化的窗口数
|
|
955
|
-
conf: { //配置参数
|
|
956
|
-
user: conf['video.username'], //用户名
|
|
957
|
-
passwd: conf['video.password'], //密码
|
|
958
|
-
ip: conf['video.ip'], //videoServer ip
|
|
959
|
-
port: conf['video.port'], //videoServer port
|
|
960
|
-
token : token //通讯录令牌,若token非空,则用户名和密码可不传
|
|
961
|
-
},
|
|
962
|
-
extra: false,
|
|
963
|
-
streamType: 0, //码流类型 默认0
|
|
964
|
-
openChangeWindowStrategy: true, //打开策略,切屏:属性为true,则当从大分屏切换到小分屏的时候会保留被关闭的视频,如果未设置 则不保留
|
|
965
|
-
capImage: true, //是否截屏:属性为true的时候,视频上会浮现控制条,进行截图、云台控制操作
|
|
966
|
-
videoCapImagePath: conf['video.cap.image.path'] //截屏默认保存的地址
|
|
967
|
-
pollInterval: 30 //轮巡时间,单位秒
|
|
968
|
-
};
|
|
969
|
-
*/
|
|
970
|
-
_init: function($dom,opts){
|
|
971
|
-
let me = this;
|
|
972
|
-
//配置项
|
|
973
|
-
me._opts = {
|
|
974
|
-
windows: 4,
|
|
975
|
-
conf: {},
|
|
976
|
-
extra: false,
|
|
977
|
-
ocxName: '__videoDiv',
|
|
978
|
-
streamType: 0,
|
|
979
|
-
openChangeWindowStrategy: false,
|
|
980
|
-
capImage: false,
|
|
981
|
-
videoCapImagePath: '',
|
|
982
|
-
pollInterval: 10
|
|
983
|
-
};
|
|
984
|
-
|
|
985
|
-
$.extend(me._opts,opts);
|
|
986
|
-
let windowsArr = me._opts.windowsArr;
|
|
987
|
-
if (!windowsArr || windowsArr.length == 0) {
|
|
988
|
-
me._windowList = {1:{}, 4:{}, 6:{}, 9:{}, 16:{}}
|
|
989
|
-
me._windowsArr = [1, 4, 6, 9, 16];
|
|
990
|
-
} else {
|
|
991
|
-
me._windowList = {};
|
|
992
|
-
for (let index in windowsArr){
|
|
993
|
-
let item = windowsArr[index];
|
|
994
|
-
me._windowList[item] = {};
|
|
995
|
-
}
|
|
996
|
-
me._windowsArr = windowsArr;
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
//me._windowList = {1:{},2:{},3:{},4:{}}
|
|
1000
|
-
|
|
1001
|
-
if (!$.isNumeric(me._opts.pollInterval)) {
|
|
1002
|
-
console.error('pollInterval should be number');
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
//是否提示
|
|
1007
|
-
me._opts.showPrompt === false && (showPrompt = false);
|
|
1008
|
-
//事件注册区域
|
|
1009
|
-
me._addStopHandler();
|
|
1010
|
-
me._addClickHandler();
|
|
1011
|
-
me._addHisHandler();
|
|
1012
|
-
me._addCapPicHandler();
|
|
1013
|
-
me._addHistoryPlayHandler();
|
|
1014
|
-
|
|
1015
|
-
//浏览器刷新/关闭前执行
|
|
1016
|
-
me._beforeUnload();
|
|
1017
|
-
|
|
1018
|
-
//当前视频窗口的值
|
|
1019
|
-
me.videoStatus = {};
|
|
1020
|
-
//不可关闭的窗口
|
|
1021
|
-
me._disableClosed = new Array();
|
|
1022
|
-
//动态生成monitor对象
|
|
1023
|
-
me._obj = $('<OBJECT>').attr({
|
|
1024
|
-
id: me._opts.ocxName,
|
|
1025
|
-
name: me._opts.ocxName,
|
|
1026
|
-
classid: 'clsid:5D62BFBF-7B2D-4E9E-A359-5228400C77BC',
|
|
1027
|
-
width: '100%',
|
|
1028
|
-
height: '100%'
|
|
1029
|
-
});
|
|
1030
|
-
$dom.append(me._obj);
|
|
1031
|
-
|
|
1032
|
-
me._obj = me._obj[0];
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
let conf = me._opts.conf;
|
|
1036
|
-
//初始化和登录
|
|
1037
|
-
let init = me._obj.ScWebDecoderInit(0);
|
|
1038
|
-
console.log('init:' + init);
|
|
1039
|
-
//是否开启抓图
|
|
1040
|
-
|
|
1041
|
-
conf.ip == '127.0.0.1' && (conf.ip = location.hostname);
|
|
1042
|
-
|
|
1043
|
-
let login;
|
|
1044
|
-
if(conf.token && conf.token.length > 0 && me._obj.SCWebDecoderLoginInVS_Token) {
|
|
1045
|
-
login = me._obj.SCWebDecoderLoginInVS_Token(conf.token, conf.ip, conf.port);
|
|
1046
|
-
} else {
|
|
1047
|
-
login = me._obj.SCWebDecoderLoginInVs(conf.user, conf.passwd, conf.ip, conf.port);
|
|
1048
|
-
}
|
|
1049
|
-
console.log('login:' + login);
|
|
1050
|
-
|
|
1051
|
-
//调整分屏模式
|
|
1052
|
-
setTimeout(function(){
|
|
1053
|
-
//设置云台抓图控制按钮
|
|
1054
|
-
me._opts.capImage && me._obj.SCWebSetPtzButtonLayout('');
|
|
1055
|
-
|
|
1056
|
-
me._opts.extra
|
|
1057
|
-
? me._obj.SCWebDecoderSetExtraScreenMode(me._opts.windows)
|
|
1058
|
-
: me._obj.SCWebDecoderSetScreenMode(me._opts.windows);
|
|
1059
|
-
}, 100);
|
|
1060
|
-
|
|
1061
|
-
},
|
|
1062
|
-
|
|
1063
|
-
/**
|
|
1064
|
-
* TODO 添加注释
|
|
1065
|
-
*/
|
|
1066
|
-
_getTipObj: function() {
|
|
1067
|
-
let obj = {};
|
|
1068
|
-
let fncName = 'play playByOrder playAll playInChoice playMulWindows click getWindowsNum setWindowsNum',
|
|
1069
|
-
fncName2 = 'isPlaying setChoiceWindow close closeAll enableClosede disableClosed addListener removeListener dispatch';
|
|
1070
|
-
$.each(fncName.split(' '),function(i,name) {
|
|
1071
|
-
obj[name] = function() {
|
|
1072
|
-
alert('不支持非IE环境');
|
|
1073
|
-
}
|
|
1074
|
-
});
|
|
1075
|
-
$.each(fncName2.split(' '),function(i,name) {
|
|
1076
|
-
obj[name] = function() {
|
|
1077
|
-
console.log('不支持非IE环境');
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
obj.type = 'disable';
|
|
1081
|
-
return obj;
|
|
1082
|
-
},
|
|
1083
|
-
|
|
1084
|
-
/**
|
|
1085
|
-
* 获取编号最小的空闲窗口的编号
|
|
1086
|
-
*/
|
|
1087
|
-
_getMinIndexFreeWindow: function(searchedZoom) {
|
|
1088
|
-
searchedZoom = searchedZoom || 0;
|
|
1089
|
-
let index = Math.ceil(Math.pow(searchedZoom,2));
|
|
1090
|
-
for (; index < this._opts.windows ; index++) {
|
|
1091
|
-
if (!this.videoStatus[index]) {
|
|
1092
|
-
return index;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
return -1;
|
|
1096
|
-
},
|
|
1097
|
-
|
|
1098
|
-
/**
|
|
1099
|
-
* 获取选择的窗口的编号
|
|
1100
|
-
*/
|
|
1101
|
-
_getChoiceWindow: function(){
|
|
1102
|
-
// let playId = this._obj.SCWebGetCurrentPlayID();
|
|
1103
|
-
// let index;
|
|
1104
|
-
// if (playId > 0) {
|
|
1105
|
-
// index = this._obj.SCWebGetRealPlayWindows().split(',')[0];
|
|
1106
|
-
// this.setChoiceWindow(index ? index : 0);
|
|
1107
|
-
// }
|
|
1108
|
-
// return index;
|
|
1109
|
-
return this._obj.SCWebGetCurrentWindowIndex();
|
|
1110
|
-
},
|
|
1111
|
-
|
|
1112
|
-
/**
|
|
1113
|
-
* 切换分屏
|
|
1114
|
-
*/
|
|
1115
|
-
/* _changeWindowsAction: function(num) {
|
|
1116
|
-
let me = this,
|
|
1117
|
-
old = me._opts.windows,
|
|
1118
|
-
now = num,
|
|
1119
|
-
oldZoom = Math.sqrt(old),
|
|
1120
|
-
nowZoom = Math.sqrt(now);
|
|
1121
|
-
if (old == now) {
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
if (me._opts.openChangeWindowStrategy) {
|
|
1125
|
-
if (old > now) {
|
|
1126
|
-
for (; now < old ; now++) {
|
|
1127
|
-
let tempZoom = Math.ceil(Math.sqrt(now+1));
|
|
1128
|
-
|
|
1129
|
-
me.videoStatus[now] && (me._windowList[tempZoom][now] = {
|
|
1130
|
-
video: me.videoStatus[now].video,
|
|
1131
|
-
id: me.videoStatus[now].id,
|
|
1132
|
-
opts: me.videoStatus[now].opts,
|
|
1133
|
-
},
|
|
1134
|
-
me.close(now));
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
} else {
|
|
1138
|
-
while (oldZoom < nowZoom) {
|
|
1139
|
-
oldZoom = oldZoom+1;
|
|
1140
|
-
me._windowList[oldZoom] && $.each(me._windowList[oldZoom],function(index,obj) {
|
|
1141
|
-
me.play(index, obj.video, obj.id, obj.opts);
|
|
1142
|
-
});
|
|
1143
|
-
me._windowList[oldZoom] = {};
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
} else {
|
|
1147
|
-
if (old > now) {
|
|
1148
|
-
for (; now < old ; now++) {
|
|
1149
|
-
me.videoStatus[now] && me.close(now);
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
},*/
|
|
1154
|
-
|
|
1155
|
-
/**
|
|
1156
|
-
* 切换分屏
|
|
1157
|
-
*/
|
|
1158
|
-
_changeWindowsAction: function(num) {
|
|
1159
|
-
let me = this,
|
|
1160
|
-
old = me._opts.windows,
|
|
1161
|
-
now = num;
|
|
1162
|
-
// oldZoom = Math.sqrt(old),
|
|
1163
|
-
// nowZoom = Math.sqrt(now);
|
|
1164
|
-
if (old == now) {
|
|
1165
|
-
return;
|
|
1166
|
-
}
|
|
1167
|
-
if (me._opts.openChangeWindowStrategy) {
|
|
1168
|
-
if (old > now) {
|
|
1169
|
-
for (; now < old ; now++) {
|
|
1170
|
-
//let tempZoom = Math.ceil(Math.sqrt(now+1));
|
|
1171
|
-
let tempZoom = me._getWindowsNum(now + 1);
|
|
1172
|
-
|
|
1173
|
-
me.videoStatus[now] && (me._windowList[tempZoom][now] = {
|
|
1174
|
-
video: me.videoStatus[now].video,
|
|
1175
|
-
id: me.videoStatus[now].id,
|
|
1176
|
-
opts: me.videoStatus[now].opts,
|
|
1177
|
-
},
|
|
1178
|
-
me.close(now));
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
} else {
|
|
1182
|
-
while (old < now) {
|
|
1183
|
-
old = me._getNextWindowsNum(old);
|
|
1184
|
-
me._windowList[old] && $.each(me._windowList[old],function(index,obj) {
|
|
1185
|
-
me.play(index, obj.video, obj.id, obj.opts);
|
|
1186
|
-
});
|
|
1187
|
-
me._windowList[old] = {};
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
} else {
|
|
1191
|
-
if (old > now) {
|
|
1192
|
-
for (; now < old ; now++) {
|
|
1193
|
-
me.videoStatus[now] && me.close(now);
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
},
|
|
1198
|
-
|
|
1199
|
-
/**
|
|
1200
|
-
* 获取当前的分屏数
|
|
1201
|
-
* now为当前窗口的编号
|
|
1202
|
-
*/
|
|
1203
|
-
_getWindowsNum: function(now) {
|
|
1204
|
-
let me = this;
|
|
1205
|
-
let windowsArr = me._windowsArr;
|
|
1206
|
-
for (let index in windowsArr){
|
|
1207
|
-
if (now <= windowsArr[index]) {
|
|
1208
|
-
return windowsArr[index];
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
},
|
|
1212
|
-
|
|
1213
|
-
/**
|
|
1214
|
-
* 获取下一窗口
|
|
1215
|
-
*/
|
|
1216
|
-
_getNextWindowsNum: function(old) {
|
|
1217
|
-
let me = this;
|
|
1218
|
-
let windowsArr = me._windowsArr;
|
|
1219
|
-
for (let index in windowsArr){
|
|
1220
|
-
if (index == windowsArr.length - 1) {
|
|
1221
|
-
return windowsArr[index]
|
|
1222
|
-
}
|
|
1223
|
-
if (old == windowsArr[index]) {
|
|
1224
|
-
return windowsArr[Number(index) + Number(1)];
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
},
|
|
1228
|
-
|
|
1229
|
-
_addStopHandler: function() {
|
|
1230
|
-
let me = this;
|
|
1231
|
-
window.stopVideo = function(playId,videoId) {
|
|
1232
|
-
if (me.getWindowByPlayId(playId) != -1 &&
|
|
1233
|
-
me.videoStatus[me.getWindowByPlayId(playId)].isPlayBack) {
|
|
1234
|
-
me.closeHistory(playId);
|
|
1235
|
-
} else {
|
|
1236
|
-
me.close(me.getWindowByPlayId(playId));
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
me.dispatch('streamoff', {playId:playId,videoId:videoId});
|
|
1240
|
-
};
|
|
1241
|
-
me._regEvent('SCWebStopVideoEvent(playId,videoId)', 'stopVideo(playId,videoId);');
|
|
1242
|
-
|
|
1243
|
-
},
|
|
1244
|
-
|
|
1245
|
-
_addClickHandler: function() {
|
|
1246
|
-
let me = this;
|
|
1247
|
-
window.clickVideo = function(playId) {
|
|
1248
|
-
me.dispatch('click',me.videoStatus[me.getWindowByPlayId(playId)]);
|
|
1249
|
-
};
|
|
1250
|
-
me._regEvent('SCWebDecoderClick(playId,type)', 'clickVideo(playId);');
|
|
1251
|
-
},
|
|
1252
|
-
|
|
1253
|
-
_addHisHandler: function() {
|
|
1254
|
-
let me = this;
|
|
1255
|
-
window.playbackVideo = function(playId,videoId,historytime) {
|
|
1256
|
-
me.dispatch('playback',{playId:playId,videoId:videoId,historyTime:historytime});
|
|
1257
|
-
};
|
|
1258
|
-
me._regEvent('SCWebHistoryPlayTime(playId,videoId,historytime)', 'playbackVideo(playId,videoId,historytime);');
|
|
1259
|
-
},
|
|
1260
|
-
|
|
1261
|
-
//监听截图事件
|
|
1262
|
-
_addCapPicHandler: function() {
|
|
1263
|
-
let me = this;
|
|
1264
|
-
window.getCapPicPath = function(playId, capPicPath, capPicName) {
|
|
1265
|
-
me.dispatch('getCapPicPath', {playId:playId, capPicPath:capPicPath, capPicName: capPicName});
|
|
1266
|
-
};
|
|
1267
|
-
me._regEvent('SCWebGetCapPicPathName(playId, capPicPath, capPicName)', 'getCapPicPath(playId, capPicPath, capPicName);');
|
|
1268
|
-
},
|
|
1269
|
-
|
|
1270
|
-
//监听点击视频框的历史回放
|
|
1271
|
-
_addHistoryPlayHandler: function() {
|
|
1272
|
-
let me = this;
|
|
1273
|
-
window.historyPlay = function(playId, videoId) {
|
|
1274
|
-
me.dispatch('historyPlay', {playId:playId, videoId:videoId});
|
|
1275
|
-
};
|
|
1276
|
-
me._regEvent('SCWebHistoryPlayEvent(playId, videoId)', 'historyPlay(playId, videoId);');
|
|
1277
|
-
},
|
|
1278
|
-
|
|
1279
|
-
_regEvent: function(eventName,handlerName) {
|
|
1280
|
-
window._addScriptFlag = true;
|
|
1281
|
-
let script;
|
|
1282
|
-
try {
|
|
1283
|
-
script = $('<script>').attr({
|
|
1284
|
-
'for': this._opts.ocxName,
|
|
1285
|
-
'event': eventName,
|
|
1286
|
-
}).text('if (!_addScriptFlag) {'
|
|
1287
|
-
+handlerName
|
|
1288
|
-
+'}'
|
|
1289
|
-
+'_addScriptFlag = false;');
|
|
1290
|
-
|
|
1291
|
-
} catch (e) {
|
|
1292
|
-
script = '<script for="'+this._opts.ocxName+'" event = "'+eventName+'" >'
|
|
1293
|
-
+'if (!_addScriptFlag) {'
|
|
1294
|
-
+handlerName
|
|
1295
|
-
+'}'
|
|
1296
|
-
+'_addScriptFlag = false;'
|
|
1297
|
-
+'</script>';
|
|
1298
|
-
}
|
|
1299
|
-
$('body').append(script);
|
|
1300
|
-
},
|
|
1301
|
-
|
|
1302
|
-
_beforeUnload: function() {
|
|
1303
|
-
let me = this;
|
|
1304
|
-
window.onbeforeunload = function (e) {
|
|
1305
|
-
me.closeAll();
|
|
1306
|
-
me._obj.SCWebDecoderDestroy();
|
|
1307
|
-
};
|
|
1308
|
-
},
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
/**
|
|
1313
|
-
* 使用webRtc方式的video工具类
|
|
1314
|
-
*/
|
|
1315
|
-
function VideoWebRtc($dom,opts){
|
|
1316
|
-
let _self = this;
|
|
1317
|
-
_self.videoListener = new Listener();
|
|
1318
|
-
if (!opts) {
|
|
1319
|
-
console.error('VideoWebRtc的参数opts不能为空');
|
|
1320
|
-
return;
|
|
1321
|
-
}
|
|
1322
|
-
_self.configOpt = (opts && opts.configOpt) || 3;
|
|
1323
|
-
hasMediaDevices();
|
|
1324
|
-
//检测声卡设备为异步方法,耗时在几十毫秒左右,因此需要做延迟
|
|
1325
|
-
//默认检查次数为40 间隔为20ms
|
|
1326
|
-
let count = 0;
|
|
1327
|
-
let index = setInterval(function () {
|
|
1328
|
-
if (count == 40) {
|
|
1329
|
-
clearInterval(index);
|
|
1330
|
-
_self._init($dom,opts);
|
|
1331
|
-
let resizeObserver = new ResizeObserver(function( entries ) {
|
|
1332
|
-
// console.log(entries)
|
|
1333
|
-
entries.forEach((item, index) =>{
|
|
1334
|
-
let target = item.target
|
|
1335
|
-
if(document.querySelector(_self.selector)){
|
|
1336
|
-
let videoLi = {}
|
|
1337
|
-
Array.prototype.slice.call(document.querySelector(_self.selector).querySelectorAll('li'), 0).forEach(liItem => {
|
|
1338
|
-
videoLi[$(liItem).attr('index')] = liItem
|
|
1339
|
-
})
|
|
1340
|
-
_self.VIDEO_DATA.forEach((item, index) => {
|
|
1341
|
-
let tel = item.video
|
|
1342
|
-
if (!tel&&item.id) {
|
|
1343
|
-
videoLi[index].querySelector('video').style = ''
|
|
1344
|
-
if(videoLi[index].querySelector('.rotate-btn'))
|
|
1345
|
-
videoLi[index].querySelector('.rotate-btn').setAttribute('rotate-index', 0)
|
|
1346
|
-
}else{
|
|
1347
|
-
let rotateIndex = $(videoLi[index]).find('button[name=rotateVideo]').attr('rotate-index')
|
|
1348
|
-
setTimeout(() => {
|
|
1349
|
-
_self.videoRotateSize(videoLi[index], rotateIndex);
|
|
1350
|
-
}, 200);
|
|
1351
|
-
}
|
|
1352
|
-
})
|
|
1353
|
-
}else{
|
|
1354
|
-
resizeObserver.unobserve(target)
|
|
1355
|
-
}
|
|
1356
|
-
})
|
|
1357
|
-
})
|
|
1358
|
-
// 监听dom
|
|
1359
|
-
resizeObserver.observe(document.querySelector(_self.selector))
|
|
1360
|
-
} else {
|
|
1361
|
-
if (window.checkAudioDevicesStatus) {
|
|
1362
|
-
clearInterval(index);
|
|
1363
|
-
_self._init($dom,opts);
|
|
1364
|
-
let resizeObserver = new ResizeObserver(function( entries ) {
|
|
1365
|
-
// console.log(entries)
|
|
1366
|
-
entries.forEach((item, index) =>{
|
|
1367
|
-
let target = item.target
|
|
1368
|
-
if(document.querySelector(_self.selector)){
|
|
1369
|
-
let videoLi = {}
|
|
1370
|
-
Array.prototype.slice.call(document.querySelector(_self.selector).querySelectorAll('li'), 0).forEach(liItem => {
|
|
1371
|
-
videoLi[$(liItem).attr('index')] = liItem
|
|
1372
|
-
})
|
|
1373
|
-
_self.VIDEO_DATA.forEach((item, index) => {
|
|
1374
|
-
let tel = item.video
|
|
1375
|
-
if (!tel&&item.id) {
|
|
1376
|
-
videoLi[index].querySelector('video').style = ''
|
|
1377
|
-
if(videoLi[index].querySelector('.rotate-btn'))
|
|
1378
|
-
videoLi[index].querySelector('.rotate-btn').setAttribute('rotate-index', 0)
|
|
1379
|
-
}else{
|
|
1380
|
-
let rotateIndex = $(videoLi[index]).find('button[name=rotateVideo]').attr('rotate-index')
|
|
1381
|
-
setTimeout(() => {
|
|
1382
|
-
_self.videoRotateSize(videoLi[index], rotateIndex);
|
|
1383
|
-
}, 200);
|
|
1384
|
-
}
|
|
1385
|
-
})
|
|
1386
|
-
}else{
|
|
1387
|
-
resizeObserver.unobserve(target)
|
|
1388
|
-
}
|
|
1389
|
-
})
|
|
1390
|
-
})
|
|
1391
|
-
// 监听dom
|
|
1392
|
-
resizeObserver.observe(document.querySelector(_self.selector))
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
count++;
|
|
1396
|
-
}, 20);
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
/**
|
|
1400
|
-
* 使用WEB-RTC方式的视频播放的方法
|
|
1401
|
-
*/
|
|
1402
|
-
VideoWebRtc.prototype = {
|
|
1403
|
-
constructor: VideoWebRtc,
|
|
1404
|
-
|
|
1405
|
-
VIDEO_DATA: [], //记录视频各分屏的状态
|
|
1406
|
-
|
|
1407
|
-
/**
|
|
1408
|
-
* 播放视频
|
|
1409
|
-
* 参数:index(视频窗口编号,从0开始) video(视频设备id,即devId) id(标识,空的话使用设备id) opts(其他参数)
|
|
1410
|
-
* 返回true/false
|
|
1411
|
-
*/
|
|
1412
|
-
play: function(index, video, id, opts){
|
|
1413
|
-
let me = this;
|
|
1414
|
-
// if (me.isPlaying(id) != -1) {
|
|
1415
|
-
// console.info('该视频正在播放');
|
|
1416
|
-
// return false;
|
|
1417
|
-
// }
|
|
1418
|
-
// 启用播放队列时,当前位置正在关闭上一个视频,则加入播放队列
|
|
1419
|
-
if (me.waitPlayQueueSwitch && me.VIDEO_DATA[index].isClosing) {
|
|
1420
|
-
me._addWaitingVideo(index, video, id, opts);
|
|
1421
|
-
return ;
|
|
1422
|
-
}
|
|
1423
|
-
console.log("play >>> " + "video=" + video + "; id=" + id + "; index=" + index);
|
|
1424
|
-
me.dispatch('beforeplay',{index:index, video:video, id:id});
|
|
1425
|
-
|
|
1426
|
-
if (index < 0) {
|
|
1427
|
-
console.error('index参数错误');
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
me.VIDEO_DATA[index].play(video);
|
|
1431
|
-
|
|
1432
|
-
opts = opts || {};
|
|
1433
|
-
|
|
1434
|
-
if (me.VIDEO_DATA[index].playing) {
|
|
1435
|
-
me.VIDEO_DATA[index].opts = opts;
|
|
1436
|
-
me.VIDEO_DATA[index].id = id;
|
|
1437
|
-
me.dispatch('playsuccess', me.VIDEO_DATA[index]);
|
|
1438
|
-
return true;
|
|
1439
|
-
}
|
|
1440
|
-
return false;
|
|
1441
|
-
},
|
|
1442
|
-
|
|
1443
|
-
/**
|
|
1444
|
-
* 在序号最小的空闲窗口播放视频
|
|
1445
|
-
* 参数:index(视频窗口编号,从0开始) video(视频设备id,即devId) opts(其他参数)
|
|
1446
|
-
* 返回true/false
|
|
1447
|
-
*/
|
|
1448
|
-
playByOrder: function(video, id, opts){
|
|
1449
|
-
let freeWindow = this._getMinIndexFreeWindow();
|
|
1450
|
-
|
|
1451
|
-
if(freeWindow == -1 ||
|
|
1452
|
-
(this._getChoiceWindow() != -1 && !this.getInChoiceVideo() && this._opts.windowsNum > 1)){
|
|
1453
|
-
return this.playInChoice(video,id,opts);
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
return this.play(freeWindow, video, id, opts);
|
|
1457
|
-
},
|
|
1458
|
-
|
|
1459
|
-
/**
|
|
1460
|
-
* 扩展视频窗口数的播放方式
|
|
1461
|
-
*/
|
|
1462
|
-
playByOrderExpandWindow: function(video, id, opts){
|
|
1463
|
-
let me = this;
|
|
1464
|
-
|
|
1465
|
-
let freeWindow = this._getMinIndexFreeWindow();
|
|
1466
|
-
|
|
1467
|
-
// while (this._opts.windows < 16 && freeWindow == -1) {
|
|
1468
|
-
// me.setWindowsNum(me._getNextWindowsNum(parseInt(me._opts.windows)));
|
|
1469
|
-
// freeWindow = this._getMinIndexFreeWindow(0);
|
|
1470
|
-
// }
|
|
1471
|
-
|
|
1472
|
-
let maxWindows = this._opts.windowsNum || 16;
|
|
1473
|
-
|
|
1474
|
-
while (me._opts.windows < maxWindows && freeWindow == -1) {
|
|
1475
|
-
let zoom = Math.sqrt(this._opts.windows*1)+1;
|
|
1476
|
-
|
|
1477
|
-
if (this._opts.windows == 6) {
|
|
1478
|
-
this.setWindowsNum(9);
|
|
1479
|
-
} else {
|
|
1480
|
-
this.setWindowsNum(Math.pow(zoom,2));
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
freeWindow = this._getMinIndexFreeWindow(zoom-1);
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
if (this._getChoiceWindow() == -1 && this._getMinIndexFreeWindow() != -1) {
|
|
1487
|
-
this.setChoiceWindow(this._getMinIndexFreeWindow());
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
if(freeWindow == -1 ||
|
|
1491
|
-
(this._getChoiceWindow() != -1 && !this.getInChoiceVideo() && this._opts.windowsNum > 1)){
|
|
1492
|
-
return this.playInChoice(video,id,opts);
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
return this.play(freeWindow, video, id, opts);
|
|
1496
|
-
},
|
|
1497
|
-
|
|
1498
|
-
/**
|
|
1499
|
-
* 播放所有视频
|
|
1500
|
-
*/
|
|
1501
|
-
playAll: function(array){
|
|
1502
|
-
if (array.length > this._opts.windows) {
|
|
1503
|
-
throw new Error('windows is not enough');
|
|
1504
|
-
}
|
|
1505
|
-
let me = this;
|
|
1506
|
-
me.closeAll();
|
|
1507
|
-
$.each(array,function(i,obj){
|
|
1508
|
-
me.play(i, obj.video, obj.id, obj.opts);
|
|
1509
|
-
});
|
|
1510
|
-
},
|
|
1511
|
-
|
|
1512
|
-
/**
|
|
1513
|
-
* 在鼠标选中的窗口中播放视频
|
|
1514
|
-
*/
|
|
1515
|
-
playInChoice: function(video, id, opts){
|
|
1516
|
-
let me = this;
|
|
1517
|
-
let selView = $(me.selector + ' li.sel');
|
|
1518
|
-
if(selView.length){
|
|
1519
|
-
if (me.VIDEO_DATA[selView.index()].playing) {
|
|
1520
|
-
me.close(selView.index());
|
|
1521
|
-
//延时打开 禁止同时一关一开
|
|
1522
|
-
setTimeout(function(){
|
|
1523
|
-
me.play(selView.index(), video, id, opts);
|
|
1524
|
-
}, 1000);
|
|
1525
|
-
} else {
|
|
1526
|
-
me.play(selView.index(), video, id, opts);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
},
|
|
1530
|
-
|
|
1531
|
-
/**
|
|
1532
|
-
* 检索当前点的视频是否被播放,被播放则返回播放的视频窗口
|
|
1533
|
-
*/
|
|
1534
|
-
isPlaying: function(id){
|
|
1535
|
-
let me = this;
|
|
1536
|
-
let index = -1;
|
|
1537
|
-
$.each(me.VIDEO_DATA,function(key,val){
|
|
1538
|
-
if (id == val.id && me.VIDEO_DATA[key].playing) {
|
|
1539
|
-
index = key;
|
|
1540
|
-
}
|
|
1541
|
-
});
|
|
1542
|
-
return index;
|
|
1543
|
-
},
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1546
|
-
* 判断指定窗口是否正在播放视频
|
|
1547
|
-
*/
|
|
1548
|
-
isPlayingByIndex: function(index){
|
|
1549
|
-
let me = this;
|
|
1550
|
-
if (index > me.VIDEO_DATA.length - 1 || index < 0) return false;
|
|
1551
|
-
|
|
1552
|
-
return me.VIDEO_DATA[index].playing;
|
|
1553
|
-
},
|
|
1554
|
-
|
|
1555
|
-
/**
|
|
1556
|
-
* 获取视频数据
|
|
1557
|
-
*/
|
|
1558
|
-
getVideoData: function(){
|
|
1559
|
-
return this.VIDEO_DATA;
|
|
1560
|
-
},
|
|
1561
|
-
|
|
1562
|
-
/**
|
|
1563
|
-
* 关闭指定窗口的视频
|
|
1564
|
-
*/
|
|
1565
|
-
close: function(index, isSave){
|
|
1566
|
-
if (index < 0) {
|
|
1567
|
-
console.info('index参数错误');
|
|
1568
|
-
return;
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
this.VIDEO_DATA[index].close();
|
|
1572
|
-
let video = $(this.selector + ' li ').eq(index).find('video')
|
|
1573
|
-
if(video.hasClass('scale-scene')) {
|
|
1574
|
-
video.removeClass('scale-scene');
|
|
1575
|
-
video.parent().find('.scale-btn').addClass('bggray')
|
|
1576
|
-
video.parent().find('.scale-btn').attr('title', '视频画面铺满')
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
if (!isSave) {
|
|
1580
|
-
this.VIDEO_DATA[index].closeType = 'close';
|
|
1581
|
-
this.dispatch('afterclose', this.VIDEO_DATA[index]);
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
},
|
|
1585
|
-
|
|
1586
|
-
/**
|
|
1587
|
-
* 关闭指定视频编号正在播放的视频
|
|
1588
|
-
*/
|
|
1589
|
-
closeByVideo: function(video, isSave){
|
|
1590
|
-
let me = this;
|
|
1591
|
-
|
|
1592
|
-
if (video == undefined) {
|
|
1593
|
-
console.info('video参数错误');
|
|
1594
|
-
return;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
let videoData = me.VIDEO_DATA;
|
|
1598
|
-
if (!videoData || videoData.length == 0) {
|
|
1599
|
-
return;
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
for (let i in videoData) {
|
|
1603
|
-
if (video == videoData[i].video) {
|
|
1604
|
-
me.close(videoData[i].index);
|
|
1605
|
-
|
|
1606
|
-
if (!isSave) {
|
|
1607
|
-
videoData[i].closeType = 'close';
|
|
1608
|
-
me.dispatch('afterclose', videoData[i]);
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
|
-
},
|
|
1613
|
-
|
|
1614
|
-
/**
|
|
1615
|
-
* 关闭所有视频
|
|
1616
|
-
*/
|
|
1617
|
-
closeAll: function(isSave){
|
|
1618
|
-
let me = this;
|
|
1619
|
-
// 清除所有等待播放队列
|
|
1620
|
-
me._removeAllWaitingVideo();
|
|
1621
|
-
let openVideos = [];
|
|
1622
|
-
for(let i = me._opts.windowsBeginIndex; i < me._opts.windowsBeginIndex + me._opts.windowsNum; i++){
|
|
1623
|
-
// if(me.VIDEO_DATA[i].playing){
|
|
1624
|
-
// me.close(i, isSave)
|
|
1625
|
-
// }
|
|
1626
|
-
me.close(i, isSave);
|
|
1627
|
-
}
|
|
1628
|
-
|
|
1629
|
-
// if(!openVideos.length) return;
|
|
1630
|
-
//
|
|
1631
|
-
// //适当延时进行关闭
|
|
1632
|
-
// let count = 0;
|
|
1633
|
-
// let interval = setInterval(function(){
|
|
1634
|
-
// if(count == openVideos.length){
|
|
1635
|
-
// clearInterval(interval);
|
|
1636
|
-
// }else{
|
|
1637
|
-
// me.close(openVideos[count], isSave)
|
|
1638
|
-
// count++;
|
|
1639
|
-
// }
|
|
1640
|
-
// }, 50);
|
|
1641
|
-
},
|
|
1642
|
-
|
|
1643
|
-
/**
|
|
1644
|
-
* 设置鼠标选中窗口
|
|
1645
|
-
*/
|
|
1646
|
-
setChoiceWindow: function(index) {
|
|
1647
|
-
$('.screen-' + (index + 1)).click();
|
|
1648
|
-
},
|
|
1649
|
-
|
|
1650
|
-
/**
|
|
1651
|
-
* 获取视频窗口数
|
|
1652
|
-
*/
|
|
1653
|
-
getWindowsNum: function() {
|
|
1654
|
-
return this._opts.windows;
|
|
1655
|
-
},
|
|
1656
|
-
|
|
1657
|
-
/**
|
|
1658
|
-
* 分屏切换,传入的参数为新的屏数
|
|
1659
|
-
*/
|
|
1660
|
-
setWindowsNum: function(num) {
|
|
1661
|
-
let me = this;
|
|
1662
|
-
|
|
1663
|
-
//切换屏幕后 选中空闲最小的窗口
|
|
1664
|
-
if (me._opts.windows != num && me._getMinIndexFreeWindow() != -1) {
|
|
1665
|
-
me.setChoiceWindow(me._getMinIndexFreeWindow());
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
|
-
$(me.selector + ' .video-main').removeClass("mode-" + me._opts.windows).addClass("mode-" + num);
|
|
1669
|
-
let _li = $(me.selector + ' li').hide();
|
|
1670
|
-
me._opts.windows = num;
|
|
1671
|
-
for(let i = 0; i < num; i++){
|
|
1672
|
-
_li.eq(i).show();
|
|
1673
|
-
}
|
|
1674
|
-
//分屏切换事件
|
|
1675
|
-
this.dispatch('screenchange', {windowNums:num, flag:me._opts.flag});
|
|
1676
|
-
|
|
1677
|
-
//设置旋转了的视频样式
|
|
1678
|
-
if(document.querySelector(me.selector)){
|
|
1679
|
-
let videoLi = {}
|
|
1680
|
-
Array.prototype.slice.call(document.querySelector(me.selector).querySelectorAll('li'), 0).forEach(liItem => {
|
|
1681
|
-
videoLi[$(liItem).attr('index')] = liItem
|
|
1682
|
-
})
|
|
1683
|
-
me.VIDEO_DATA.forEach((item, index) => {
|
|
1684
|
-
let tel = item.video
|
|
1685
|
-
if (!tel&&item.id) {
|
|
1686
|
-
if(videoLi[index]){
|
|
1687
|
-
videoLi[index].querySelector('video').style = ''
|
|
1688
|
-
if(videoLi[index].querySelector('.rotate-btn'))
|
|
1689
|
-
videoLi[index].querySelector('.rotate-btn').setAttribute('rotate-index', 0)
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
})
|
|
1693
|
-
}
|
|
1694
|
-
//设置旋转视频的样式
|
|
1695
|
-
for(let k = 0; k < _li.length; k++){
|
|
1696
|
-
let rotateIndex = _li.eq(k).find('button[name=rotateVideo]').attr('rotate-index');
|
|
1697
|
-
let scaleBtn = _li.eq(k).find('button[name=scaleVideo]').hasClass('bggray')
|
|
1698
|
-
if(scaleBtn){
|
|
1699
|
-
setTimeout(() => {
|
|
1700
|
-
me.videoRotateSize(_li.eq(k)[0], rotateIndex);
|
|
1701
|
-
}, 200);
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
},
|
|
1705
|
-
|
|
1706
|
-
/**
|
|
1707
|
-
* 询问是否无可用窗口
|
|
1708
|
-
*/
|
|
1709
|
-
isUnavailable: function() {
|
|
1710
|
-
return this._opts.windows == 16 && this._getMinIndexFreeWindow() == -1;
|
|
1711
|
-
},
|
|
1712
|
-
|
|
1713
|
-
/**
|
|
1714
|
-
* 执行轮巡
|
|
1715
|
-
*/
|
|
1716
|
-
startPoll: function(array,time) {
|
|
1717
|
-
if (!array || array.length == 0) {
|
|
1718
|
-
promptAlarm('请选择视频设备!');
|
|
1719
|
-
return false;
|
|
1720
|
-
}
|
|
1721
|
-
|
|
1722
|
-
time = $.isNumeric(time) ? time : this._opts.pollInterval;
|
|
1723
|
-
this._pollArray = array;
|
|
1724
|
-
let me = this,
|
|
1725
|
-
windowNum = me._opts.windows,
|
|
1726
|
-
maxNum = array.length,
|
|
1727
|
-
nowNum = 0 ;
|
|
1728
|
-
me.saveList();
|
|
1729
|
-
|
|
1730
|
-
this._polltimer = new PollTimer(function(firstRun){
|
|
1731
|
-
me.closeAll();
|
|
1732
|
-
|
|
1733
|
-
if (firstRun) {
|
|
1734
|
-
for(let i = 0; i < windowNum; i++) {
|
|
1735
|
-
if(nowNum == maxNum){
|
|
1736
|
-
nowNum = 0;
|
|
1737
|
-
if(maxNum < windowNum) {
|
|
1738
|
-
break;
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
me.playByOrder(array[nowNum].video, array[nowNum].id, array[nowNum].opts);
|
|
1743
|
-
nowNum++;
|
|
1744
|
-
}
|
|
1745
|
-
me.dispatch('startpoll', array);
|
|
1746
|
-
}else {
|
|
1747
|
-
wait(1500).then(function(){
|
|
1748
|
-
for(let i = 0; i < windowNum; i++) {
|
|
1749
|
-
if(nowNum == maxNum){
|
|
1750
|
-
nowNum = 0;
|
|
1751
|
-
if(maxNum < windowNum) {
|
|
1752
|
-
break;
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
me.playByOrder(array[nowNum].video, array[nowNum].id, array[nowNum].opts);
|
|
1757
|
-
nowNum++;
|
|
1758
|
-
}
|
|
1759
|
-
})
|
|
1760
|
-
}
|
|
1761
|
-
}, time);
|
|
1762
|
-
},
|
|
1763
|
-
|
|
1764
|
-
/**
|
|
1765
|
-
* 结束轮巡
|
|
1766
|
-
*/
|
|
1767
|
-
stopPoll: function() {
|
|
1768
|
-
if(!this._polltimer){
|
|
1769
|
-
return;
|
|
1770
|
-
}
|
|
1771
|
-
|
|
1772
|
-
this._polltimer.stop();
|
|
1773
|
-
this._polltimer = undefined;
|
|
1774
|
-
|
|
1775
|
-
console.log('------> 轮巡结束 <-------');
|
|
1776
|
-
this.dispatch('stoppoll', {});
|
|
1777
|
-
|
|
1778
|
-
this._pollArray = null;
|
|
1779
|
-
this.closeAll();
|
|
1780
|
-
//恢复之前打开的视频
|
|
1781
|
-
//this.playSaveList();
|
|
1782
|
-
},
|
|
1783
|
-
|
|
1784
|
-
/**
|
|
1785
|
-
* 获取是否在轮巡
|
|
1786
|
-
*/
|
|
1787
|
-
isPolling: function() {
|
|
1788
|
-
return !!this._polltimer;
|
|
1789
|
-
},
|
|
1790
|
-
|
|
1791
|
-
holder: function(type, opts, isStop) {
|
|
1792
|
-
let index = this._getChoiceWindow();
|
|
1793
|
-
if (index < 0) {
|
|
1794
|
-
promptFailed('请先选中视频');
|
|
1795
|
-
return false;
|
|
1796
|
-
}
|
|
1797
|
-
return this.VIDEO_DATA[index].holder(type, opts, isStop);
|
|
1798
|
-
},
|
|
1799
|
-
|
|
1800
|
-
/**
|
|
1801
|
-
* 视频回放
|
|
1802
|
-
* @param startTime [YYYY-MM-DDTHH:mm:ss]
|
|
1803
|
-
* @param endTime
|
|
1804
|
-
* @return playId
|
|
1805
|
-
*/
|
|
1806
|
-
playHistory: function(video, startTime, endTime, opts) {
|
|
1807
|
-
let me = this;
|
|
1808
|
-
|
|
1809
|
-
let index;
|
|
1810
|
-
//回放是一分屏的默认使用一个窗口
|
|
1811
|
-
if (me._opts.windowsNum == 1) {
|
|
1812
|
-
index = me._opts.windowsBeginIndex;
|
|
1813
|
-
} else {
|
|
1814
|
-
index = me._getMinIndexFreeWindow();
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
if (index < 0) {
|
|
1818
|
-
console.error('窗口编号获取失败!')
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
me.setChoiceWindow(index);
|
|
1822
|
-
me.VIDEO_DATA[index].opts = opts;
|
|
1823
|
-
return me.VIDEO_DATA[index].playback(video,startTime,endTime);
|
|
1824
|
-
},
|
|
1825
|
-
|
|
1826
|
-
/**
|
|
1827
|
-
* 关闭历史流
|
|
1828
|
-
*/
|
|
1829
|
-
closeHistory: function(video, index) {
|
|
1830
|
-
if (!video) return;
|
|
1831
|
-
|
|
1832
|
-
let me = this;
|
|
1833
|
-
|
|
1834
|
-
if (!index) {
|
|
1835
|
-
let index;
|
|
1836
|
-
if (me._opts.windowsNum == 1) {
|
|
1837
|
-
index = me._opts.windowsBeginIndex;
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
return me.VIDEO_DATA[index].playbackControl(video, "stop", 0);
|
|
1842
|
-
},
|
|
1843
|
-
|
|
1844
|
-
/**
|
|
1845
|
-
* 历史流控制
|
|
1846
|
-
* @param {number} video
|
|
1847
|
-
* @param {string} playType 播放类型(play && pause & stop)
|
|
1848
|
-
* @param {numner} playSpeed 播放速率
|
|
1849
|
-
* @param {string} startTime 回放时间(暂时无用)
|
|
1850
|
-
*/
|
|
1851
|
-
historyControl: function(video, playType, playSpeed, startTime) {
|
|
1852
|
-
let me = this;
|
|
1853
|
-
let index;
|
|
1854
|
-
if (me._opts.windowsNum == 1) {
|
|
1855
|
-
index = me._opts.windowsBeginIndex;
|
|
1856
|
-
} else {
|
|
1857
|
-
index = me._getChoiceWindow();
|
|
1858
|
-
}
|
|
1859
|
-
return me.VIDEO_DATA[index].playbackControl(video, playType, playSpeed, startTime);
|
|
1860
|
-
},
|
|
1861
|
-
|
|
1862
|
-
saveList: function() {
|
|
1863
|
-
this._saveList = cloneObj(this.VIDEO_DATA);
|
|
1864
|
-
},
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
playSaveList: function() {
|
|
1868
|
-
if (!this._saveList) {
|
|
1869
|
-
return;
|
|
1870
|
-
}
|
|
1871
|
-
this.closeAll();
|
|
1872
|
-
let me = this;
|
|
1873
|
-
$.each(this._saveList, function(index, obj){
|
|
1874
|
-
if (obj.video) {
|
|
1875
|
-
me.play(obj.index, obj.video, obj.id, obj.opts);
|
|
1876
|
-
}
|
|
1877
|
-
});
|
|
1878
|
-
},
|
|
1879
|
-
|
|
1880
|
-
/**
|
|
1881
|
-
* 获取当前选择窗口的视频video
|
|
1882
|
-
*/
|
|
1883
|
-
getInChoiceVideo: function() {
|
|
1884
|
-
let me = this;
|
|
1885
|
-
let selView = $(me.selector + ' li.sel');
|
|
1886
|
-
if(selView.length && me.VIDEO_DATA[selView.attr("index")].video){
|
|
1887
|
-
return me.VIDEO_DATA[selView.attr("index")];
|
|
1888
|
-
}
|
|
1889
|
-
return undefined;
|
|
1890
|
-
},
|
|
1891
|
-
|
|
1892
|
-
/**
|
|
1893
|
-
* 设置全屏
|
|
1894
|
-
*/
|
|
1895
|
-
setFullScreen: function() {
|
|
1896
|
-
this._fullScreenEvent(document.getElementById("video-main-web-rtc"));
|
|
1897
|
-
},
|
|
1898
|
-
|
|
1899
|
-
/**
|
|
1900
|
-
* 获取当前视频控件的配置项
|
|
1901
|
-
*/
|
|
1902
|
-
getVideoControllerOpts: function() {
|
|
1903
|
-
return this._opts;
|
|
1904
|
-
},
|
|
1905
|
-
|
|
1906
|
-
/**
|
|
1907
|
-
* 获取截屏数据
|
|
1908
|
-
* @param callback 回调函数
|
|
1909
|
-
*/
|
|
1910
|
-
getScreenCaptureData: function(index, callback) {
|
|
1911
|
-
let me = this;
|
|
1912
|
-
|
|
1913
|
-
//如果index为空则使用选中窗口的index
|
|
1914
|
-
let dataObj = me.VIDEO_DATA[index != undefined ? index : me._getChoiceWindow()];
|
|
1915
|
-
|
|
1916
|
-
if (!dataObj.playing) {
|
|
1917
|
-
promptAlarm('请选择播放的视频源!');
|
|
1918
|
-
return;
|
|
1919
|
-
}
|
|
1920
|
-
|
|
1921
|
-
let canvasObj = document.getElementById('myCanvas');
|
|
1922
|
-
let videoObj = dataObj.tagBox.get(0);
|
|
1923
|
-
if (videoObj == undefined) {
|
|
1924
|
-
return;
|
|
1925
|
-
}
|
|
1926
|
-
// 取流中 取视频框尺寸
|
|
1927
|
-
// 播放中 取视频画面尺寸
|
|
1928
|
-
if (dataObj.tagBox.parent().find(".stream-loading").length != 0) {
|
|
1929
|
-
canvasObj.width = dataObj.tagBox.width();
|
|
1930
|
-
canvasObj.height = dataObj.tagBox.height();
|
|
1931
|
-
} else {
|
|
1932
|
-
canvasObj.width = videoObj.videoWidth;
|
|
1933
|
-
canvasObj.height = videoObj.videoHeight;
|
|
1934
|
-
}
|
|
1935
|
-
|
|
1936
|
-
let ctx = canvasObj.getContext("2d");
|
|
1937
|
-
ctx.drawImage(videoObj, 0, 0, videoObj.videoWidth, videoObj.videoHeight);
|
|
1938
|
-
|
|
1939
|
-
let dataUrl = canvasObj.toDataURL('image/jpeg');
|
|
1940
|
-
callback ? callback(dataUrl) : null;
|
|
1941
|
-
},
|
|
1942
|
-
|
|
1943
|
-
/**
|
|
1944
|
-
* 开始录像
|
|
1945
|
-
*/
|
|
1946
|
-
startAvRecord: function(index) {
|
|
1947
|
-
let me = this;
|
|
1948
|
-
return me.VIDEO_DATA[index].recordAv("start_av_record", recordAvBusinessId);
|
|
1949
|
-
},
|
|
1950
|
-
|
|
1951
|
-
/**
|
|
1952
|
-
* 结束录像
|
|
1953
|
-
*/
|
|
1954
|
-
stopAvRecord: function(index) {
|
|
1955
|
-
let me = this;
|
|
1956
|
-
return me.VIDEO_DATA[index].recordAv("stop_av_record", recordAvBusinessId);
|
|
1957
|
-
},
|
|
1958
|
-
|
|
1959
|
-
/**
|
|
1960
|
-
* 改变分辨率
|
|
1961
|
-
* @param resolution 新分辨率
|
|
1962
|
-
*/
|
|
1963
|
-
changeResolution: function(index, resolution) {
|
|
1964
|
-
let me = this;
|
|
1965
|
-
return me.VIDEO_DATA[index].changeResolution("change_resolution", resolution);
|
|
1966
|
-
},
|
|
1967
|
-
|
|
1968
|
-
/**
|
|
1969
|
-
* 开启对讲预呼叫
|
|
1970
|
-
* @param pocNo 对讲号码
|
|
1971
|
-
* @param centerTel 调度中心号
|
|
1972
|
-
*/
|
|
1973
|
-
openPocCall: function(pocNo, centerTel) {
|
|
1974
|
-
let me = this;
|
|
1975
|
-
|
|
1976
|
-
let index;
|
|
1977
|
-
//对讲预呼叫默认使用一个窗口
|
|
1978
|
-
if (me._opts.windowsNum == 1) {
|
|
1979
|
-
index = me._opts.windowsBeginIndex;
|
|
1980
|
-
} else {
|
|
1981
|
-
index = me._getMinIndexFreeWindow();
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
if (index < 0) {
|
|
1985
|
-
console.error('窗口编号获取失败!')
|
|
1986
|
-
}
|
|
1987
|
-
//保存对讲号码
|
|
1988
|
-
window.pocNo = pocNo;
|
|
1989
|
-
return me.VIDEO_DATA[index].pocCall("open_poccall", pocNo, centerTel);
|
|
1990
|
-
},
|
|
1991
|
-
|
|
1992
|
-
/**
|
|
1993
|
-
* 关闭对讲预呼叫
|
|
1994
|
-
* @param pocNo 对讲号码
|
|
1995
|
-
* @param centerTel 调度中心号
|
|
1996
|
-
*/
|
|
1997
|
-
closePocCall: function(pocNo, centerTel) {
|
|
1998
|
-
let me = this;
|
|
1999
|
-
|
|
2000
|
-
let index;
|
|
2001
|
-
//对讲预呼叫默认使用一个窗口
|
|
2002
|
-
if (me._opts.windowsNum == 1) {
|
|
2003
|
-
index = me._opts.windowsBeginIndex;
|
|
2004
|
-
} else {
|
|
2005
|
-
index = me._getMinIndexFreeWindow();
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
|
-
if (index < 0) {
|
|
2009
|
-
console.error('窗口编号获取失败!')
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
me.VIDEO_DATA[index].stream = null;
|
|
2013
|
-
window.pocNo = null;
|
|
2014
|
-
return me.VIDEO_DATA[index].pocCall("close_poccall", pocNo, centerTel);
|
|
2015
|
-
},
|
|
2016
|
-
|
|
2017
|
-
/**
|
|
2018
|
-
* 设置录像的businessId
|
|
2019
|
-
* @param businessId 业务ID
|
|
2020
|
-
*/
|
|
2021
|
-
setRecordAvBusinessId: function(businessId) {
|
|
2022
|
-
//let me = this;
|
|
2023
|
-
recordAvBusinessId = businessId;
|
|
2024
|
-
},
|
|
2025
|
-
|
|
2026
|
-
/**
|
|
2027
|
-
* 开启音频
|
|
2028
|
-
*/
|
|
2029
|
-
sendAudio: function(index) {
|
|
2030
|
-
let me = this;
|
|
2031
|
-
index = (index != undefined ? index : me._opts.windowsBeginIndex);
|
|
2032
|
-
me.VIDEO_DATA[index].stream.getAudioTracks()[0].enabled = true;
|
|
2033
|
-
},
|
|
2034
|
-
|
|
2035
|
-
/**
|
|
2036
|
-
* 关闭音频
|
|
2037
|
-
*/
|
|
2038
|
-
unSendAudio: function(index) {
|
|
2039
|
-
let me = this;
|
|
2040
|
-
index = (index != undefined ? index : me._opts.windowsBeginIndex);
|
|
2041
|
-
me.VIDEO_DATA[index].stream.getAudioTracks()[0].enabled = false;
|
|
2042
|
-
},
|
|
2043
|
-
|
|
2044
|
-
/**
|
|
2045
|
-
* 添加事件
|
|
2046
|
-
*/
|
|
2047
|
-
addListener: function(type, handler, key){
|
|
2048
|
-
this.videoListener.addListener(type, handler, key);
|
|
2049
|
-
},
|
|
2050
|
-
|
|
2051
|
-
/**
|
|
2052
|
-
* 删除事件
|
|
2053
|
-
*/
|
|
2054
|
-
removeListener: function(type, handler){
|
|
2055
|
-
this.videoListener.removeListener(type, handler);
|
|
2056
|
-
},
|
|
2057
|
-
/**
|
|
2058
|
-
* 派发事件
|
|
2059
|
-
*/
|
|
2060
|
-
dispatch: function(e, options){
|
|
2061
|
-
this.videoListener.dispatch(e, options);
|
|
2062
|
-
},
|
|
2063
|
-
|
|
2064
|
-
/**
|
|
2065
|
-
* 清空事件
|
|
2066
|
-
*/
|
|
2067
|
-
removeAllListeners: function() {
|
|
2068
|
-
this.videoListener.removeAllListeners();
|
|
2069
|
-
},
|
|
2070
|
-
/**
|
|
2071
|
-
* 获取编号最小的空闲窗口的编号
|
|
2072
|
-
*/
|
|
2073
|
-
_getMinIndexFreeWindow: function(index) {
|
|
2074
|
-
let me = this;
|
|
2075
|
-
index = index || me._opts.windowsBeginIndex;
|
|
2076
|
-
for (; index < me._opts.windowsBeginIndex + me._opts.windows ; index++) {
|
|
2077
|
-
if (!me.VIDEO_DATA[index].playing && !me.VIDEO_DATA[index].isWaiting) {
|
|
2078
|
-
return index;
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
return -1;
|
|
2082
|
-
},
|
|
2083
|
-
|
|
2084
|
-
/**
|
|
2085
|
-
* 获取选中的窗口的index
|
|
2086
|
-
*/
|
|
2087
|
-
_getChoiceWindow: function() {
|
|
2088
|
-
let me = this;
|
|
2089
|
-
let selView = $(me.selector + ' li.sel');
|
|
2090
|
-
if (selView.length) {
|
|
2091
|
-
return selView.index();
|
|
2092
|
-
}
|
|
2093
|
-
return -1;
|
|
2094
|
-
},
|
|
2095
|
-
|
|
2096
|
-
/**
|
|
2097
|
-
* 获取下一窗口
|
|
2098
|
-
*/
|
|
2099
|
-
_getNextWindowsNum: function(old) {
|
|
2100
|
-
let me = this;
|
|
2101
|
-
let windowsArr = me._windowsArr;
|
|
2102
|
-
for (let index in windowsArr){
|
|
2103
|
-
if (index == windowsArr.length - 1) {
|
|
2104
|
-
return windowsArr[index]
|
|
2105
|
-
}
|
|
2106
|
-
if (old == windowsArr[index]) {
|
|
2107
|
-
return windowsArr[Number(index) + Number(1)];
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
},
|
|
2111
|
-
|
|
2112
|
-
/**
|
|
2113
|
-
* 设置鼠标选中窗口
|
|
2114
|
-
*/
|
|
2115
|
-
_clickWindow: function() {
|
|
2116
|
-
let me = this;
|
|
2117
|
-
//视频窗口选中
|
|
2118
|
-
$(me.selector + ' li').click(function(){
|
|
2119
|
-
$(me.selector + ' li').removeClass("sel");
|
|
2120
|
-
$(this).addClass("sel");
|
|
2121
|
-
|
|
2122
|
-
//如果视频正在播放则分发点击消息
|
|
2123
|
-
if (me.getInChoiceVideo()) {
|
|
2124
|
-
me.dispatch('click', me.getInChoiceVideo());
|
|
2125
|
-
}
|
|
2126
|
-
});
|
|
2127
|
-
// 设置视频窗可拖拽
|
|
2128
|
-
let src = null;
|
|
2129
|
-
$(me.selector + ' li').bind("dragstart", function (ev) {
|
|
2130
|
-
src = $(this);
|
|
2131
|
-
})
|
|
2132
|
-
|
|
2133
|
-
$(me.selector + ' li').bind("dragover", function (ev) {
|
|
2134
|
-
ev.preventDefault();
|
|
2135
|
-
})
|
|
2136
|
-
|
|
2137
|
-
$(me.selector + ' li').bind("drop", function (ev) {
|
|
2138
|
-
//拖拽交换位置后,更改index,更改相应的video_data数组中对应的对象索引位置
|
|
2139
|
-
console.log(ev)
|
|
2140
|
-
ev.preventDefault();
|
|
2141
|
-
if(src.prop("outerHTML") === $(this).prop("outerHTML")){
|
|
2142
|
-
return;
|
|
2143
|
-
}
|
|
2144
|
-
let target = $(this);
|
|
2145
|
-
let srcIndex = src.index();
|
|
2146
|
-
let targetIndex = target.index();
|
|
2147
|
-
target.removeClass('screen-' + (targetIndex + 1)).addClass('screen-' + (srcIndex + 1))
|
|
2148
|
-
src.removeClass('screen-' + (srcIndex + 1)).addClass('screen-' + (targetIndex + 1))
|
|
2149
|
-
target.attr('index', srcIndex)
|
|
2150
|
-
src.attr('index', targetIndex)
|
|
2151
|
-
src.children('#frame-decoded-' + (srcIndex + 1)).attr('id', 'frame-decoded-' + (targetIndex + 1))
|
|
2152
|
-
target.children('#frame-decoded-' + (targetIndex + 1)).attr('id', 'frame-decoded-' + (srcIndex + 1))
|
|
2153
|
-
src.children('#info-self' + (srcIndex + 1)).attr('id', 'info-self-' + (targetIndex + 1))
|
|
2154
|
-
target.children('#info-self-' + (targetIndex + 1)).attr('id', 'info-self-' + (srcIndex + 1))
|
|
2155
|
-
|
|
2156
|
-
let videoData = me.VIDEO_DATA;
|
|
2157
|
-
if (srcIndex > targetIndex) {
|
|
2158
|
-
src.insertBefore(target);
|
|
2159
|
-
target.insertAfter($(me.selector +' .video-main li.screen').eq(srcIndex));
|
|
2160
|
-
} else {
|
|
2161
|
-
src.insertAfter(target);
|
|
2162
|
-
target.insertBefore($(me.selector +' .video-main li.screen').eq(srcIndex));
|
|
2163
|
-
}
|
|
2164
|
-
let targetVideo = videoData[targetIndex]
|
|
2165
|
-
let srcVideo = videoData.splice(srcIndex, 1, targetVideo)
|
|
2166
|
-
videoData.splice(targetIndex, 1, ...srcVideo)
|
|
2167
|
-
})
|
|
2168
|
-
},
|
|
2169
|
-
|
|
2170
|
-
/*
|
|
2171
|
-
* 总的初始化
|
|
2172
|
-
* 参数示例:
|
|
2173
|
-
* let opts = {
|
|
2174
|
-
windows: 4, //初始化的窗口数
|
|
2175
|
-
conf: { //配置参数
|
|
2176
|
-
user: 'admin', //用户名
|
|
2177
|
-
passwd: '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b', //密码
|
|
2178
|
-
janusUrl: 'wss: //192.168.103.226:8989', //janusServer服务地址
|
|
2179
|
-
},
|
|
2180
|
-
pollInterval: 30 //轮巡时间,单位秒
|
|
2181
|
-
};
|
|
2182
|
-
*/
|
|
2183
|
-
_init: function($dom,opts){
|
|
2184
|
-
let me = this;
|
|
2185
|
-
//保存dom元素的selector用作后续所有子集对象的定位(在多组件对讲模式下有用)
|
|
2186
|
-
if($dom.length == 0 || !me.getDomSelector($dom)) {
|
|
2187
|
-
console.error("父doom元素为空,无法进行视频初始化", $dom);
|
|
2188
|
-
return ;
|
|
2189
|
-
}
|
|
2190
|
-
//配置项
|
|
2191
|
-
me._opts = {
|
|
2192
|
-
windows: 4,
|
|
2193
|
-
conf: {},
|
|
2194
|
-
pollInterval: 10,
|
|
2195
|
-
windowsNum: 16,
|
|
2196
|
-
isVideoTag: true, //true生成video标签 false生产audio标签 默认true
|
|
2197
|
-
showVideoInfo: 1, //显示分辨率、码率等信息,1-显示左下角 2-显示左上角,为0时控制_showVideoInfo函数处理,默认1
|
|
2198
|
-
waitPlayQueueSwitch: false, //播放队列开关,默认false
|
|
2199
|
-
defaultBusinessType: 0, // 配置的默认业务类型 0:调度主线 1:勤指
|
|
2200
|
-
videoTipTimeOut: 5, // 超时无首屏检测时间
|
|
2201
|
-
};
|
|
2202
|
-
|
|
2203
|
-
$.extend(me._opts,opts);
|
|
2204
|
-
|
|
2205
|
-
let windowsArr = me._opts.windowsArr;
|
|
2206
|
-
if (!windowsArr || windowsArr.length == 0) {
|
|
2207
|
-
me._windowList = {1:{}, 4:{}, 6:{}, 9:{}, 16:{}}
|
|
2208
|
-
me._windowsArr = [1, 4, 6, 9, 16];
|
|
2209
|
-
} else {
|
|
2210
|
-
me._windowList = {};
|
|
2211
|
-
for (let index in windowsArr){
|
|
2212
|
-
let item = windowsArr[index];
|
|
2213
|
-
me._windowList[item] = {};
|
|
2214
|
-
}
|
|
2215
|
-
me._windowsArr = windowsArr;
|
|
2216
|
-
}
|
|
2217
|
-
|
|
2218
|
-
//获取起始的窗口位置
|
|
2219
|
-
me._opts.windowsBeginIndex = 0;
|
|
2220
|
-
// 对讲号码初始化
|
|
2221
|
-
window.pocNo = 0;
|
|
2222
|
-
// 播放队列开关 默认打开
|
|
2223
|
-
me.waitPlayQueueSwitch = opts.waitPlayQueueSwitch == undefined ? false : opts.waitPlayQueueSwitch;
|
|
2224
|
-
|
|
2225
|
-
//是否提示
|
|
2226
|
-
me._opts.showPrompt === false && (showPrompt = false);
|
|
2227
|
-
// 勤指业务下 设备检测
|
|
2228
|
-
me._opts.defaultBusinessType == 1 && me._checkDevices();
|
|
2229
|
-
//初始化界面
|
|
2230
|
-
me._opts.isVideoTag ? me._initVideoView($dom, me._opts.showVideoInfo) : me._initAudioView($dom);
|
|
2231
|
-
|
|
2232
|
-
//初始化Janus
|
|
2233
|
-
me._initJanus();
|
|
2234
|
-
//初始化按钮点击事件
|
|
2235
|
-
me._initBtnEvent();
|
|
2236
|
-
// 初始化事件监听
|
|
2237
|
-
me._initEventListen();
|
|
2238
|
-
|
|
2239
|
-
//设置鼠标点击选中窗口
|
|
2240
|
-
me._clickWindow();
|
|
2241
|
-
if (me._opts.showVideoInfo != 0) {
|
|
2242
|
-
//显示视频信息:名称、分辨率、码率、丢包率
|
|
2243
|
-
me._showVideoInfo();
|
|
2244
|
-
}
|
|
2245
|
-
//双击某个视频全屏
|
|
2246
|
-
me._dbClickFullScreen();
|
|
2247
|
-
},
|
|
2248
|
-
|
|
2249
|
-
videoRotateSize(li, rotateIndex){
|
|
2250
|
-
if(!li) return
|
|
2251
|
-
let video = li.querySelector('video');
|
|
2252
|
-
let videoWidth = video.videoWidth;
|
|
2253
|
-
let videoHeight = video.videoHeight;
|
|
2254
|
-
let vWidth = video.offsetWidth
|
|
2255
|
-
let vHeight = video.offsetHeight
|
|
2256
|
-
let liWidth = li.offsetWidth;
|
|
2257
|
-
let liHeight = li.offsetHeight;
|
|
2258
|
-
if(rotateIndex == 0){ //0
|
|
2259
|
-
$(video).attr('class', 'video-box');
|
|
2260
|
-
$(video).css('height', 'auto');
|
|
2261
|
-
$(video).css('width', 'auto');
|
|
2262
|
-
$(video).css('max-height', '100%');
|
|
2263
|
-
$(video).css('max-width', '100%');
|
|
2264
|
-
video.style.position = 'absolute';
|
|
2265
|
-
$(video).css('left', '50%');
|
|
2266
|
-
$(video).css('top', '50%');
|
|
2267
|
-
video.style.transform = 'translate(-50%, -50%)';
|
|
2268
|
-
}else if(rotateIndex == 3){ //3
|
|
2269
|
-
$(video).attr('class', 'video-box');
|
|
2270
|
-
video.style.position = 'absolute';
|
|
2271
|
-
video.style.transform = 'rotate(270deg)';
|
|
2272
|
-
$(video).css('max-height', 'none');
|
|
2273
|
-
$(video).css('max-width', 'none');
|
|
2274
|
-
if(videoHeight * liHeight / videoWidth < liWidth){ //视频横向留白
|
|
2275
|
-
$(video).css('width', liHeight);
|
|
2276
|
-
$(video).css('height', 'auto');
|
|
2277
|
-
$(video).css('left', 'calc(' + liWidth + 'px / 2' + ' - ' + liHeight + 'px / 2)');
|
|
2278
|
-
$(video).css('top', 'calc(-' + videoHeight * liHeight / videoWidth / 2 + 'px + ' + liHeight + 'px / 2)');
|
|
2279
|
-
}else { //视频纵向留白
|
|
2280
|
-
$(video).css('width', 'auto');
|
|
2281
|
-
$(video).css('height', liWidth);
|
|
2282
|
-
$(video).css('left', 'calc(-' + videoWidth * liWidth / videoHeight / 2 + 'px + ' + liWidth + 'px / 2)');
|
|
2283
|
-
$(video).css('top', 'calc(' + liHeight + 'px / 2' + ' - ' + liWidth + 'px / 2)');
|
|
2284
|
-
}
|
|
2285
|
-
}else if(rotateIndex == 2){ //2
|
|
2286
|
-
$(video).attr('class', 'video-box');
|
|
2287
|
-
$(video).css('height', 'auto');
|
|
2288
|
-
$(video).css('width', 'auto');
|
|
2289
|
-
$(video).css('max-height', '100%');
|
|
2290
|
-
$(video).css('max-width', '100%');
|
|
2291
|
-
video.style.position = 'absolute';
|
|
2292
|
-
$(video).css('left', '50%');
|
|
2293
|
-
$(video).css('top', '50%');
|
|
2294
|
-
video.style.transform = 'translate(-50%, -50%) rotate(180deg)';
|
|
2295
|
-
}else if(rotateIndex == 1){ //1
|
|
2296
|
-
$(video).attr('class', 'video-box');
|
|
2297
|
-
video.style.position = 'absolute';
|
|
2298
|
-
video.style.transform = 'rotate(90deg)';
|
|
2299
|
-
$(video).css('max-height', 'none');
|
|
2300
|
-
$(video).css('max-width', 'none');
|
|
2301
|
-
if(videoHeight * liHeight / videoWidth < liWidth){ //视频横向留白
|
|
2302
|
-
$(video).css('width', liHeight);
|
|
2303
|
-
$(video).css('height', 'auto');
|
|
2304
|
-
$(video).css('left', 'calc(' + liWidth + 'px / 2' + ' - ' + liHeight + 'px / 2)');
|
|
2305
|
-
$(video).css('top', 'calc(-' + videoHeight * liHeight / videoWidth / 2 + 'px + ' + liHeight + 'px / 2)');
|
|
2306
|
-
}else { //视频纵向留白
|
|
2307
|
-
$(video).css('width', 'auto');
|
|
2308
|
-
$(video).css('height', liWidth);
|
|
2309
|
-
$(video).css('left', 'calc(-' + videoWidth * liWidth / videoHeight / 2 + 'px + ' + liWidth + 'px / 2)');
|
|
2310
|
-
$(video).css('top', 'calc(' + liHeight + 'px / 2' + ' - ' + liWidth + 'px / 2)');
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
},
|
|
2314
|
-
/**
|
|
2315
|
-
* 获取父窗口传入dom的唯一selector(针对jquery高版本dom对象没有selector属性的问题)
|
|
2316
|
-
* @param $dom
|
|
2317
|
-
* @return {boolean}
|
|
2318
|
-
*/
|
|
2319
|
-
getDomSelector: function($dom) {
|
|
2320
|
-
var me = this;
|
|
2321
|
-
if($dom.selector) {
|
|
2322
|
-
me.selector = $dom.selector;
|
|
2323
|
-
}
|
|
2324
|
-
else {
|
|
2325
|
-
if($dom.attr("id")) {
|
|
2326
|
-
me.selector = "#" + $dom.attr("id");
|
|
2327
|
-
}
|
|
2328
|
-
else {
|
|
2329
|
-
if(!$dom.attr("class")) return false;
|
|
2330
|
-
var classNames = $dom.attr("class").split(/\s+/);
|
|
2331
|
-
$.each(classNames, function (i, className) {
|
|
2332
|
-
if ($("." + className).length == 1) {
|
|
2333
|
-
me.selector = "." + className;
|
|
2334
|
-
return true;
|
|
2335
|
-
}
|
|
2336
|
-
});
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
if(!me.selector) return false;
|
|
2340
|
-
else return true;
|
|
2341
|
-
},
|
|
2342
|
-
|
|
2343
|
-
/**
|
|
2344
|
-
* 初始化按钮点击事件
|
|
2345
|
-
*/
|
|
2346
|
-
_initBtnEvent: function() {
|
|
2347
|
-
let me = this;
|
|
2348
|
-
let videoFlagObj = $(me.selector + ' .video-main');
|
|
2349
|
-
|
|
2350
|
-
//锁定视频事件
|
|
2351
|
-
videoFlagObj.find("button[name='lockVideo']").click(function(){
|
|
2352
|
-
let index = Number($(this).parent().parent().attr("index"));
|
|
2353
|
-
|
|
2354
|
-
if (!me.VIDEO_DATA[index].playing) {
|
|
2355
|
-
promptAlarm('请选择播放的视频源!');
|
|
2356
|
-
return;
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
|
-
if ($(this).attr('class') == 'lock-video-btn') {
|
|
2360
|
-
me.VIDEO_DATA[index].isLockVideo = false;
|
|
2361
|
-
$(this).attr('class', 'unlock-video-btn');
|
|
2362
|
-
} else {
|
|
2363
|
-
me.VIDEO_DATA[index].isLockVideo = true;
|
|
2364
|
-
$(this).attr('class', 'lock-video-btn');
|
|
2365
|
-
}
|
|
2366
|
-
//jquery方式阻止默认事件 & 冒泡事件
|
|
2367
|
-
return false;
|
|
2368
|
-
});
|
|
2369
|
-
videoFlagObj.find('button[name=rotateVideo]').click(function(){
|
|
2370
|
-
let rotateIndex = Number($(this).attr("rotate-index"));
|
|
2371
|
-
rotateIndex++
|
|
2372
|
-
rotateIndex %= 4
|
|
2373
|
-
$(this).attr("rotate-index", rotateIndex);
|
|
2374
|
-
let li = $(this).parent().parent()[0];
|
|
2375
|
-
me.videoRotateSize(li, rotateIndex)
|
|
2376
|
-
//jquery方式阻止默认事件 & 冒泡事件
|
|
2377
|
-
return false;
|
|
2378
|
-
})
|
|
2379
|
-
videoFlagObj.find('button[name=scaleVideo]').click(function(){
|
|
2380
|
-
let isgray = $(this).hasClass('bggray')
|
|
2381
|
-
if(isgray) {
|
|
2382
|
-
$(this).parent().parent().find('.video-box').addClass('scale-scene')
|
|
2383
|
-
$(this).attr('title', '原视频分辨率展示')
|
|
2384
|
-
}
|
|
2385
|
-
else {
|
|
2386
|
-
$(this).parent().parent().find('.video-box').removeClass('scale-scene')
|
|
2387
|
-
$(this).attr('title', '视频画面铺满')
|
|
2388
|
-
}
|
|
2389
|
-
$(this).toggleClass("bggray")
|
|
2390
|
-
//jquery方式阻止默认事件 & 冒泡事件
|
|
2391
|
-
return false;
|
|
2392
|
-
})
|
|
2393
|
-
|
|
2394
|
-
//接收音频事件
|
|
2395
|
-
videoFlagObj.find("button[name='recvAudio']").click(function(){
|
|
2396
|
-
let _self = this;
|
|
2397
|
-
let index = Number($(this).parent().parent().attr("index"));
|
|
2398
|
-
// 优先当前窗口参数设置的业务类型 其次配置的默认业务类型
|
|
2399
|
-
let businessType = me.VIDEO_DATA[index].opts.businessType == undefined ? me._opts.defaultBusinessType : me.VIDEO_DATA[index].opts.businessType;
|
|
2400
|
-
|
|
2401
|
-
if (!me.VIDEO_DATA[index].playing) {
|
|
2402
|
-
promptAlarm('请选择播放的视频源!');
|
|
2403
|
-
return;
|
|
2404
|
-
}
|
|
2405
|
-
|
|
2406
|
-
if ($(this).attr('class') == 'recv-audio-btn') {
|
|
2407
|
-
//发送停止播放音频的请求
|
|
2408
|
-
me.VIDEO_DATA[index].operateAudio("stop_audio")
|
|
2409
|
-
$(this).attr('class', 'unrecv-audio-btn');
|
|
2410
|
-
me.VIDEO_DATA[index].tagBox.prop("muted", true);
|
|
2411
|
-
} else {
|
|
2412
|
-
if (businessType == 0) {
|
|
2413
|
-
//发送前先关闭其它音频通道(包括接收和发送音频)
|
|
2414
|
-
let lis = $($(_self).parent().parent().parent()).children();
|
|
2415
|
-
for (let i = 0; i < lis.length; i++) {
|
|
2416
|
-
let btnIndex = Number($(lis[i]).attr("index"));
|
|
2417
|
-
if (index == btnIndex) {
|
|
2418
|
-
continue;
|
|
2419
|
-
}
|
|
2420
|
-
let recvBtn = $($(lis[i]).find("button[name='recvAudio']")[0]);
|
|
2421
|
-
let sendBtn = $($(lis[i]).find("button[name='sendAudio']")[0]);
|
|
2422
|
-
|
|
2423
|
-
if (recvBtn.attr("class") == 'recv-audio-btn') {
|
|
2424
|
-
if (me.VIDEO_DATA[btnIndex].playing) {
|
|
2425
|
-
recvBtn.click();
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
if (sendBtn.attr("class") == 'send-audio-btn') {
|
|
2429
|
-
if (me.VIDEO_DATA[btnIndex].playing) {
|
|
2430
|
-
sendBtn.click();
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
//发送播放音频的请求
|
|
2435
|
-
$(_self).attr('class', 'recv-audio-btn');
|
|
2436
|
-
setTimeout(function () {
|
|
2437
|
-
if(!me.VIDEO_DATA[index].isClosing){
|
|
2438
|
-
me.VIDEO_DATA[index].operateAudio("recv_audio");
|
|
2439
|
-
me.VIDEO_DATA[index].tagBox.prop("muted", false);
|
|
2440
|
-
}
|
|
2441
|
-
}, 1000);
|
|
2442
|
-
} else if (businessType == 1) {
|
|
2443
|
-
// poc新模式支持回传多个音频,因此不关闭
|
|
2444
|
-
//发送播放音频的请求
|
|
2445
|
-
$(_self).attr('class', 'recv-audio-btn');
|
|
2446
|
-
me.VIDEO_DATA[index].operateAudio("recv_audio");
|
|
2447
|
-
me.VIDEO_DATA[index].tagBox.prop("muted", false)
|
|
2448
|
-
}
|
|
2449
|
-
}
|
|
2450
|
-
});
|
|
2451
|
-
|
|
2452
|
-
//发送音频事件
|
|
2453
|
-
videoFlagObj.find("button[name='sendAudio']").click(function(){
|
|
2454
|
-
let index = Number($(this).parent().parent().attr("index"));
|
|
2455
|
-
// 优先当前窗口参数设置的业务类型 其次配置的默认业务类型 最后默认调度业务
|
|
2456
|
-
let businessType = me.VIDEO_DATA[index].opts.businessType == undefined ? me._opts.defaultBusinessType : me.VIDEO_DATA[index].opts.businessType;
|
|
2457
|
-
|
|
2458
|
-
if (!me.VIDEO_DATA[index].playing) {
|
|
2459
|
-
promptAlarm('请选择播放的视频源!');
|
|
2460
|
-
return;
|
|
2461
|
-
}
|
|
2462
|
-
if (businessType == 0) {
|
|
2463
|
-
// 主线业务
|
|
2464
|
-
if ($(this).attr('class') == 'send-audio-btn') {
|
|
2465
|
-
me.VIDEO_DATA[index].operateAudio("unsend_audio")
|
|
2466
|
-
$(this).attr('class', 'unsend-audio-btn');
|
|
2467
|
-
me.VIDEO_DATA[index].stream.getAudioTracks()[0].enabled = false;
|
|
2468
|
-
} else {
|
|
2469
|
-
me.VIDEO_DATA[index].operateAudio("send_audio");
|
|
2470
|
-
$(this).attr('class', 'send-audio-btn');
|
|
2471
|
-
me.VIDEO_DATA[index].stream.getAudioTracks()[0].enabled = true;
|
|
2472
|
-
}
|
|
2473
|
-
} else if (businessType == 1) {
|
|
2474
|
-
// 勤指业务
|
|
2475
|
-
if ($(this).attr('class') == 'send-audio-btn') {
|
|
2476
|
-
$(this).attr('class', 'unsend-audio-btn');
|
|
2477
|
-
//关闭点对点对讲
|
|
2478
|
-
me.VIDEO_DATA[index].ptopPoc("close_ptop_poc", window.pocNo);
|
|
2479
|
-
} else {
|
|
2480
|
-
$(this).attr('class', 'send-audio-btn');
|
|
2481
|
-
//发起点对点对讲
|
|
2482
|
-
me.VIDEO_DATA[index].ptopPoc("open_ptop_poc", window.pocNo);
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
//jquery方式阻止默认事件 & 冒泡事件
|
|
2486
|
-
return false;
|
|
2487
|
-
});
|
|
2488
|
-
|
|
2489
|
-
//关闭视频事件
|
|
2490
|
-
videoFlagObj.find("button[name='closeVideo']").click(function(){
|
|
2491
|
-
let index = Number($(this).parent().parent().attr("index"));
|
|
2492
|
-
me.close(index);
|
|
2493
|
-
// //jquery方式阻止默认事件 & 冒泡事件
|
|
2494
|
-
// return false;
|
|
2495
|
-
});
|
|
2496
|
-
},
|
|
2497
|
-
/**
|
|
2498
|
-
* 初始化事件监听
|
|
2499
|
-
*/
|
|
2500
|
-
_initEventListen: function () {
|
|
2501
|
-
let _self = this;
|
|
2502
|
-
// 打开视频 {index, video, id, opts} index(视频窗口编号,从0开始) video(视频设备id,即devId) id(标识,空的话使用设备id) opts(其他参数)
|
|
2503
|
-
_self.addListener('openVideo', function (e) {
|
|
2504
|
-
_self.play(e.index, e.video, e.id, e.opts);
|
|
2505
|
-
})
|
|
2506
|
-
|
|
2507
|
-
// janus通知后台已关闭视频
|
|
2508
|
-
_self.addListener('notifyCloseVideo', function (e) {
|
|
2509
|
-
_self._notifyWaitingVideo(e.index);
|
|
2510
|
-
});
|
|
2511
|
-
},
|
|
2512
|
-
/**
|
|
2513
|
-
* 双击某个视频全屏
|
|
2514
|
-
*/
|
|
2515
|
-
_dbClickFullScreen: function() {
|
|
2516
|
-
let me = this;
|
|
2517
|
-
$(me.selector + ' .video-main').find('.video-box').on("dblclick",function(){
|
|
2518
|
-
me._fullScreenEvent(this);
|
|
2519
|
-
});
|
|
2520
|
-
},
|
|
2521
|
-
|
|
2522
|
-
/**
|
|
2523
|
-
* 全屏事件
|
|
2524
|
-
*/
|
|
2525
|
-
_fullScreenEvent: function(el) {
|
|
2526
|
-
let isFullscreen = el.fullScreen || el.mozFullScreen || el.webkitIsFullScreen;
|
|
2527
|
-
if(!isFullscreen){//进入全屏,多重短路表达式
|
|
2528
|
-
(el.requestFullscreen && el.requestFullscreen()) ||
|
|
2529
|
-
(el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
|
|
2530
|
-
(el.webkitRequestFullscreen && el.webkitRequestFullscreen()) || (el.msRequestFullscreen && el.msRequestFullscreen());
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
//关闭全屏
|
|
2534
|
-
// colseFullscreen();
|
|
2535
|
-
// function colseFullscreen() {
|
|
2536
|
-
// el.onmouseup = function(e){ //在body里点击触发事件
|
|
2537
|
-
// if(e.button === 0){
|
|
2538
|
-
// document.exitFullscreen?document.exitFullscreen():
|
|
2539
|
-
// document.mozCancelFullScreen?document.mozCancelFullScreen():
|
|
2540
|
-
// document.webkitExitFullscreen?document.webkitExitFullscreen():'';
|
|
2541
|
-
// }
|
|
2542
|
-
// }
|
|
2543
|
-
// }
|
|
2544
|
-
},
|
|
2545
|
-
|
|
2546
|
-
/**
|
|
2547
|
-
* 在视频界面上显示视频的信息 码率、分辨率、丢包率
|
|
2548
|
-
*/
|
|
2549
|
-
_showVideoInfo: function() {
|
|
2550
|
-
let me = this;
|
|
2551
|
-
function clock(){
|
|
2552
|
-
if(!me.VIDEO_DATA || !me.VIDEO_DATA.length) return;
|
|
2553
|
-
for (let i = 0; i < me.VIDEO_DATA.length; i++) {
|
|
2554
|
-
if (me.VIDEO_DATA[i].playing) {
|
|
2555
|
-
let number = Number(me.VIDEO_DATA[i].index) + Number(1);
|
|
2556
|
-
//获取视频video标签
|
|
2557
|
-
let $videoList = $(me.selector + " .video-main #video-" + number);
|
|
2558
|
-
if(!$videoList.length) {
|
|
2559
|
-
console.error("can not find dom by id [video-" + number + "]");
|
|
2560
|
-
continue ;
|
|
2561
|
-
}
|
|
2562
|
-
let videoObj = $videoList[0];
|
|
2563
|
-
|
|
2564
|
-
if (!videoObj) continue;
|
|
2565
|
-
|
|
2566
|
-
let width = videoObj.videoWidth;
|
|
2567
|
-
let height = videoObj.videoHeight;
|
|
2568
|
-
|
|
2569
|
-
//码率
|
|
2570
|
-
let bitrate = me.VIDEO_DATA[i].sipcall.getBitrate();
|
|
2571
|
-
if (!width || !height || !bitrate || bitrate.indexOf("kbits") == -1 || bitrate.indexOf("NaN") != -1) {
|
|
2572
|
-
continue;
|
|
2573
|
-
}
|
|
2574
|
-
|
|
2575
|
-
let config = me.VIDEO_DATA[i].sipcall.webrtcStuff;
|
|
2576
|
-
me._setPacketsLostRate(i, config, me);
|
|
2577
|
-
me._setFrameDecoded(i, config, me);
|
|
2578
|
-
let resolution = width + "×" + height;
|
|
2579
|
-
switch(height + '') {
|
|
2580
|
-
case '1080':
|
|
2581
|
-
resolution = "1080P";
|
|
2582
|
-
break;
|
|
2583
|
-
case '720':
|
|
2584
|
-
resolution = "720P";
|
|
2585
|
-
break;
|
|
2586
|
-
case '480':
|
|
2587
|
-
resolution = "480P";
|
|
2588
|
-
break;
|
|
2589
|
-
case '288':
|
|
2590
|
-
resolution = "CIF";
|
|
2591
|
-
break;
|
|
2592
|
-
default:
|
|
2593
|
-
break;
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
//获取文案显示dom元素
|
|
2597
|
-
let $videoInfoList = $(me.selector + " .video-main #info-" + number);
|
|
2598
|
-
if(!$videoInfoList.length) {
|
|
2599
|
-
console.error("can not find dom by id [info-" + number + "]");
|
|
2600
|
-
continue ;
|
|
2601
|
-
}
|
|
2602
|
-
let videoInfoObj = $videoInfoList[0];
|
|
2603
|
-
let videoName = me.VIDEO_DATA[i].opts && me.VIDEO_DATA[i].opts.name ?
|
|
2604
|
-
me.VIDEO_DATA[i].opts.name : me.VIDEO_DATA[i].video;
|
|
2605
|
-
videoInfoObj.innerHTML = videoName + ' ' + resolution +
|
|
2606
|
-
'<br>丢包率:' + me.VIDEO_DATA[i].packetsLostRate + ' ' + bitrate.replace("kbits/sec", "kbps");
|
|
2607
|
-
//根据视频框大小自动计算 显示文案的文字大小
|
|
2608
|
-
let fontHeightSize = $(me.selector + " .video-main #video-" + number).height() / 15;
|
|
2609
|
-
let fontWidthSize = $(me.selector + " .video-main #video-" + number).width() / 18;
|
|
2610
|
-
//长和宽 除以 15, 取小的值做文字大小样式
|
|
2611
|
-
let fontSize = fontHeightSize < fontWidthSize? fontHeightSize:fontWidthSize;
|
|
2612
|
-
fontSize = (!fontSize || fontSize > 20)? 20 : fontSize;
|
|
2613
|
-
$("#info-" + number).css("font-size", fontSize+"px");
|
|
2614
|
-
}
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
|
|
2618
|
-
//已存在则清除
|
|
2619
|
-
if (me.videoInfoTimer) {
|
|
2620
|
-
clearInterval(me.videoInfoTimer);
|
|
2621
|
-
me.videoInfoTimer = null;
|
|
2622
|
-
}
|
|
2623
|
-
|
|
2624
|
-
me.videoInfoTimer = setInterval(clock, 1000);
|
|
2625
|
-
},
|
|
2626
|
-
/**
|
|
2627
|
-
* 获取设置丢包率
|
|
2628
|
-
*/
|
|
2629
|
-
_setPacketsLostRate: function(index, config, me) {
|
|
2630
|
-
if(config.pc != null && config.pc != undefined && config.pc.getStats) {
|
|
2631
|
-
config.pc.getStats().then(function(stats) {
|
|
2632
|
-
stats.forEach(function (res) {
|
|
2633
|
-
if(!res) {
|
|
2634
|
-
return;
|
|
2635
|
-
}
|
|
2636
|
-
let inStats = false;
|
|
2637
|
-
// Check if these are statistics on incoming media
|
|
2638
|
-
if((res.mediaType === "video" || res.id.toLowerCase().indexOf("video") > -1) &&
|
|
2639
|
-
res.type === "inbound-rtp" && res.id.indexOf("rtcp") < 0) {
|
|
2640
|
-
// New stats
|
|
2641
|
-
inStats = true;
|
|
2642
|
-
} else if(res.type == 'ssrc' && res.bytesReceived &&
|
|
2643
|
-
(res.googCodecName === "VP8" || res.googCodecName === "")) {
|
|
2644
|
-
// Older Chromer versions
|
|
2645
|
-
inStats = true;
|
|
2646
|
-
}
|
|
2647
|
-
// Parse stats now
|
|
2648
|
-
if(inStats) {
|
|
2649
|
-
if (res.hasOwnProperty("packetsLost")) {
|
|
2650
|
-
//console.info('丢包率:' + res.packetsLost);
|
|
2651
|
-
if (!res.packetsLost || isNaN(res.packetsLost) || Number(res.packetsLost) == '0' || res.packetsLost == 'NaN') {
|
|
2652
|
-
me.VIDEO_DATA[index].packetsLostRate = '0.00%';
|
|
2653
|
-
} else {
|
|
2654
|
-
let packetsLost = Number(res.packetsLost) - Number(me.VIDEO_DATA[index].packetsLostSum);
|
|
2655
|
-
let packetsReceived = Number(res.packetsReceived) - Number(me.VIDEO_DATA[index].packetsReceivedSum);
|
|
2656
|
-
|
|
2657
|
-
let packetsLostRate = 0;
|
|
2658
|
-
//防止分母是0
|
|
2659
|
-
if (packetsLost > 0) {
|
|
2660
|
-
let packetsLostRate = (Number(packetsLost) / (Number(packetsLost) + Number(packetsReceived))) * 100;
|
|
2661
|
-
}
|
|
2662
|
-
me.VIDEO_DATA[index].packetsLostRate = packetsLostRate.toFixed(2) + '%';
|
|
2663
|
-
}
|
|
2664
|
-
//window.VIDEO_DATA[index].packetsLostRate = (Number(res.packetsLost) / (Number(res.packetsLost) + Number(res.packetsReceived))) * 100;
|
|
2665
|
-
/* videoInfoObj.innerHTML = videoName + ' ' + width + "×" + height +
|
|
2666
|
-
'<br>' + bitrate + ' Lost:' + res.packetsLost;*/
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
});
|
|
2670
|
-
});
|
|
2671
|
-
}
|
|
2672
|
-
},
|
|
2673
|
-
|
|
2674
|
-
/**
|
|
2675
|
-
* 设置当前网络信号提示
|
|
2676
|
-
* @param index 当前打开视频的索引
|
|
2677
|
-
* @param config
|
|
2678
|
-
* @param me
|
|
2679
|
-
* @private
|
|
2680
|
-
*/
|
|
2681
|
-
_setFrameDecoded: function(index, config, me) {
|
|
2682
|
-
if (config.pc !== null && typeof config.pc !== 'undefined' && config.pc.getStats) {
|
|
2683
|
-
config.pc.getStats().then(function (stats) {
|
|
2684
|
-
stats.forEach(function (res) {
|
|
2685
|
-
if (res) {
|
|
2686
|
-
let inStats = false;
|
|
2687
|
-
// Check if these are statistics on incoming media
|
|
2688
|
-
if ((res.mediaType === 'video' || res.id.toLowerCase().indexOf('video') > -1) &&
|
|
2689
|
-
res.type === 'inbound-rtp' && res.id.indexOf('rtcp') < 0) {
|
|
2690
|
-
// New stats
|
|
2691
|
-
inStats = true;
|
|
2692
|
-
} else if (res.type === 'ssrc' && res.bytesReceived &&
|
|
2693
|
-
(res.googCodecName === 'VP8' || res.googCodecName === '')) {
|
|
2694
|
-
// Older Chromer versions
|
|
2695
|
-
inStats = true;
|
|
2696
|
-
}
|
|
2697
|
-
// Parse stats now
|
|
2698
|
-
if (inStats) {
|
|
2699
|
-
if (res.hasOwnProperty('framesDecoded')) {
|
|
2700
|
-
if (res.framesDecoded <= 1) return;
|
|
2701
|
-
if (typeof me.VIDEO_DATA[index].framesDecodedCount === 'undefined') {
|
|
2702
|
-
me.VIDEO_DATA[index].framesDecodedCount = 0;
|
|
2703
|
-
}
|
|
2704
|
-
if (typeof me.VIDEO_DATA[index].framesDecodedLast === 'undefined') {
|
|
2705
|
-
me.VIDEO_DATA[index].framesDecodedLast = res.framesDecoded;
|
|
2706
|
-
}
|
|
2707
|
-
if (res.framesDecoded > me.VIDEO_DATA[index].framesDecodedLast) {
|
|
2708
|
-
if (typeof me.VIDEO_DATA[index].tipDom !== 'undefined' && me.VIDEO_DATA[index].tipDom.style.display === 'block') {
|
|
2709
|
-
me.VIDEO_DATA[index].tipDom.style.display = 'none';
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
me.VIDEO_DATA[index].framesDecodedCount++;
|
|
2713
|
-
// 定时检测
|
|
2714
|
-
if (me.VIDEO_DATA[index].framesDecodedCount === me.configOpt) {
|
|
2715
|
-
if (res.framesDecoded - me.VIDEO_DATA[index].framesDecodedLast === 0) { // 卡顿
|
|
2716
|
-
if (typeof me.VIDEO_DATA[index].tipDom === 'undefined') {
|
|
2717
|
-
var numIndex = index + 1;
|
|
2718
|
-
me.VIDEO_DATA[index].tipDom = document.getElementById('frame-decoded-' + numIndex);
|
|
2719
|
-
}
|
|
2720
|
-
me.VIDEO_DATA[index].tipDom.style.display = 'block';
|
|
2721
|
-
}
|
|
2722
|
-
me.VIDEO_DATA[index].framesDecodedCount = 0;
|
|
2723
|
-
me.VIDEO_DATA[index].framesDecodedLast = res.framesDecoded;
|
|
2724
|
-
} else {
|
|
2725
|
-
me.VIDEO_DATA[index].framesDecodedLast = res.framesDecoded;
|
|
2726
|
-
}
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
|
|
2731
|
-
});
|
|
2732
|
-
});
|
|
2733
|
-
}
|
|
2734
|
-
},
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
/**
|
|
2738
|
-
* 设备可用性检查(扬声器、麦克风、分辨率、浏览器类型)
|
|
2739
|
-
* 1. 未检测(status == undefined)询问进入检测界面
|
|
2740
|
-
* 2. 检测完成按相应结果给予相应提示
|
|
2741
|
-
* 3. 拒绝检测按所有检测通过处理
|
|
2742
|
-
* 4. 程序自行检测,并将是否加载声卡结果放入window对象
|
|
2743
|
-
* @private
|
|
2744
|
-
*/
|
|
2745
|
-
_checkDevices: function() {
|
|
2746
|
-
let me = this;
|
|
2747
|
-
let tipCountKey = "DEVICES_CHECK_TIP_COUNT";
|
|
2748
|
-
let statusKey = "DEVICES_CHECK_STATUS";
|
|
2749
|
-
let checkCompleted = "completed";
|
|
2750
|
-
let checkRejected = "rejected";
|
|
2751
|
-
let microResultKey = "MICRO_RESULT";
|
|
2752
|
-
let speakerResultKey = "SPEAKER_RESULT";
|
|
2753
|
-
let screenResultKey = "SCREEN_RESULT";
|
|
2754
|
-
let resultPass = "pass";
|
|
2755
|
-
let resultNotPass = "not pass";
|
|
2756
|
-
|
|
2757
|
-
let tipCount = sessionStorage.getItem(tipCountKey);
|
|
2758
|
-
let status = localStorage.getItem(statusKey);
|
|
2759
|
-
if ((tipCount == undefined || tipCount == "0") && status == undefined) {
|
|
2760
|
-
sessionStorage.setItem(tipCountKey, "1");
|
|
2761
|
-
//弹窗讯问是否进入检测界面
|
|
2762
|
-
if (confirm("您还没有检测硬件设备,是否先进行检测?")) {
|
|
2763
|
-
window.open("/scooper-video/new/checkDevices");
|
|
2764
|
-
} else {
|
|
2765
|
-
localStorage.setItem(statusKey, checkRejected);
|
|
2766
|
-
}
|
|
2767
|
-
return;
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
if (status == checkCompleted) {
|
|
2771
|
-
let microResult = (localStorage.getItem(microResultKey) == undefined) ? resultPass : localStorage.getItem(microResultKey);
|
|
2772
|
-
let speakerResult = (localStorage.getItem(speakerResultKey) == undefined) ? resultPass : localStorage.getItem(speakerResultKey);
|
|
2773
|
-
let screenResult = (localStorage.getItem(screenResultKey) == undefined) ? resultPass : localStorage.getItem(screenResultKey);
|
|
2774
|
-
|
|
2775
|
-
let msg = "";
|
|
2776
|
-
if(speakerResult == resultNotPass){
|
|
2777
|
-
msg += "检测到扬声器异常,可能影响系统某些功能的使用!";
|
|
2778
|
-
console.error(msg);
|
|
2779
|
-
}
|
|
2780
|
-
if (microResult == resultNotPass) {
|
|
2781
|
-
msg += "检测到麦克风异常,可能影响系统某些功能的使用!";
|
|
2782
|
-
console.error(msg);
|
|
2783
|
-
}
|
|
2784
|
-
if (screenResult === resultNotPass) {
|
|
2785
|
-
msg += "您的屏幕分辨率过低,可能导致页面布局混乱!";
|
|
2786
|
-
//提示消息
|
|
2787
|
-
promptAlarm(msg);
|
|
2788
|
-
}
|
|
2789
|
-
let userAgent = navigator.userAgent;
|
|
2790
|
-
if (userAgent.toLowerCase().indexOf("chrome") < 0 && userAgent.toLowerCase().indexOf("firefox") < 0 && userAgent.toLowerCase().indexOf("edge") < 0) {
|
|
2791
|
-
msg += "当前浏览器下部分功能可能存在兼容问题,建议使用谷歌浏览器!";
|
|
2792
|
-
promptAlarm(msg);
|
|
2793
|
-
}
|
|
2794
|
-
|
|
2795
|
-
if (msg != "") {
|
|
2796
|
-
//提示并派发消息
|
|
2797
|
-
// promptAlarm(msg);
|
|
2798
|
-
//防止外部未监听消息就派发事件
|
|
2799
|
-
setTimeout(function () {
|
|
2800
|
-
me.videoListener.dispatch('msginfo', {'msg' : msg});
|
|
2801
|
-
}, 3000);
|
|
2802
|
-
}
|
|
2803
|
-
}
|
|
2804
|
-
|
|
2805
|
-
},
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
/**
|
|
2809
|
-
* 视频界面的初始化,在传过来的dom中创建界面
|
|
2810
|
-
*/
|
|
2811
|
-
_initVideoView: function($dom, infoPosition) {
|
|
2812
|
-
let me = this;
|
|
2813
|
-
let position;
|
|
2814
|
-
switch (infoPosition) {
|
|
2815
|
-
case 1: position = "info-bottom"; break;
|
|
2816
|
-
case 2: position = "info-top"; break;
|
|
2817
|
-
default : position = "info-bottom";
|
|
2818
|
-
}
|
|
2819
|
-
let objClass = (me._opts.windowsNum == 1 ? 'video-main video-main-full mode-' : 'video-main mode-') + me._opts.windows;
|
|
2820
|
-
let videoHtml = '<ul class="' + objClass +'" id="video-main-web-rtc" video-flag="'+me._opts.windowsBeginIndex+'">';
|
|
2821
|
-
let index = me._opts.windowsBeginIndex + 1;
|
|
2822
|
-
for (let i = index; i < index + me._opts.windowsNum; i++) {
|
|
2823
|
-
videoHtml += '<li class="screen screen-' + i +'" index="' + (i - 1) +'" draggable="true"><video muted class="video-box" id="video-' + i +'" autoplay ></video>' +
|
|
2824
|
-
'<div class="hide info ' + position + '" id="info-' + i +'"></div><div class="hide info-self info-top" id="info-self-' + i +'"></div>' +
|
|
2825
|
-
'<div class="hide frame-decoded" id="frame-decoded-' + i + '"style="position:absolute;float:left;color:#fff;width:67%;z-index:1;top:135px;left:180px">网络信号不佳</div>' +
|
|
2826
|
-
'<div class="operate-btn">';
|
|
2827
|
-
//videoHtml +='<button type="button" class="unlock-video-btn hide" name="lockVideo"></button>';
|
|
2828
|
-
// checkUserMediaAvailable() &&
|
|
2829
|
-
videoHtml += '<button type="button" class="scale-btn bggray hide" name="scaleVideo" title="视频画面铺满"></button><button type="button" class="rotate-btn hide" name="rotateVideo" rotate-index="0" title="视频旋转"></button><button type="button" class="unsend-audio-btn hide" name="sendAudio"></button>';
|
|
2830
|
-
videoHtml += '<button type="button" class="unrecv-audio-btn hide" name="recvAudio"></button>' +
|
|
2831
|
-
'<button type="button" class="close-btn hide" name="closeVideo"></button>' +
|
|
2832
|
-
'</div>' +
|
|
2833
|
-
'</li>';
|
|
2834
|
-
}
|
|
2835
|
-
videoHtml += '</ul> <div class="canvasBox hide"><canvas id="myCanvas" ></canvas></div>';
|
|
2836
|
-
$dom.append(videoHtml);
|
|
2837
|
-
|
|
2838
|
-
me.setWindowsNum(me._opts.windows);
|
|
2839
|
-
},
|
|
2840
|
-
|
|
2841
|
-
/**
|
|
2842
|
-
* 音频界面的初始化,在传过来的dom中创建界面
|
|
2843
|
-
*/
|
|
2844
|
-
_initAudioView: function($dom) {
|
|
2845
|
-
let me = this;
|
|
2846
|
-
let objClass = (me._opts.windowsNum == 1 ? 'video-main video-main-full mode-' : 'video-main mode-') + me._opts.windows;
|
|
2847
|
-
let videoHtml = '<ul class="' + objClass +'" id="video-main-web-rtc" video-flag="'+me._opts.windowsBeginIndex+'">';
|
|
2848
|
-
let index = me._opts.windowsBeginIndex + 1;
|
|
2849
|
-
for (let i = index; i < index + me._opts.windowsNum; i++) {
|
|
2850
|
-
videoHtml += '<audio id="audio-' + i +'" autoplay ></video>';
|
|
2851
|
-
}
|
|
2852
|
-
$dom.append(videoHtml);
|
|
2853
|
-
},
|
|
2854
|
-
|
|
2855
|
-
/**
|
|
2856
|
-
* Janus的初始化
|
|
2857
|
-
*/
|
|
2858
|
-
_initJanus: function(){
|
|
2859
|
-
let me = this;
|
|
2860
|
-
|
|
2861
|
-
// if (window.parent && window.parent.janus) {
|
|
2862
|
-
// me._initSVideo(window.parent.janus);
|
|
2863
|
-
// return;
|
|
2864
|
-
// }
|
|
2865
|
-
|
|
2866
|
-
Janus.init({
|
|
2867
|
-
debug:"error",
|
|
2868
|
-
dependencies: Janus.useDefaultDependencies({
|
|
2869
|
-
adapter: adapter
|
|
2870
|
-
}),
|
|
2871
|
-
callback: function(){
|
|
2872
|
-
if(!Janus.isWebrtcSupported()) {
|
|
2873
|
-
alert("不支持WEB-RTC");
|
|
2874
|
-
return;
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
let janusUrl = me._opts.conf.janusUrl;
|
|
2878
|
-
checkIsHttps() && (janusUrl = janusUrl.replace('ws:','wss:'));
|
|
2879
|
-
me._opts.janus = new Janus({
|
|
2880
|
-
// server: janusUrl.indexOf("127.0.0.1") == -1 ? janusUrl : janusUrl.split("//")[0] + "//" + (location.hostname)+":"+janusUrl.split(":")[2],
|
|
2881
|
-
//使用项目必须定义window.janusHttpsHost来适应https
|
|
2882
|
-
server: location.protocol == "https:" ? janusUrl.split("//")[0] + "//" + "szh.rfb.zj.gov.cn/tytxstream" + "/janus/" : janusUrl,
|
|
2883
|
-
// server: 'ws://112.124.244.179:8188/janus/',
|
|
2884
|
-
success: function(){
|
|
2885
|
-
console.log("Janus服务连接成功!");
|
|
2886
|
-
me._initSVideo(me._opts.janus);
|
|
2887
|
-
},
|
|
2888
|
-
error: function(error) {
|
|
2889
|
-
//只提示一次,防止Janus挂了一直重连
|
|
2890
|
-
!me._opts.isNotFistTip && promptFailed('Janus服务连接失败!');
|
|
2891
|
-
me._opts.isNotFistTip = true;
|
|
2892
|
-
|
|
2893
|
-
console.error('Janus服务连接失败:'+ error)
|
|
2894
|
-
me.closeAll();
|
|
2895
|
-
me._removeAllWaitingVideo();
|
|
2896
|
-
me._initJanus();
|
|
2897
|
-
},
|
|
2898
|
-
destroyed: function() {
|
|
2899
|
-
me._opts.isNotFistTip = true;
|
|
2900
|
-
}
|
|
2901
|
-
});
|
|
2902
|
-
|
|
2903
|
-
}
|
|
2904
|
-
});
|
|
2905
|
-
},
|
|
2906
|
-
/**
|
|
2907
|
-
* 销毁所有
|
|
2908
|
-
*/
|
|
2909
|
-
destory: function() {
|
|
2910
|
-
var me = this;
|
|
2911
|
-
me.destoryJanus();
|
|
2912
|
-
$(me.selector).empty();
|
|
2913
|
-
me.videoListener = null;
|
|
2914
|
-
me.VIDEO_DATA = null;
|
|
2915
|
-
me.selector = null;
|
|
2916
|
-
//destoryJanus会触发回调,需要使用到opts
|
|
2917
|
-
// me._opts = null;
|
|
2918
|
-
},
|
|
2919
|
-
|
|
2920
|
-
/**
|
|
2921
|
-
* 销毁:Janus销毁、资源释放
|
|
2922
|
-
*/
|
|
2923
|
-
destoryJanus: function() {
|
|
2924
|
-
let me = this;
|
|
2925
|
-
me._opts.janus.destroy({
|
|
2926
|
-
success: function() {
|
|
2927
|
-
// window.windowsSum = 0;
|
|
2928
|
-
//userToken = null;
|
|
2929
|
-
registered = false;
|
|
2930
|
-
},
|
|
2931
|
-
asyncRequest: true,
|
|
2932
|
-
notifyDestroyed: true,
|
|
2933
|
-
|
|
2934
|
-
});
|
|
2935
|
-
me.removeAllListeners();
|
|
2936
|
-
},
|
|
2937
|
-
|
|
2938
|
-
reLoginJanusItvIndex : -1,
|
|
2939
|
-
|
|
2940
|
-
/**
|
|
2941
|
-
* 初始化插件、登陆,初始化窗口
|
|
2942
|
-
*/
|
|
2943
|
-
_initSVideo: function(janus){
|
|
2944
|
-
let me = this;
|
|
2945
|
-
|
|
2946
|
-
//已经初始化过,则直接拿来用
|
|
2947
|
-
// if (janus && (registered || (window.parent && window.parent.registered))) {
|
|
2948
|
-
// //生成主界面
|
|
2949
|
-
// for(let i = me._opts.windowsBeginIndex; i < me._opts.windowsBeginIndex + me._opts.windowsNum; i++){
|
|
2950
|
-
// me.VIDEO_DATA[i] = new SVideo({
|
|
2951
|
-
// index:i,
|
|
2952
|
-
// janus:janus
|
|
2953
|
-
//
|
|
2954
|
-
// });
|
|
2955
|
-
// }
|
|
2956
|
-
// return;
|
|
2957
|
-
// }
|
|
2958
|
-
|
|
2959
|
-
//初始化一个插件,用来登陆,不能用此插件播放视频。
|
|
2960
|
-
let _loginSipCall = null;
|
|
2961
|
-
janus.attach({
|
|
2962
|
-
plugin: me._opts.conf.janusPlugin ? me._opts.conf.janusPlugin : "janus.plugin.videoserver",
|
|
2963
|
-
opaqueId: "siptest-" + Janus.randomString(12),
|
|
2964
|
-
success: function(pluginHandle) {
|
|
2965
|
-
console.log("Janus登陆插件初始化成功!");
|
|
2966
|
-
_loginSipCall = pluginHandle;
|
|
2967
|
-
let register = {
|
|
2968
|
-
"request" : "register",
|
|
2969
|
-
"username" : me._opts.conf.user,
|
|
2970
|
-
"secret": me._opts.conf.passwd,
|
|
2971
|
-
};
|
|
2972
|
-
_loginSipCall.send({"message": register});
|
|
2973
|
-
},
|
|
2974
|
-
error: function(error) {
|
|
2975
|
-
promptFailed('Janus登陆插件初始化失败!');
|
|
2976
|
-
console.error("Janus登陆插件初始化失败:" + error);
|
|
2977
|
-
},
|
|
2978
|
-
onmessage: function(msg, jsep) {
|
|
2979
|
-
if (msg.error_code) {
|
|
2980
|
-
console.error(msg.error)
|
|
2981
|
-
promptFailed(FAILED_CODE[msg.error_code] || '错误码:' + msg.error_code);
|
|
2982
|
-
return false;
|
|
2983
|
-
}
|
|
2984
|
-
|
|
2985
|
-
let result = msg["result"];
|
|
2986
|
-
let event = result["event"];
|
|
2987
|
-
|
|
2988
|
-
if (result.error_code && result.error_code != 0) {
|
|
2989
|
-
promptFailed(FAILED_CODE[result.error_code] || '错误码:' + result.error_code);
|
|
2990
|
-
}
|
|
2991
|
-
|
|
2992
|
-
if(result !== null && result !== undefined && result["event"] !== undefined && result["event"] !== null) {
|
|
2993
|
-
console.log("result event:" + event);
|
|
2994
|
-
if(event === 'registration_failed') {
|
|
2995
|
-
promptFailed("janus登陆失败: " + result["code"] + " " + result["reason"]);
|
|
2996
|
-
if(me.reLoginJanusItvIndex == -1) {
|
|
2997
|
-
me.reLoginJanusItvIndex = setInterval(function () {
|
|
2998
|
-
console.log("尝试重新登陆janus!");
|
|
2999
|
-
me._initJanus(janus);
|
|
3000
|
-
}, 5000);
|
|
3001
|
-
}
|
|
3002
|
-
return;
|
|
3003
|
-
}
|
|
3004
|
-
if (event === 'video_server_closed') {
|
|
3005
|
-
if(me.reLoginJanusItvIndex == -1) {
|
|
3006
|
-
me.reLoginJanusItvIndex = setInterval(function () {
|
|
3007
|
-
console.log("尝试重新登陆janus!");
|
|
3008
|
-
me._initJanus(janus);
|
|
3009
|
-
}, 5000);
|
|
3010
|
-
}
|
|
3011
|
-
return;
|
|
3012
|
-
}
|
|
3013
|
-
if(event === 'registered') {
|
|
3014
|
-
let userToken = result["userToken"];
|
|
3015
|
-
console.log('janus登陆成功')
|
|
3016
|
-
registered = true;
|
|
3017
|
-
if (me.reLoginJanusItvIndex != -1) {
|
|
3018
|
-
clearInterval(me.reLoginJanusItvIndex);
|
|
3019
|
-
me.reLoginJanusItvIndex = -1;
|
|
3020
|
-
}
|
|
3021
|
-
|
|
3022
|
-
//生成主界面
|
|
3023
|
-
//相对序号,用于标识当前janus连接初始化的序号窗口
|
|
3024
|
-
let relativeIndex = 0;
|
|
3025
|
-
for(let i = me._opts.windowsBeginIndex; i < me._opts.windowsBeginIndex + me._opts.windowsNum; i++){
|
|
3026
|
-
me.VIDEO_DATA[i] = new SVideo({
|
|
3027
|
-
index: i,
|
|
3028
|
-
janus: janus,
|
|
3029
|
-
userToken: userToken,
|
|
3030
|
-
windowsNum: me._opts.windowsNum,
|
|
3031
|
-
relativeIndex: relativeIndex++,
|
|
3032
|
-
flag: me._opts.flag,
|
|
3033
|
-
isVideoTag: me._opts.isVideoTag,
|
|
3034
|
-
janusPlugin: me._opts.conf.janusPlugin,
|
|
3035
|
-
videoTipTimeOut: me._opts.videoTipTimeOut,
|
|
3036
|
-
parentSelector: me.selector
|
|
3037
|
-
}, me.videoListener);
|
|
3038
|
-
}
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
});
|
|
3043
|
-
},
|
|
3044
|
-
/* ----------------------------- 播放队列 --------------------------- */
|
|
3045
|
-
|
|
3046
|
-
// 记录等待中的视频
|
|
3047
|
-
WAITING_DATA: [],
|
|
3048
|
-
|
|
3049
|
-
// 播放队列开关 默认关闭
|
|
3050
|
-
waitPlayQueueSwitch: false,
|
|
3051
|
-
|
|
3052
|
-
/**
|
|
3053
|
-
* 添加等待视频数据
|
|
3054
|
-
* 同一位置再次打开,则覆盖上一次的
|
|
3055
|
-
* 参数:index(视频窗口编号,从0开始) video(视频设备id,即devId) id(标识,空的话使用设备id) opts(其他参数)
|
|
3056
|
-
*/
|
|
3057
|
-
_addWaitingVideo: function (index, video, id, opts) {
|
|
3058
|
-
let _self = this;
|
|
3059
|
-
let isOverride = false;
|
|
3060
|
-
$.each(_self.WAITING_DATA, function (i, obj) {
|
|
3061
|
-
if (obj.index == index) {
|
|
3062
|
-
console.log("播放队列中 index = " + index + ", video = " + obj.video + " 替换为 video = " + video);
|
|
3063
|
-
_self.WAITING_DATA[i] = {
|
|
3064
|
-
index: index,
|
|
3065
|
-
video: video,
|
|
3066
|
-
id: id,
|
|
3067
|
-
opts: opts
|
|
3068
|
-
}
|
|
3069
|
-
isOverride = true;
|
|
3070
|
-
return false;
|
|
3071
|
-
}
|
|
3072
|
-
});
|
|
3073
|
-
if (!isOverride) {
|
|
3074
|
-
_self.WAITING_DATA.push({
|
|
3075
|
-
index: index,
|
|
3076
|
-
video: video,
|
|
3077
|
-
id: id,
|
|
3078
|
-
opts: opts
|
|
3079
|
-
});
|
|
3080
|
-
console.log("index = " + index + ", video = " + video + " 加入播放队列");
|
|
3081
|
-
}
|
|
3082
|
-
_self.VIDEO_DATA[index].isWaiting = true;
|
|
3083
|
-
},
|
|
3084
|
-
|
|
3085
|
-
/**
|
|
3086
|
-
* 删除等待视频数据
|
|
3087
|
-
*/
|
|
3088
|
-
_removeWaitingVideo: function (index, video) {
|
|
3089
|
-
let _self = this;
|
|
3090
|
-
$.each(_self.WAITING_DATA, function (i, obj) {
|
|
3091
|
-
if (obj.index == index && obj.video == video) {
|
|
3092
|
-
_self.WAITING_DATA.splice(i, 1);
|
|
3093
|
-
_self.VIDEO_DATA[index].isWaiting = false;
|
|
3094
|
-
console.log("index = " + index + ", video = " + video + " 从播放队列移除");
|
|
3095
|
-
return false;
|
|
3096
|
-
}
|
|
3097
|
-
});
|
|
3098
|
-
},
|
|
3099
|
-
|
|
3100
|
-
/**
|
|
3101
|
-
* 删除所有等待播放视频的数据
|
|
3102
|
-
*/
|
|
3103
|
-
_removeAllWaitingVideo: function () {
|
|
3104
|
-
let _self = this;
|
|
3105
|
-
_self.WAITING_DATA = [];
|
|
3106
|
-
let index = _self._opts.windowsBeginIndex;
|
|
3107
|
-
for (; index < _self._opts.windowsBeginIndex + _self._opts.windows ; index++) {
|
|
3108
|
-
_self.VIDEO_DATA[index].isWaiting = false;
|
|
3109
|
-
}
|
|
3110
|
-
},
|
|
3111
|
-
|
|
3112
|
-
/**
|
|
3113
|
-
* 上一个视频关闭后,如果该位置由等待视频,通知打开新视频
|
|
3114
|
-
* @param index
|
|
3115
|
-
*/
|
|
3116
|
-
_notifyWaitingVideo: function (index) {
|
|
3117
|
-
let _self = this;
|
|
3118
|
-
$.each(_self.WAITING_DATA, function (i, obj) {
|
|
3119
|
-
if (obj.index == index) {
|
|
3120
|
-
_self.play(obj.index, obj.video, obj.id, obj.opts);
|
|
3121
|
-
_self._removeWaitingVideo(obj.index, obj.video);
|
|
3122
|
-
return false;
|
|
3123
|
-
}
|
|
3124
|
-
});
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
|
-
}
|
|
3128
|
-
|
|
3129
|
-
let CONST_CODE = {
|
|
3130
|
-
//打开失败错误码,面板显示,不做浮窗提示框显示
|
|
3131
|
-
VIDEO_CODE: {
|
|
3132
|
-
2002 : "打开失败,未找到该ID的视频源",
|
|
3133
|
-
2003 : "打开失败,请确认视频服务版本",
|
|
3134
|
-
3001 : "打开失败,未接收到引流包,请检查端口映射",
|
|
3135
|
-
3002 : "",
|
|
3136
|
-
3003 : "打开失败,对方拒绝视频请求",
|
|
3137
|
-
4001 : "打开失败,视频流中断",
|
|
3138
|
-
4002 : "打开失败,终端挂机或超时未接听",
|
|
3139
|
-
7000 : "打开失败,无法连接视频设备",
|
|
3140
|
-
7001 : "打开失败,无法连接视频设备",
|
|
3141
|
-
7002 : "打开失败,无法连接视频设备"
|
|
3142
|
-
},
|
|
3143
|
-
|
|
3144
|
-
OTHER_CODE: {
|
|
3145
|
-
453 : "videoServer连接失败,错误码453",
|
|
3146
|
-
454 : "视频窗口已被占用,请选择其它窗口打开或停止播放",
|
|
3147
|
-
455 : "操作失败,该段时间无视频录像",
|
|
3148
|
-
499 : "操作异常,错误码499",
|
|
3149
|
-
440 : "操作异常,错误码440",
|
|
3150
|
-
441 : "操作异常,错误码441",
|
|
3151
|
-
442 : "操作异常,错误码442",
|
|
3152
|
-
443 : "操作异常,错误码443",
|
|
3153
|
-
444 : "操作异常,错误码444",
|
|
3154
|
-
445 : "操作异常,错误码445",
|
|
3155
|
-
446 : "操作异常,错误码446",
|
|
3156
|
-
447 : "操作异常,错误码447",
|
|
3157
|
-
448 : "操作异常,错误码448",
|
|
3158
|
-
449 : "操作异常,错误码449",
|
|
3159
|
-
450 : "操作异常,错误码450",
|
|
3160
|
-
451 : "操作异常,错误码451",
|
|
3161
|
-
452 : "操作异常,错误码452",
|
|
3162
|
-
456 : "设备已处于对讲状态或不支持对讲",
|
|
3163
|
-
6001 : "录像失败"
|
|
3164
|
-
},
|
|
3165
|
-
FAILED_CODE: {
|
|
3166
|
-
1001 : "账号或密码错误",
|
|
3167
|
-
1002 : "该帐号已连接",
|
|
3168
|
-
1004 : "没有鉴权",
|
|
3169
|
-
2001 : "未携带token或token错误",
|
|
3170
|
-
2002 : "视频源id不存在",
|
|
3171
|
-
2003 : "操作指令非法(该账号不允许执行这个指令,或者不支持该指令)",
|
|
3172
|
-
3001 : "nat通道未建立",
|
|
3173
|
-
3002 : "该视频流已在传输",
|
|
3174
|
-
3003 : "无法获取远端视频流",
|
|
3175
|
-
4001 : "视频流异常断开连接",
|
|
3176
|
-
4002 : "获取视频失败",
|
|
3177
|
-
5000 : "内部错误",
|
|
3178
|
-
8001 : "该设备不支持云台操作",
|
|
3179
|
-
453 : "videoServer连接失败",
|
|
3180
|
-
454 : "录像回放窗口已占用,请先停止播放",
|
|
3181
|
-
455 : "无视频录像,操作失败",
|
|
3182
|
-
5001 : "呼叫异常断开",
|
|
3183
|
-
5002 : "禁止修改分辨率",
|
|
3184
|
-
401 : "禁止修改分辨率",
|
|
3185
|
-
4003 : "音频重置",
|
|
3186
|
-
4004 : "音频被占用",
|
|
3187
|
-
4005 : "客户端已打开对讲",
|
|
3188
|
-
4006 : "终端离开云眼音频",
|
|
3189
|
-
4008 : "终端拒绝打开视频",
|
|
3190
|
-
6001 : "录像失败",
|
|
3191
|
-
499 : "内部创建失败",
|
|
3192
|
-
440 : "请求消息内容为空",
|
|
3193
|
-
441 : "json格式错误",
|
|
3194
|
-
442 : "无效的请求",
|
|
3195
|
-
443 : "消息内容缺失",
|
|
3196
|
-
444 : "消息缺少参数",
|
|
3197
|
-
445 : "账户已登陆",
|
|
3198
|
-
446 : "收到的videoserver消息有误",
|
|
3199
|
-
447 : "消息参数错误",
|
|
3200
|
-
448 : "SDP创建失败",
|
|
3201
|
-
449 : "未使用",
|
|
3202
|
-
450 : "创建端口失败",
|
|
3203
|
-
451 : "SDP创建失败",
|
|
3204
|
-
452 : "未使用加密的RTP",
|
|
3205
|
-
456 : "对讲未打开",
|
|
3206
|
-
7000 : "URL账号密码错误(RTSP)",
|
|
3207
|
-
7001 : "URL地址不通(RTSP)",
|
|
3208
|
-
7002 : "URL格式错误(RTSP)"
|
|
3209
|
-
},
|
|
3210
|
-
|
|
3211
|
-
STATUS_CODE_ARR: ['5002', '4003', '4004', '4005', '4006']
|
|
3212
|
-
}
|
|
3213
|
-
/**
|
|
3214
|
-
* 显示播放错误内容, 4002特殊处理
|
|
3215
|
-
* @param videoObj 视频对象
|
|
3216
|
-
* @param code 状态码(包含错误码)
|
|
3217
|
-
* @param isShowReplayBtn 是否显示重新播放按钮
|
|
3218
|
-
* @param video 打开错误的视频Id
|
|
3219
|
-
*/
|
|
3220
|
-
function showResult(videoObj, code, isShowReplayBtn, video) {
|
|
3221
|
-
let videoDom = videoObj.tagBox.parent();
|
|
3222
|
-
|
|
3223
|
-
videoDom.addClass("result");
|
|
3224
|
-
videoDom.find('.operate-btn .close-btn').show();
|
|
3225
|
-
|
|
3226
|
-
if (CONST_CODE.FAILED_CODE[code] && code != "4002") {
|
|
3227
|
-
let resultHtml = "<div class='real-result'>错误码" + code + ": " + CONST_CODE.FAILED_CODE[code] + "</div>"
|
|
3228
|
-
videoDom.append(resultHtml);
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
let resultHtml = "<div class='result'><div class='result-tip'>" + CONST_CODE.VIDEO_CODE[code] + "</div>";
|
|
3232
|
-
if(isShowReplayBtn && code != "4002") {
|
|
3233
|
-
resultHtml += "<div class='result-replay'><span id='replay-" + videoObj.index + "' class='replay'>点击重试</span></div>"
|
|
3234
|
-
}
|
|
3235
|
-
resultHtml += "</div>";
|
|
3236
|
-
videoDom.append(resultHtml);
|
|
3237
|
-
if(isShowReplayBtn && code != "4002") {
|
|
3238
|
-
$("#replay-" + videoObj.index).unbind("click").click(function () {
|
|
3239
|
-
videoObj.videoListener.dispatch("openVideo", {index: videoObj.index, video: video, id: videoObj.id, opts: videoObj.opts});
|
|
3240
|
-
});
|
|
3241
|
-
}
|
|
3242
|
-
if (code == "4002") {
|
|
3243
|
-
setTimeout(function () {
|
|
3244
|
-
clearResult(videoDom);
|
|
3245
|
-
}, 5000);
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
|
|
3249
|
-
/**
|
|
3250
|
-
* 清除显示内容 videoDom: 视频Dom对象
|
|
3251
|
-
*/
|
|
3252
|
-
function clearResult(videoDom, videoObj) {
|
|
3253
|
-
videoDom.removeClass("result");
|
|
3254
|
-
videoDom.find(".real-result").remove();
|
|
3255
|
-
videoDom.find(".result").remove();
|
|
3256
|
-
if (!videoObj || !videoObj.playing) {
|
|
3257
|
-
// bug id 18654: 增加是否正在播放判断
|
|
3258
|
-
videoDom.find('.operate-btn .close-btn').hide();
|
|
3259
|
-
}
|
|
3260
|
-
}
|
|
3261
|
-
|
|
3262
|
-
//window.VIDEO_DATA = [];//记录视频各分屏的状态
|
|
3263
|
-
window.windowsSum = 0; //当前页面的视频总数,可能有多个VideoWebRtc对象
|
|
3264
|
-
//let userToken = null;
|
|
3265
|
-
let registered = false;
|
|
3266
|
-
let recordAvBusinessId = null;
|
|
3267
|
-
|
|
3268
|
-
function SVideo (opts, videoListener) {
|
|
3269
|
-
this.janus = opts.janus;
|
|
3270
|
-
this.userToken = opts.userToken;
|
|
3271
|
-
this.sipcall = null;
|
|
3272
|
-
this.index = opts.index;
|
|
3273
|
-
this.relativeIndex = opts.relativeIndex;
|
|
3274
|
-
// this.tagBox = opts.isVideoTag ? $('#video-' + (this.index + 1)) : $('#audio-' + (this.index + 1));
|
|
3275
|
-
this.tagBox = opts.isVideoTag ? $(opts.parentSelector + ' #video-' + (this.index + 1)) : $('#audio-' + (this.index + 1));
|
|
3276
|
-
this.windowsNum = opts.windowsNum;
|
|
3277
|
-
this.flag = opts.flag;
|
|
3278
|
-
this.isVideoTag = opts.isVideoTag;
|
|
3279
|
-
this.janusPlugin = opts.janusPlugin;
|
|
3280
|
-
this.isClosing = false; // 当前分屏是否正在关闭视频
|
|
3281
|
-
this.isWaiting = false; // 当前分屏是否有视频在等待播放
|
|
3282
|
-
this.playSucTimeOutIndex = -1; // 超时提示定时器index
|
|
3283
|
-
this.videoTipTimeOut = opts.videoTipTimeOut; // 超时无首屏时间
|
|
3284
|
-
this.videoListener = videoListener;
|
|
3285
|
-
this.init();
|
|
3286
|
-
}
|
|
3287
|
-
|
|
3288
|
-
/**
|
|
3289
|
-
* 使用web-rtc方式的视频播放
|
|
3290
|
-
*/
|
|
3291
|
-
SVideo.prototype = {
|
|
3292
|
-
|
|
3293
|
-
/**
|
|
3294
|
-
* 初始化
|
|
3295
|
-
*/
|
|
3296
|
-
init:function(){
|
|
3297
|
-
let self = this;
|
|
3298
|
-
|
|
3299
|
-
self.janus.attach({
|
|
3300
|
-
plugin: self.janusPlugin ? self.janusPlugin : "janus.plugin.videoserver",
|
|
3301
|
-
opaqueId:"siptest-" + Janus.randomString(12),
|
|
3302
|
-
|
|
3303
|
-
success: function(pluginHandle) {
|
|
3304
|
-
console.log("视频插件初始化成功:" + self.index);
|
|
3305
|
-
self.sipcall = pluginHandle;
|
|
3306
|
-
|
|
3307
|
-
if (self.relativeIndex + 1 >= self.windowsNum) {
|
|
3308
|
-
self.videoListener.dispatch('initsucc', self);
|
|
3309
|
-
}
|
|
3310
|
-
},
|
|
3311
|
-
|
|
3312
|
-
error: function(error) {
|
|
3313
|
-
console.error("插件初始化失败");
|
|
3314
|
-
},
|
|
3315
|
-
|
|
3316
|
-
consentDialog: function(on) {
|
|
3317
|
-
console.log("Consent dialog should be " + (on ? "on" : "off") + " now");
|
|
3318
|
-
},
|
|
3319
|
-
|
|
3320
|
-
onmessage: function(msg, jsep) {
|
|
3321
|
-
if(!registered) {
|
|
3322
|
-
promptFailed("请先登陆");
|
|
3323
|
-
}
|
|
3324
|
-
|
|
3325
|
-
let video = self.video;
|
|
3326
|
-
if (msg.error_code) {
|
|
3327
|
-
console.error("错误码:" + msg.error_code + " " + CONST_CODE.FAILED_CODE[msg.error_code]);
|
|
3328
|
-
if (CONST_CODE.VIDEO_CODE[msg.error_code]) {
|
|
3329
|
-
showResult(self, msg.error_code, true, video);
|
|
3330
|
-
} else {
|
|
3331
|
-
promptFailed(CONST_CODE.OTHER_CODE[msg.error_code] || CONST_CODE.FAILED_CODE[msg.error_code] || '错误码:' + msg.error_code);
|
|
3332
|
-
}
|
|
3333
|
-
self.videoListener.dispatch('msginfo', {'code': msg.error_code, 'msg' : CONST_CODE.OTHER_CODE[msg.error_code] || CONST_CODE.FAILED_CODE[msg.error_code] || '错误码:' + msg.error_code});
|
|
3334
|
-
return false;
|
|
3335
|
-
}
|
|
3336
|
-
|
|
3337
|
-
let result = msg["result"];
|
|
3338
|
-
if (!result) return;
|
|
3339
|
-
if (result.error_code && result.error_code != 0) {
|
|
3340
|
-
//videoListener.dispatch('afterclose', self);
|
|
3341
|
-
|
|
3342
|
-
if (!CONST_CODE.STATUS_CODE_ARR.includes(result.error_code + '')) {
|
|
3343
|
-
//videoListener.dispatch('afterclose', self);
|
|
3344
|
-
//播放失败 关闭视频
|
|
3345
|
-
|
|
3346
|
-
self.close('err');
|
|
3347
|
-
|
|
3348
|
-
if (self.isLockVideo) {
|
|
3349
|
-
setTimeout(function () {
|
|
3350
|
-
self.play(video);
|
|
3351
|
-
}, 1500);
|
|
3352
|
-
} else {
|
|
3353
|
-
self.closeType = 'error';
|
|
3354
|
-
self.videoListener.dispatch('afterclose', self);
|
|
3355
|
-
}
|
|
3356
|
-
}
|
|
3357
|
-
|
|
3358
|
-
self.videoListener.dispatch('msginfo', {'code': result.error_code, 'msg' : CONST_CODE.OTHER_CODE[result.error_code] || CONST_CODE.FAILED_CODE[result.error_code] || '错误码:' + result.error_code});
|
|
3359
|
-
if (CONST_CODE.VIDEO_CODE[result.error_code]) {
|
|
3360
|
-
showResult(self, result.error_code, true, video);
|
|
3361
|
-
} else {
|
|
3362
|
-
promptFailed(CONST_CODE.OTHER_CODE[result.error_code] || CONST_CODE.FAILED_CODE[result.error_code] || '错误码:' + result.error_code);
|
|
3363
|
-
}
|
|
3364
|
-
|
|
3365
|
-
self.tagBox.parent().find('.recv-audio-btn').attr("class", "unrecv-audio-btn");
|
|
3366
|
-
self.tagBox.parent().find('.send-audio-btn').attr("class", "unsend-audio-btn");
|
|
3367
|
-
}
|
|
3368
|
-
|
|
3369
|
-
//事件响应
|
|
3370
|
-
let event = result["event"];
|
|
3371
|
-
if (!event) return;
|
|
3372
|
-
switch(event) {
|
|
3373
|
-
//即将播放视频
|
|
3374
|
-
case 'incomingcall':
|
|
3375
|
-
self.sipcall.createAnswer({
|
|
3376
|
-
jsep: jsep,
|
|
3377
|
-
media: { audioSend: checkUserMediaAvailable(), videoSend:false, audioRecv: true , videoRecv: true},
|
|
3378
|
-
success: function(jsep) {
|
|
3379
|
-
let body = {
|
|
3380
|
-
request:"accept",
|
|
3381
|
-
videoidentify: result["videoidentify"],
|
|
3382
|
-
playseq: parseInt(result["playseq"]),
|
|
3383
|
-
userToken: self.userToken,
|
|
3384
|
-
};
|
|
3385
|
-
self.sipcall.send({"message": body, "jsep": jsep});
|
|
3386
|
-
},
|
|
3387
|
-
error: function(error) {
|
|
3388
|
-
console.error(error);
|
|
3389
|
-
// let body = { "request": "decline", "code": 480 };
|
|
3390
|
-
// self.sipcall.send({"message": body});
|
|
3391
|
-
}
|
|
3392
|
-
});
|
|
3393
|
-
break;
|
|
3394
|
-
case 'accepted' :
|
|
3395
|
-
self.playSucTimeOutIndex = setTimeout(function () {
|
|
3396
|
-
let _li = self.tagBox.parent();
|
|
3397
|
-
_li.append('<div class="video-tip">网络环境较差,可能无法正常加载视频</div>');
|
|
3398
|
-
}, self.videoTipTimeOut * 1000);
|
|
3399
|
-
break;
|
|
3400
|
-
//呼叫失败
|
|
3401
|
-
case 'callfaild':
|
|
3402
|
-
//promptFailed(FAILED_CODE[result.error_code] || '错误码:' + result.error_code);
|
|
3403
|
-
break;
|
|
3404
|
-
//云台
|
|
3405
|
-
case 'ptz':
|
|
3406
|
-
break;
|
|
3407
|
-
//历史流控制
|
|
3408
|
-
case 'av_control':
|
|
3409
|
-
break;
|
|
3410
|
-
//录像通知
|
|
3411
|
-
case 'start_av_record':
|
|
3412
|
-
if (result && result.filename) {
|
|
3413
|
-
self.videoFileName = result.filename;
|
|
3414
|
-
self.videoListener.dispatch('startRecordVideo', self);
|
|
3415
|
-
console.log('录像地址:' + result.filename);
|
|
3416
|
-
}
|
|
3417
|
-
break;
|
|
3418
|
-
case 'stop_av_record':
|
|
3419
|
-
if (result && result.filename) {
|
|
3420
|
-
self.videoFileName = result.filename;
|
|
3421
|
-
self.videoListener.dispatch('stopRecordVideo', self);
|
|
3422
|
-
console.log('录像地址:' + result.filename);
|
|
3423
|
-
}
|
|
3424
|
-
break;
|
|
3425
|
-
//修改分辨率
|
|
3426
|
-
case 'ser_notify_resolution':
|
|
3427
|
-
if (result && result.resolution) {
|
|
3428
|
-
self.resolution = result.resolution;
|
|
3429
|
-
self.videoListener.dispatch('notifyresolution', self);
|
|
3430
|
-
console.log('接收notifyresolution:' + result.resolution);
|
|
3431
|
-
//promptAlarm('当前分辨率:' + result.resolution);
|
|
3432
|
-
}
|
|
3433
|
-
break;
|
|
3434
|
-
case 'change_resolution':
|
|
3435
|
-
if(result) {
|
|
3436
|
-
self.videoListener.dispatch('notifyResolutionChange', self);
|
|
3437
|
-
}
|
|
3438
|
-
break;
|
|
3439
|
-
//建立预呼叫响应
|
|
3440
|
-
case 'open_poccall':
|
|
3441
|
-
console.log('建立预呼叫');
|
|
3442
|
-
self.sipcall.createAnswer({
|
|
3443
|
-
jsep: jsep,
|
|
3444
|
-
media: {audioSend: checkUserMediaAvailable(), videoSend:false, audioRecv: true , videoRecv: false},
|
|
3445
|
-
success: function(jsep) {
|
|
3446
|
-
let body = {
|
|
3447
|
-
request:"accept",
|
|
3448
|
-
userToken: self.userToken,
|
|
3449
|
-
};
|
|
3450
|
-
self.sipcall.send({"message": body, "jsep": jsep});
|
|
3451
|
-
},
|
|
3452
|
-
error: function(error) {
|
|
3453
|
-
console.error(error);
|
|
3454
|
-
// let body = { "request": "decline", "code": 480 };
|
|
3455
|
-
// self.sipcall.send({"message": body});
|
|
3456
|
-
}
|
|
3457
|
-
});
|
|
3458
|
-
break
|
|
3459
|
-
//预呼叫异常断开
|
|
3460
|
-
case 'ser_close_poccall':
|
|
3461
|
-
console.log('预呼叫异常断开');
|
|
3462
|
-
break;
|
|
3463
|
-
case 'ser_stop_audio':
|
|
3464
|
-
self.tagBox.parent().find('.recv-audio-btn').attr("class", "unrecv-audio-btn");
|
|
3465
|
-
console.log('音频异常关闭!');
|
|
3466
|
-
break;
|
|
3467
|
-
case 'close_down_audio':
|
|
3468
|
-
self.tagBox.parent().find('.send-audio-btn').attr("class", "unsend-audio-btn");
|
|
3469
|
-
promptSuccess("通话时间到");
|
|
3470
|
-
console.log('通话时间到!');
|
|
3471
|
-
break;
|
|
3472
|
-
case 'ser_notify_dispatch_close_ptop_poc':
|
|
3473
|
-
self.tagBox.parent().find('.send-audio-btn').attr("class", "unsend-audio-btn");
|
|
3474
|
-
console.log('调度通知点对点对讲关闭!');
|
|
3475
|
-
break;
|
|
3476
|
-
case 'ser_close_ptop_poc':
|
|
3477
|
-
self.tagBox.parent().find('.send-audio-btn').attr("class", "unsend-audio-btn");
|
|
3478
|
-
console.log('点对点对讲关闭!');
|
|
3479
|
-
break;
|
|
3480
|
-
case 'ser_open_ptop_poc':
|
|
3481
|
-
self.tagBox.parent().find('.unsend-audio-btn').attr("class", "send-audio-btn");
|
|
3482
|
-
console.log('点对点对讲打开!');
|
|
3483
|
-
break;
|
|
3484
|
-
// 视频关闭通知
|
|
3485
|
-
case 'ser_close_video':
|
|
3486
|
-
console.log('视频框 ' + self.index + ' 视频已关闭');
|
|
3487
|
-
self.isClosing = false;
|
|
3488
|
-
self.videoListener.dispatch('notifyCloseVideo', self);
|
|
3489
|
-
break;
|
|
3490
|
-
default:
|
|
3491
|
-
console.log('event:' + event);
|
|
3492
|
-
break;
|
|
3493
|
-
}
|
|
3494
|
-
},
|
|
3495
|
-
|
|
3496
|
-
//处理远程流
|
|
3497
|
-
onremotestream: function(stream) {
|
|
3498
|
-
console.log('onremotestream:分屏=' + (self.index + 1) + ', video=' + self.video);
|
|
3499
|
-
Janus.attachMediaStream(self.tagBox.get(0), stream);
|
|
3500
|
-
},
|
|
3501
|
-
|
|
3502
|
-
//处理本地流
|
|
3503
|
-
onlocalstream: function(stream) {
|
|
3504
|
-
stream.getAudioTracks()[0].enabled = false;
|
|
3505
|
-
self.stream = stream;
|
|
3506
|
-
|
|
3507
|
-
// Janus.attachMediaStream(self.tagBox.get(0), stream);
|
|
3508
|
-
// let s = stream.getAudioTracks()[0];
|
|
3509
|
-
// stream.removeTrack(s);
|
|
3510
|
-
// self.sipcall.webrtcStuff.myStream.addTrack(s);
|
|
3511
|
-
// self.sipcall.webrtcStuff.myStream.removeTrack(s);
|
|
3512
|
-
// stream.getTracks().forEach(track => track.stop());
|
|
3513
|
-
|
|
3514
|
-
// if (self.isVideoTag) {
|
|
3515
|
-
// let btnObj = self.tagBox.parent().find("button[name='sendAudio']");
|
|
3516
|
-
// btnObj.unbind('click');
|
|
3517
|
-
// //stream.getAudioTracks()[0].enabled = false;
|
|
3518
|
-
//
|
|
3519
|
-
// btnObj.click(function() {
|
|
3520
|
-
// if (btnObj.attr('class') == 'send-audio-btn') {
|
|
3521
|
-
// stream.getAudioTracks()[0].enabled = false;
|
|
3522
|
-
// self.operateAudio("unsend_audio");
|
|
3523
|
-
// btnObj.attr('class', 'unsend-audio-btn');
|
|
3524
|
-
// } else {
|
|
3525
|
-
// stream.getAudioTracks()[0].enabled = true;
|
|
3526
|
-
// self.operateAudio("send_audio");
|
|
3527
|
-
// btnObj.attr('class', 'send-audio-btn');
|
|
3528
|
-
// }
|
|
3529
|
-
// });
|
|
3530
|
-
//
|
|
3531
|
-
// console.log('onrelocalstream:分屏=' + (self.index + 1) + ', video=' + self.video);
|
|
3532
|
-
// }
|
|
3533
|
-
},
|
|
3534
|
-
|
|
3535
|
-
//清理
|
|
3536
|
-
oncleanup: function() {
|
|
3537
|
-
console.log('oncleanup:分屏=' + (self.index + 1));
|
|
3538
|
-
}
|
|
3539
|
-
});
|
|
3540
|
-
|
|
3541
|
-
//<video>注册playing/canplay事件,用于判断视频播放成功
|
|
3542
|
-
self.tagBox.bind("canplay play playing", function () {
|
|
3543
|
-
if(self.video){
|
|
3544
|
-
if (self.tagBox.is(':visible')) return;
|
|
3545
|
-
// 清除播放监测定时任务,清除内容
|
|
3546
|
-
self.playSucTimeOutIndex > 0 && clearTimeout(self.playSucTimeOutIndex);
|
|
3547
|
-
self.tagBox.parent().find(".video-tip").remove();
|
|
3548
|
-
console.log('分屏=' + (self.index + 1) + ', ' + self.video + ' 播放成功');
|
|
3549
|
-
promptSuccess('分屏' + (self.index + 1) + ' 播放成功');
|
|
3550
|
-
self.tagBox.show();
|
|
3551
|
-
//self.tagBox.parent().removeClass("loading").find(".stream-loading").remove();
|
|
3552
|
-
self.tagBox.parent().find(".stream-loading").remove();
|
|
3553
|
-
|
|
3554
|
-
//显示视频信息
|
|
3555
|
-
self.tagBox.parent().find('.info').show();
|
|
3556
|
-
self.tagBox.parent().find('.info-self').show();
|
|
3557
|
-
|
|
3558
|
-
//显示音频按钮
|
|
3559
|
-
self.tagBox.parent().find('.operate-btn button').show();
|
|
3560
|
-
if (self.isPlayBack) {
|
|
3561
|
-
self.tagBox.parent().find('.unrecv-audio-btn').hide();
|
|
3562
|
-
}
|
|
3563
|
-
self.tagBox.parent().find('.recv-audio-btn').attr("class", "unrecv-audio-btn");
|
|
3564
|
-
self.tagBox.parent().find('.send-audio-btn').attr("class", "unsend-audio-btn");
|
|
3565
|
-
|
|
3566
|
-
let width = this.videoWidth;
|
|
3567
|
-
let height = this.videoHeight;
|
|
3568
|
-
//保持长宽比例填充video视频框
|
|
3569
|
-
if (width <= height && width != '0') {
|
|
3570
|
-
self.tagBox.css('object-fit', 'contain');
|
|
3571
|
-
}
|
|
3572
|
-
}
|
|
3573
|
-
});
|
|
3574
|
-
},
|
|
3575
|
-
|
|
3576
|
-
/**
|
|
3577
|
-
* 播放视频
|
|
3578
|
-
* video:视频编号(ID)
|
|
3579
|
-
*/
|
|
3580
|
-
play:function(video){
|
|
3581
|
-
if(!video){
|
|
3582
|
-
//alert("请输入视频ID");
|
|
3583
|
-
promptAlarm('视频ID不能为空');
|
|
3584
|
-
return;
|
|
3585
|
-
}
|
|
3586
|
-
let body = {
|
|
3587
|
-
request: "call",
|
|
3588
|
-
videoidentify: video,
|
|
3589
|
-
playseq: this.index,
|
|
3590
|
-
userToken: this.userToken,
|
|
3591
|
-
autoack: true
|
|
3592
|
-
};
|
|
3593
|
-
this.sipcall.send({"message": body });
|
|
3594
|
-
this.video = video;
|
|
3595
|
-
this.isClosing = false;
|
|
3596
|
-
this.playing = true;
|
|
3597
|
-
this.packetsLostRate = '0.00%';
|
|
3598
|
-
this.packetsLostSum = 0;
|
|
3599
|
-
this.packetsReceivedSum = 0;
|
|
3600
|
-
let numIndex = this.index + 1;
|
|
3601
|
-
let framesDecodedDom = document.getElementById("frame-decoded-" + numIndex);
|
|
3602
|
-
framesDecodedDom.style.display = 'none';
|
|
3603
|
-
this.framesDecodedLast = undefined;
|
|
3604
|
-
this.framesDecodedCount = 0;
|
|
3605
|
-
|
|
3606
|
-
//loading
|
|
3607
|
-
let _li = this.tagBox.parent();
|
|
3608
|
-
clearResult(_li, this);
|
|
3609
|
-
if(!_li.hasClass("loading")){
|
|
3610
|
-
_li.addClass("loading").append('<div class="stream-loading">等待数据流传送...</div>');
|
|
3611
|
-
}
|
|
3612
|
-
_li.find('.operate-btn .close-btn').show();
|
|
3613
|
-
console.log("视频播放:分屏=" + (this.index + 1) + ",设备ID=" + video);
|
|
3614
|
-
},
|
|
3615
|
-
|
|
3616
|
-
close:function(type){
|
|
3617
|
-
if (!type) {
|
|
3618
|
-
this.isLockVideo = false;
|
|
3619
|
-
this.tagBox.parent().find('.lock-video-btn').attr("class", "unlock-video-btn");
|
|
3620
|
-
|
|
3621
|
-
}
|
|
3622
|
-
//清除结果提示内容
|
|
3623
|
-
clearResult(this.tagBox.parent(), this);
|
|
3624
|
-
|
|
3625
|
-
//let reqType = type ? type : "hangup";
|
|
3626
|
-
if(!this.playing) return;
|
|
3627
|
-
let _hangup = {
|
|
3628
|
-
request: "hangup",
|
|
3629
|
-
videoidentify: this.video,
|
|
3630
|
-
playseq: this.index,
|
|
3631
|
-
userToken: this.userToken
|
|
3632
|
-
};
|
|
3633
|
-
this.sipcall.send({"message": _hangup});
|
|
3634
|
-
this.sipcall.hangup();
|
|
3635
|
-
this.tagBox.hide();
|
|
3636
|
-
this.isClosing = true;
|
|
3637
|
-
this.playing = false;
|
|
3638
|
-
this.video = null;
|
|
3639
|
-
this.packetsLostRate = '0.00%';
|
|
3640
|
-
this.packetsLostSum = 0;
|
|
3641
|
-
this.packetsReceivedSum = 0;
|
|
3642
|
-
//清除显示的视频信息
|
|
3643
|
-
if(document.getElementById('info-' + (Number(this.index) + Number(1))))
|
|
3644
|
-
document.getElementById('info-' + (Number(this.index) + Number(1))).innerHTML = '';
|
|
3645
|
-
//隐藏视频信息
|
|
3646
|
-
this.tagBox.parent().find('.info').hide();
|
|
3647
|
-
if(document.getElementById('info-self-' + (Number(this.index) + Number(1))))
|
|
3648
|
-
document.getElementById('info-self-' + (Number(this.index) + Number(1))).innerHTML = '';
|
|
3649
|
-
//隐藏视频信息
|
|
3650
|
-
this.tagBox.parent().find('.info-self').hide();
|
|
3651
|
-
//隐藏音频喇叭
|
|
3652
|
-
this.tagBox.parent().find('.operate-btn button').hide();
|
|
3653
|
-
//避免没收到成功时就点击关闭,清除loading框
|
|
3654
|
-
this.tagBox.parent().removeClass("loading").find(".stream-loading").remove();
|
|
3655
|
-
//清除object-fit
|
|
3656
|
-
this.tagBox.css('object-fit', '');
|
|
3657
|
-
|
|
3658
|
-
// 清除内容提示
|
|
3659
|
-
this.playSucTimeOutIndex > 0 && clearTimeout(this.playSucTimeOutIndex);
|
|
3660
|
-
this.tagBox.parent().find(".video-tip").remove();
|
|
3661
|
-
var numIndex = Number(this.index) + 1;
|
|
3662
|
-
var framesDecodedDom = document.getElementById("frame-decoded-" + numIndex);
|
|
3663
|
-
framesDecodedDom.style.display = 'none';
|
|
3664
|
-
this.framesDecodedLast = undefined;
|
|
3665
|
-
this.framesDecodedCount = 0;
|
|
3666
|
-
},
|
|
3667
|
-
|
|
3668
|
-
/**
|
|
3669
|
-
* 云台控制
|
|
3670
|
-
* up 上
|
|
3671
|
-
* down 下
|
|
3672
|
-
* left 左
|
|
3673
|
-
* right 右
|
|
3674
|
-
* upleft 上左
|
|
3675
|
-
* upright 上右
|
|
3676
|
-
* downleft 下左
|
|
3677
|
-
* downright 下右
|
|
3678
|
-
* zoomin 倍率变大
|
|
3679
|
-
* zoomout 倍率变下
|
|
3680
|
-
* focusnear 焦点+
|
|
3681
|
-
* focusfar 焦点-
|
|
3682
|
-
* irisopen 光圈+
|
|
3683
|
-
* irisclose 光圈-
|
|
3684
|
-
* pointset 设置预置点
|
|
3685
|
-
* pointdel 删除预置点
|
|
3686
|
-
* pointgoto 到预置点
|
|
3687
|
-
* scansetleft 自动扫描左边界
|
|
3688
|
-
* scansetright 自动扫描又边界
|
|
3689
|
-
* scansetspeed 设置扫描速度
|
|
3690
|
-
* scanrun 自动扫描运行
|
|
3691
|
-
* cruiseadd 添加巡航点
|
|
3692
|
-
* cruisedel 删除巡航点
|
|
3693
|
-
* cruisespeed 设置巡航点速度
|
|
3694
|
-
* cruisepausetime 设置巡航滞留时间
|
|
3695
|
-
* cruiserun 启动巡航
|
|
3696
|
-
*/
|
|
3697
|
-
holder: function(type, opts, isStop) {
|
|
3698
|
-
if(!this.video || !this.playing){
|
|
3699
|
-
promptAlarm('未选中播放的视频!');
|
|
3700
|
-
return;
|
|
3701
|
-
}
|
|
3702
|
-
|
|
3703
|
-
let holdType = 'up down left right upleft upright downleft downright zoomin zoomout focusnear focusfar irisopen irisclose pointset pointdel pointgoto '+
|
|
3704
|
-
'scansetleft scansetright scansetspeed scanrun cruiseadd cruisedel cruisespeed cruisepausetime cruiserun';
|
|
3705
|
-
let typeVal = (Number(holdType.split(' ').indexOf(type))+Number(1));
|
|
3706
|
-
|
|
3707
|
-
console.log("holdType:" + typeVal + " type:" + type + (isStop ? ' 停止' : ''));
|
|
3708
|
-
|
|
3709
|
-
if (!typeVal || typeVal <= 0) {
|
|
3710
|
-
console.error('异常PTZ指令:' + typeVal);
|
|
3711
|
-
return false;
|
|
3712
|
-
}
|
|
3713
|
-
|
|
3714
|
-
let body = {
|
|
3715
|
-
request: "ptz",
|
|
3716
|
-
videoidentify: this.video,
|
|
3717
|
-
playseq: this.index,
|
|
3718
|
-
userToken: this.userToken,
|
|
3719
|
-
};
|
|
3720
|
-
|
|
3721
|
-
body.cmd = {
|
|
3722
|
-
speed: opts.speed ? opts.speed : 200,
|
|
3723
|
-
group: 0,
|
|
3724
|
-
present: opts.present ? opts.present : 0,
|
|
3725
|
-
time: 0,
|
|
3726
|
-
type: typeVal
|
|
3727
|
-
}
|
|
3728
|
-
|
|
3729
|
-
if(isStop) {
|
|
3730
|
-
console.log(">>>>yuntai control,stop, video=" + this.video);
|
|
3731
|
-
body.cmd.action = 1;
|
|
3732
|
-
} else {
|
|
3733
|
-
body.cmd.action = 0;
|
|
3734
|
-
console.log('设备号:'+this.video+', 云台移动-->'+ type);
|
|
3735
|
-
}
|
|
3736
|
-
|
|
3737
|
-
this.sipcall.send({"message": body });
|
|
3738
|
-
},
|
|
3739
|
-
|
|
3740
|
-
/**
|
|
3741
|
-
* 历史回放
|
|
3742
|
-
* video设备ID startTime录像开始 stopTime录像结束 例:2015-07-22T12:00:00,注意T隔开
|
|
3743
|
-
*/
|
|
3744
|
-
playback: function(video, startTime, stopTime) {
|
|
3745
|
-
if(!video){
|
|
3746
|
-
promptAlarm('视频ID不能为空');
|
|
3747
|
-
return;
|
|
3748
|
-
}
|
|
3749
|
-
|
|
3750
|
-
let body = {
|
|
3751
|
-
request: "av_playback",
|
|
3752
|
-
videoidentify: video,
|
|
3753
|
-
playseq: this.index,
|
|
3754
|
-
userToken: this.userToken,
|
|
3755
|
-
start_time: startTime,
|
|
3756
|
-
stop_time: stopTime
|
|
3757
|
-
};
|
|
3758
|
-
|
|
3759
|
-
console.log(">>>>playback video=" + video +" startTime=" + startTime + " stopTime=" + stopTime);
|
|
3760
|
-
this.sipcall.send({"message": body });
|
|
3761
|
-
this.video = video;
|
|
3762
|
-
this.playing = true;
|
|
3763
|
-
this.packetsLostRate = '0.00%';
|
|
3764
|
-
this.packetsLostSum = 0;
|
|
3765
|
-
this.packetsReceivedSum = 0;
|
|
3766
|
-
this.isPlayBack = true;
|
|
3767
|
-
|
|
3768
|
-
//loading
|
|
3769
|
-
let _li = this.tagBox.parent();
|
|
3770
|
-
clearResult(_li, this);
|
|
3771
|
-
if(!_li.hasClass("loading")){
|
|
3772
|
-
_li.addClass("loading").append('<div class="stream-loading">等待数据流传送...</div>');
|
|
3773
|
-
}
|
|
3774
|
-
_li.find('.operate-btn .close-btn').show();
|
|
3775
|
-
console.log("历史回放:分屏=" + (this.index + 1) + ",视频ID=" + video);
|
|
3776
|
-
},
|
|
3777
|
-
|
|
3778
|
-
/**
|
|
3779
|
-
* 历史回放控制
|
|
3780
|
-
* video设备ID playType类型 playSpeed速率 startTime开始时间
|
|
3781
|
-
*/
|
|
3782
|
-
playbackControl: function(video, playType, playSpeed, startTime) {
|
|
3783
|
-
let self = this;
|
|
3784
|
-
|
|
3785
|
-
let body = {
|
|
3786
|
-
request: "av_control",
|
|
3787
|
-
videoidentify: video,
|
|
3788
|
-
playseq: self.index,
|
|
3789
|
-
userToken: self.userToken,
|
|
3790
|
-
start_time: startTime,
|
|
3791
|
-
rate: String(playSpeed),
|
|
3792
|
-
cmd: playType
|
|
3793
|
-
};
|
|
3794
|
-
|
|
3795
|
-
console.log(">>>>playbackControl video=" + video + " playType=" + playType + " playSpeed=" + playSpeed);
|
|
3796
|
-
|
|
3797
|
-
//setTimeout(function (){
|
|
3798
|
-
self.sipcall.send({"message": body });
|
|
3799
|
-
//}, 1000);
|
|
3800
|
-
|
|
3801
|
-
if (playType == 'stop') {
|
|
3802
|
-
self.close();
|
|
3803
|
-
|
|
3804
|
-
self.tagBox.hide();
|
|
3805
|
-
self.playing = false;
|
|
3806
|
-
self.video = null;
|
|
3807
|
-
self.packetsLostRate = '0.00%';
|
|
3808
|
-
self.packetsLostSum = 0;
|
|
3809
|
-
self.packetsReceivedSum = 0;
|
|
3810
|
-
self.isPlayBack = false;
|
|
3811
|
-
//清除显示的视频信息
|
|
3812
|
-
document.getElementById('info-' + (Number(self.index) + Number(1))).innerHTML = '';
|
|
3813
|
-
document.getElementById('info-self-' + (Number(self.index) + Number(1))).innerHTML = '';
|
|
3814
|
-
|
|
3815
|
-
//隐藏音频喇叭
|
|
3816
|
-
this.tagBox.parent().find('.operate-btn button').hide();
|
|
3817
|
-
//避免没收到成功时就点击关闭,清除loading框
|
|
3818
|
-
self.tagBox.parent().removeClass("loading").find(".stream-loading").remove();
|
|
3819
|
-
//清除object-fit
|
|
3820
|
-
self.tagBox.css('object-fit', '');
|
|
3821
|
-
}
|
|
3822
|
-
},
|
|
3823
|
-
|
|
3824
|
-
/**
|
|
3825
|
-
* 音频流操作
|
|
3826
|
-
* requstType: recv_audio、stop_audio、send_audio、unsend_audio
|
|
3827
|
-
*/
|
|
3828
|
-
operateAudio: function(requestType) {
|
|
3829
|
-
let self = this;
|
|
3830
|
-
|
|
3831
|
-
if(!self.video){
|
|
3832
|
-
promptAlarm('视频ID不能为空');
|
|
3833
|
-
return;
|
|
3834
|
-
}
|
|
3835
|
-
let body = {
|
|
3836
|
-
request: requestType,
|
|
3837
|
-
videoidentify: self.video,
|
|
3838
|
-
playseq: self.index,
|
|
3839
|
-
userToken: self.userToken,
|
|
3840
|
-
};
|
|
3841
|
-
|
|
3842
|
-
self.sipcall.send({"message": body });
|
|
3843
|
-
console.log("音频操作="+ requestType +", 分屏=" + (self.index + 1) + ",设备ID=" + self.video);
|
|
3844
|
-
},
|
|
3845
|
-
|
|
3846
|
-
/**
|
|
3847
|
-
* 录像操作
|
|
3848
|
-
* requstType: start_av_record(开启录像)、stop_av_record(停止录像)
|
|
3849
|
-
*/
|
|
3850
|
-
recordAv: function(requestType, businessId) {
|
|
3851
|
-
let self = this;
|
|
3852
|
-
|
|
3853
|
-
if(!self.video){
|
|
3854
|
-
promptAlarm('视频ID不能为空');
|
|
3855
|
-
return;
|
|
3856
|
-
}
|
|
3857
|
-
let body = {
|
|
3858
|
-
request: requestType,
|
|
3859
|
-
videoidentify: self.video,
|
|
3860
|
-
playseq: self.index,
|
|
3861
|
-
userToken: self.userToken,
|
|
3862
|
-
businessid: businessId || null
|
|
3863
|
-
};
|
|
3864
|
-
|
|
3865
|
-
self.sipcall.send({"message": body });
|
|
3866
|
-
console.log("录像操作="+ requestType +", 分屏=" + (self.index + 1) + ",设备ID=" + self.video + ",业务ID=" + (businessId || null));
|
|
3867
|
-
},
|
|
3868
|
-
|
|
3869
|
-
/**
|
|
3870
|
-
* 修改分辨率
|
|
3871
|
-
* requstType: change_resolution
|
|
3872
|
-
* CIF 480P 720P 1080P
|
|
3873
|
-
*/
|
|
3874
|
-
changeResolution: function(requestType, resolution) {
|
|
3875
|
-
let self = this;
|
|
3876
|
-
|
|
3877
|
-
if(!self.video){
|
|
3878
|
-
promptAlarm('视频ID不能为空');
|
|
3879
|
-
return;
|
|
3880
|
-
}
|
|
3881
|
-
|
|
3882
|
-
let body = {
|
|
3883
|
-
request: requestType,
|
|
3884
|
-
videoidentify: self.video,
|
|
3885
|
-
playseq: self.index,
|
|
3886
|
-
resolution: resolution,
|
|
3887
|
-
userToken: self.userToken,
|
|
3888
|
-
};
|
|
3889
|
-
|
|
3890
|
-
self.sipcall.send({"message": body });
|
|
3891
|
-
console.log("修改分辨率操作="+ resolution +", 分屏=" + (self.index + 1) + ",设备ID=" + self.video);
|
|
3892
|
-
},
|
|
3893
|
-
|
|
3894
|
-
/**
|
|
3895
|
-
* 对象预呼叫
|
|
3896
|
-
* requstType: open_poccall(开启) close_poccall(关闭)
|
|
3897
|
-
* pocno
|
|
3898
|
-
* centerTel
|
|
3899
|
-
*/
|
|
3900
|
-
pocCall: function(requestType, pocNo, centerTel) {
|
|
3901
|
-
let self = this;
|
|
3902
|
-
|
|
3903
|
-
let body = {
|
|
3904
|
-
request: requestType,
|
|
3905
|
-
pocno: pocNo,
|
|
3906
|
-
playseq: self.index,
|
|
3907
|
-
center_tel: centerTel,
|
|
3908
|
-
userToken: self.userToken,
|
|
3909
|
-
};
|
|
3910
|
-
|
|
3911
|
-
self.sipcall.send({"message": body });
|
|
3912
|
-
console.log("预呼叫操作="+ requestType +", 对讲号码=" + pocNo + ",调度中心号码=" + centerTel);
|
|
3913
|
-
},
|
|
3914
|
-
|
|
3915
|
-
/**
|
|
3916
|
-
* 点对点对讲
|
|
3917
|
-
* requstType: open_ptop_poc(开启) close_poc_poc(关闭)
|
|
3918
|
-
* pocno
|
|
3919
|
-
*/
|
|
3920
|
-
ptopPoc: function(requestType, pocNo) {
|
|
3921
|
-
let self = this;
|
|
3922
|
-
|
|
3923
|
-
let body = {
|
|
3924
|
-
request: requestType,
|
|
3925
|
-
pocno: pocNo,
|
|
3926
|
-
playseq: self.index,
|
|
3927
|
-
pocmember: self.video,
|
|
3928
|
-
userToken: self.userToken,
|
|
3929
|
-
};
|
|
3930
|
-
|
|
3931
|
-
self.sipcall.send({"message": body });
|
|
3932
|
-
console.log("点对点对讲操作="+ requestType +", 主叫号码=" + pocNo + ",被叫号码=" + self.video);
|
|
3933
|
-
}
|
|
3934
|
-
}
|
|
3935
|
-
|
|
3936
|
-
return isIE() ? VideoOcx : VideoWebRtc;
|
|
3937
|
-
}));
|