react_hsbc_teller 2.0.7 → 2.0.8

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.
@@ -6,8 +6,11 @@ import QRCode from 'qrcode.react';
6
6
  import API from '../../api/api';
7
7
  import { BoardOperate } from '../../common/index.esm.js';
8
8
  import './video.less'
9
+ import { compressImage, isLight } from '../../utils/utils'
9
10
  import Header from '../header/header.jsx'
10
11
  import Foot from '../foot/foot.jsx'
12
+ import IconSuccess from '../../assets/img/icon_success.jpg'
13
+ import IconFail from '../../assets/img/icon_fail.jpg'
11
14
  import voiceImgOpen from '../../assets/img/icon_Mute.png'
12
15
  import voiceImgCloe from '../../assets/img/icon_MuteOne.png'
13
16
  import cameraImgOpen from '../../assets/img/icon_camera.png'
@@ -20,6 +23,8 @@ import recordErrorAudio from '../../assets/mp3/record_error.mp3'
20
23
  import internalJoin from '../../assets/mp3/internalJoin.mp3'
21
24
  import internalLeft from '../../assets/mp3/internalLeft.mp3'
22
25
  import leftMetting from '../../assets/mp3/leftmeeting.mp3'
26
+ import networkWeakAudio from '../../assets/mp3/networkweak.mp3'
27
+ import PIPictureClosedAudio from '../../assets/mp3/pip_close.mp3'
23
28
  import errorPng from '../../assets/img/tooltips2_fail.png'
24
29
  import Modal from "antd/lib/modal";
25
30
  import 'antd/lib/modal/style'
@@ -47,6 +52,8 @@ import SignMy from '../sign/signMy.jsx'
47
52
  import Step from '../components/step/step.jsx'
48
53
  import axios from 'axios';
49
54
  import CryptoJS from "crypto-js";
55
+
56
+ const SDK_VERISON = '2.0.8'
50
57
  const IDtypeFront = '请客户在其设备后置摄像头下展示证件正面(如:身份证照片页面)'
51
58
  const IDtypeBack = '请在后置摄像头下展示证件反面(如:身份证国徽页)'
52
59
  const { Option } = Select;
@@ -54,6 +61,18 @@ const LEAVE_TYPE = {
54
61
  TELLER_EXIT: 1, // 坐席退出
55
62
  ROOM_DESTROYED: -1, // 房间异常
56
63
  }
64
+ const POINT_TYPE = {
65
+ tts: '文字转语音',
66
+ asr: '语音转文字',
67
+ ffd: "人脸出框检测",
68
+ env: "环境检测",
69
+ pipd: "画中画显示、关闭",
70
+ pwd: "违禁词检测",
71
+ wnd: "弱网",
72
+ mute: "静音"
73
+ }
74
+ const RECORD_DEVICE_NAME = 'screen-capture-recorder'
75
+ // const RECORD_DEVICE_NAME = 'Full HD webcam'
57
76
  let media_status = 0
58
77
  let pictureInPictureVideo
59
78
  let mix_stream
@@ -73,6 +92,8 @@ let isSuccuseHs = false
73
92
  let isGraffiti = false
74
93
  let strokeColor = '#333'
75
94
  let clearTime
95
+ let beautyMode = 'none'
96
+ let hsMode = 'none'
76
97
  let CanvasHome = styled.div`
77
98
  position: fixed;
78
99
  z-index: ${props => props.zIndexNum};
@@ -118,7 +139,7 @@ function clearStreamRemain() {
118
139
  };
119
140
  async function startBeauty(stream) {
120
141
  await beautyInit();
121
- beautyStart(stream, "none");
142
+ beautyStart(stream, beautyMode);
122
143
  }
123
144
  async function startMix(stream, onState) {
124
145
  var drawCanvas = document.getElementById('canvas');
@@ -134,21 +155,25 @@ async function startHs(stream) {
134
155
 
135
156
  await hsInit();
136
157
 
137
- hsStart(stream, 'none');
158
+ hsStart(stream, hsMode);
138
159
 
139
160
  }
140
161
 
141
162
  async function stopHs() {
142
- var stop_stream = true;//控制是否内部来进行关闭流
143
- var stream = hsStop(stop_stream);
144
- if (stream != null && stream != undefined) {
145
- stream.getTracks().forEach((track) => {
146
- track.stop();
147
- });
148
- stream = null;
163
+ try {
164
+ var stop_stream = true;//控制是否内部来进行关闭流
165
+ var stream = hsStop(stop_stream);
166
+ if (stream != null && stream != undefined) {
167
+ stream.getTracks().forEach((track) => {
168
+ track.stop();
169
+ });
170
+ stream = null;
171
+ }
172
+ isSuccuseHs = false
173
+ } catch (err) {
174
+ console.log('stopHs Error')
175
+ console.log(err)
149
176
  }
150
- isSuccuseHs = false
151
-
152
177
  }
153
178
  async function mixStopClick() {
154
179
  var stop_stream = true;//控制是否内部来进行关闭流
@@ -173,6 +198,7 @@ class Video extends Component {
173
198
  }
174
199
  cancel = axios.CancelToken.source()
175
200
  state = {
201
+ ablePlayNetweakAudio: true,
176
202
  beautyType: false,
177
203
  beautyName: '开启美颜',
178
204
  signNoClick: false,
@@ -205,6 +231,7 @@ class Video extends Component {
205
231
  isModalVisibleFacial: false,
206
232
  isModalVisibleEnd: false,
207
233
  isModalVisible: false,
234
+ isPictureConfirmModalVisible:false,
208
235
  screenName: '共享模式',
209
236
  suspendName: '暂停',
210
237
  cameraImg: cameraImgOpen,
@@ -292,6 +319,8 @@ class Video extends Component {
292
319
  cardFailReason: '',
293
320
  videoType: '',
294
321
  certificateValidityType: true,
322
+ drawCanvasInterval: null,
323
+ faceDetectionTimer: null, // 人脸检测定时器
295
324
  };
296
325
  // eslint-disable-next-line no-undef
297
326
  test_controller = '';
@@ -299,7 +328,7 @@ class Video extends Component {
299
328
  saveLog = (val) => {
300
329
  axios({
301
330
  method: 'get',
302
- baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller=2.0.7&logTime=' + Date.now() + '&mtoken=' + encodeURIComponent(this.state.rtoken) + '&roomId=' + encodeURIComponent(this.state.channelId) + '&sessionId=' + encodeURIComponent(this.state.sessionId) + '&appointmentID=' + this.props.businessNumber,
331
+ baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller='+ SDK_VERISON +'&logTime=' + Date.now() + '&mtoken=' + encodeURIComponent(this.state.rtoken) + '&roomId=' + encodeURIComponent(this.state.channelId) + '&sessionId=' + encodeURIComponent(this.state.sessionId) + '&appointmentID=' + this.props.businessNumber,
303
332
 
304
333
  }).then(res => {
305
334
 
@@ -345,6 +374,8 @@ class Video extends Component {
345
374
  this.test_controller.Publish(publish_config)
346
375
  })
347
376
  // this.publishAllScreen();
377
+ // 单独发布录制屏幕设备的流
378
+ this.publishRecorderDevice()
348
379
 
349
380
  this.props.createRoomCallback({
350
381
  type: 1,
@@ -549,7 +580,7 @@ class Video extends Component {
549
580
  }
550
581
  }
551
582
  // 开启录制
552
- enableServerRecording = () => {
583
+ enableServerRecording = (record_business_id) => {
553
584
  const that = this
554
585
  this.rateAll().then((res) => {
555
586
  console.log('退出房间者', res)
@@ -625,7 +656,7 @@ class Video extends Component {
625
656
  height: 175
626
657
  },
627
658
  {
628
- tag: 'RM_ALL_SCREEN',
659
+ tag: 'sharedScreen', // 一期暂时不需要录制
629
660
  xPosition: 960,
630
661
  yPosition: 180,
631
662
  width: 320,
@@ -666,12 +697,23 @@ class Video extends Component {
666
697
  recordParam.endType = 1;
667
698
  recordParam.crf = 26
668
699
  recordParam.overlaps = [
700
+ {
701
+ tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
702
+ type: 2, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
703
+ id: 2, // ⽔印 ID
704
+ enable: true,
705
+ xPosition: 640, // x 轴位置
706
+ yPosition: 10, // y 轴位置
707
+ text: `${this.props.recordMode ==1 ?'远程录制' :'网点录制'} ${this.props.salesBranchCode || ''} ${this.props.financialOffice || ''}`,
708
+ fontSize: 16, // 字体⼤⼩
709
+ url: '' // ⽔印图⽚ HTTP 地址
710
+ },
669
711
  {
670
712
  tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
671
713
  type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
672
714
  id: 1, // ⽔印 ID
673
715
  enable: true,
674
- xPosition: 1000, // x 轴位置
716
+ xPosition: 1080, // x 轴位置
675
717
  yPosition: 10, // y 轴位置
676
718
  text: '', // ⽔印⽂字
677
719
  fontSize: 16, // 字体⼤⼩
@@ -680,7 +722,7 @@ class Video extends Component {
680
722
  ];
681
723
  recordParam.tagPositions = list
682
724
  console.log('recordParam', recordParam);
683
- that.test_controller.StartRemoteRecord(filePath, recordParam, '')
725
+ that.test_controller.StartRemoteRecord(filePath, recordParam, record_business_id)
684
726
 
685
727
  })
686
728
 
@@ -698,6 +740,7 @@ class Video extends Component {
698
740
  };
699
741
  sendMessage = (msg) => {
700
742
  try {
743
+ console.log('发送消息', JSON.stringify(msg))
701
744
  this.test_controller.SendTextMsg(JSON.stringify(msg))
702
745
  } catch (err) {
703
746
  console.error(`内部错误, msg = ${JSON.stringify(msg)} `)
@@ -945,6 +988,100 @@ class Video extends Component {
945
988
  this.selectCustomer('facial')
946
989
  }
947
990
  };
991
+ generateMediaInfo = (sid) => {
992
+ let that = this
993
+ console.log(that.test_controller, sid)
994
+ console.log(that.test_controller.GetMediaInfo(sid))
995
+ let originalMediaInfo = that.test_controller.GetMediaInfo(sid);
996
+ let mediaInfo = {
997
+ peer_connection_: originalMediaInfo.peer_connection_,
998
+ local_video_width: originalMediaInfo.local_video_width,
999
+ local_video_height: originalMediaInfo.local_video_height,
1000
+ local_video_frame: originalMediaInfo.local_video_frame,
1001
+ local_video_bitrate: originalMediaInfo.local_video_bitrate,
1002
+ stream_type: originalMediaInfo.stream_type,
1003
+ stat_interval_: 3,
1004
+ video_send_packets_base_: 0,
1005
+ video_recv_packets_base_: 0,
1006
+ video_send_lost_pack_base_: 0,
1007
+ video_recv_lost_pack_base_: 0,
1008
+ audio_send_packets_base_: 0,
1009
+ audio_recv_packets_base_: 0,
1010
+ audio_send_lost_pack_base_: 0,
1011
+ audio_recv_lost_pack_base_: 0,
1012
+ video_send_qpsum_base: 0,
1013
+ video_send_frame_encoded_base: 0,
1014
+ video_recv_qpsum_base: 0,
1015
+ video_recv_frame_decoded_base: 0,
1016
+ video_send_bitrate_base_: 0,
1017
+ video_recv_bitrate_base_: 0,
1018
+ audio_send_bitrate_base_: 0,
1019
+ audio_recv_bitrate_base_: 0,
1020
+ };
1021
+ return mediaInfo;
1022
+ }
1023
+ detectNetworkWeak = () => {
1024
+ return new Promise((resolve, reject) => {
1025
+ let detectionsNumber = 3
1026
+ let finalResult = true
1027
+ let setTimer = () => {
1028
+ setTimeout(() => {
1029
+ this.test_controller.GetStats(this.mediaInfo).then(media_stat => {
1030
+ if (detectionsNumber>2) {
1031
+ // 不考虑第一次的评估结果,重新计算码率
1032
+ detectionsNumber--;
1033
+ setTimer()
1034
+ return
1035
+ }
1036
+ console.log('media_stat:')
1037
+ console.log(media_stat)
1038
+ // 分辨率、帧率
1039
+ let googAvailableSendBandwidth = (media_stat["VideoBwe"]["googAvailableSendBandwidth"] / 1000).toFixed(2);
1040
+ let googTransmitBitrate = (media_stat["VideoBwe"]["googTransmitBitrate"] / 1000).toFixed(2);
1041
+ let ssrcVideoSendLostRate = media_stat["ssrcVideoSend"]["lostRate"];
1042
+ let ssrcAudioSendLostRate = media_stat["ssrcAudioSend"]["lostRate"];
1043
+ let weak_googAvailableSendBandwidth = 200;
1044
+ let weak_ssrcVideoSendLostRate = 20;
1045
+ let weak_ssrcAudioSendLostRate = 20;
1046
+ let weak_str = "网络正常";
1047
+ if (googAvailableSendBandwidth < weak_googAvailableSendBandwidth) {
1048
+ weak_str = "当前网络不佳";
1049
+ }
1050
+ let bpsSend = (media_stat.ssrcVideoSend["bpsSend"] / 1000).toFixed(2)
1051
+ let fps = media_stat["ssrcVideoSend"].googFrameRateSent
1052
+ let str =
1053
+ "带宽评估:" + (googAvailableSendBandwidth == undefined ? "none" : googAvailableSendBandwidth + "kbps") + "; "
1054
+ + "视频码率:" + bpsSend + "kb" + "; "
1055
+ + "音频码率:" + (media_stat.ssrcAudioSend["bpsSend"] / 1000).toFixed(2) + "kb" + "; "
1056
+ + "视频丢包率:" + (ssrcVideoSendLostRate == undefined ? "none" : ssrcVideoSendLostRate + "%") + "; "
1057
+ + "音频丢包率:" + (ssrcAudioSendLostRate == undefined ? "none" : ssrcAudioSendLostRate + "%") + "; "
1058
+ + weak_str + "; "
1059
+ + "当前编码格式:" + media_stat["ssrcVideoSend"].googCodecName + "; "
1060
+ + "分辨率:" + media_stat["ssrcVideoSend"].resolution + "; "
1061
+ + "帧率:" + media_stat["ssrcVideoSend"].googFrameRateSent;
1062
+ console.log('弱网', str)
1063
+ // document.getElementById("publish_media_stat1").innerText = str;
1064
+ let result = (bpsSend < 200 ) && googAvailableSendBandwidth < weak_googAvailableSendBandwidth
1065
+ if (result) {
1066
+ console.log('[!]弱网单次评估' + result);
1067
+ } else {
1068
+ finalResult = false
1069
+ console.log('弱网单次评估' + result);
1070
+ }
1071
+ if (detectionsNumber > 0 && finalResult) {
1072
+ detectionsNumber -= 1
1073
+ setTimer();
1074
+ } else {
1075
+ console.log('弱网综合检测结果:' + finalResult)
1076
+ resolve(finalResult)
1077
+ }
1078
+ });
1079
+
1080
+ }, 3000)
1081
+ }
1082
+ setTimer()
1083
+ })
1084
+ }
948
1085
  ocrClick = () => {
949
1086
  if (this.isFileSuccuse()) {
950
1087
  this.state.faceCustomerType = 2
@@ -1012,14 +1149,14 @@ class Video extends Component {
1012
1149
  return a.order - b.order;
1013
1150
  })
1014
1151
  for (let i =1;i<=12;i++){
1015
- if(document.getElementById('video'+i).name){
1152
+ if(sortedlist[i-1].videoName){
1016
1153
  list.push({
1017
- name: 'video' + i,
1018
- title: sortedlist[i-1].videoName,
1019
- mute: sortedlist[i-1].mute,
1020
- noVideo: sortedlist[i-1].noVideo
1021
- })
1022
- }
1154
+ name: 'video' + sortedlist[i-1].idIndex,
1155
+ title: sortedlist[i-1].videoName,
1156
+ mute: sortedlist[i-1].mute,
1157
+ noVideo: sortedlist[i-1].noVideo
1158
+ })
1159
+ }
1023
1160
  }
1024
1161
  console.log(list)
1025
1162
  this.state.listVideoPicture = list
@@ -1224,17 +1361,33 @@ class Video extends Component {
1224
1361
 
1225
1362
  pictureInPictureVideo.addEventListener('enterpictureinpicture', (event) => {
1226
1363
  //可获取画中画窗口的一些数据,如宽高等
1364
+ console.log('开启画中画')
1227
1365
  pictureInPictureVideo.style.display = 'block';
1228
1366
  pictureInPictureVideo.play();
1229
1367
  this.state.isPictureInPicture = true
1230
1368
  });
1231
1369
 
1232
1370
  pictureInPictureVideo.addEventListener('leavepictureinpicture', (event) => {
1371
+ console.log('关闭画中画')
1233
1372
  pictureInPictureVideo.srcObject = null;
1234
1373
  pictureInPictureVideo.style.display = "none";
1235
1374
  this.state.listVideoPicture = []
1236
1375
  worker.postMessage(false);
1237
1376
  this.state.isPictureInPicture = false
1377
+
1378
+ // 画中画循环播放逻辑
1379
+ this.setState({
1380
+ isPictureConfirmModalVisible: true
1381
+ })
1382
+ const loopPlay = () => {
1383
+ console.log('loopPlay status', this.state.isPictureInPicture);
1384
+ if(!this.state.isPictureInPicture && document.getElementById("publish_video1")){
1385
+ let audio = new Audio(PIPictureClosedAudio)
1386
+ audio.play()
1387
+ setTimeout(loopPlay, 3000);
1388
+ }
1389
+ }
1390
+ setTimeout(loopPlay, 0);
1238
1391
  });
1239
1392
 
1240
1393
  }
@@ -1336,6 +1489,7 @@ class Video extends Component {
1336
1489
  }, ()=>{
1337
1490
  this.pictureInPicture('Refresh')
1338
1491
  })
1492
+ this.messageClick('客户人脸已离框', 'error')
1339
1493
  }
1340
1494
  }
1341
1495
  else if (Mival.typeId == 3003) { // app进入前台
@@ -1352,6 +1506,18 @@ class Video extends Component {
1352
1506
  })
1353
1507
  }
1354
1508
  }
1509
+ else if (Mival.typeId == 5001) { // 客户端离框
1510
+ this.messageClick('客户人脸已离框', 'error')
1511
+ // this.saveVideoPoint('ffd', '客户人脸离框');
1512
+ }
1513
+ else if (Mival.typeId == 5002) { // 客户端
1514
+ this.messageClick('客户背光、曝光过度', 'error')
1515
+ // this.saveVideoPoint('env', '客户端背光、曝光过度');
1516
+ }
1517
+ else if (Mival.typeId == 5003) { // 客户端弱网
1518
+ this.messageClick('客户当前网络较弱', 'error')
1519
+ // this.saveVideoPoint('wnd', '客户端弱网');
1520
+ }
1355
1521
  else if (Mival.typeId == 1220) {
1356
1522
  // 一炒多的图片 1214
1357
1523
  if (Mival.sessionId == this.state.sessionId) {
@@ -1382,6 +1548,9 @@ class Video extends Component {
1382
1548
  if (Mival.type == 1) {
1383
1549
  this.switchExternal()
1384
1550
  this.saveLog('whiteboard start, typeId=1218,')
1551
+ if (typeof this.props.sfpCallback === 'function'){
1552
+ this.props.sfpCallback()
1553
+ }
1385
1554
  } else if (Mival.type == 2) {
1386
1555
  if (streamShare) {
1387
1556
  streamShare.getTracks().forEach(track => track.stop());
@@ -1395,6 +1564,7 @@ class Video extends Component {
1395
1564
  } else {
1396
1565
  if (document.getElementById('video20').name) {
1397
1566
  this.test_controller.UnPublish(document.getElementById('video20').name)
1567
+ if(this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
1398
1568
  }
1399
1569
  this.setState({
1400
1570
  isWhiteboard: false
@@ -1425,6 +1595,9 @@ class Video extends Component {
1425
1595
 
1426
1596
  }
1427
1597
  }
1598
+ if (this.state.isPictureInPicture) {
1599
+ this.pictureInPicture('Refresh')
1600
+ }
1428
1601
  }
1429
1602
  } else if (Mival.typeId == 121305) {
1430
1603
  if (Mival.sessionId == this.state.sessionId) {
@@ -1492,20 +1665,165 @@ class Video extends Component {
1492
1665
  this.setState({
1493
1666
  videoList: this.state.videoList
1494
1667
  })
1668
+ if (this.state.isPictureInPicture) {
1669
+ this.pictureInPicture('Refresh')
1670
+ }
1495
1671
  }
1496
1672
  } else if (Mival.typeId == 10020) {
1497
- // 录制服务异常中断,请重试
1673
+ // 录制中断
1498
1674
  this.messageClick('录制服务异常中断,请重试', 'error')
1499
- let audio = new Audio(recordErrorAudio)
1500
- audio.play()
1675
+ this.saveLog('recording error')
1676
+ this.setState({
1677
+ isRecordingeErrorModalVisible: true,
1678
+ recordId: ''
1679
+ })
1680
+ // 循环播放录制中断语音
1681
+ const loopPlay = () => {
1682
+ if(!this.state.recordId && document.getElementById("publish_video1")){
1683
+ let audio = new Audio(recordErrorAudio)
1684
+ audio.play()
1685
+ setTimeout(loopPlay, 3000);
1686
+ }
1687
+ }
1688
+ setTimeout(loopPlay, 0);
1689
+
1501
1690
  } else if (Mival.typeId == 33001 && this.state.sessionId == Mival.data.sessionId) {
1502
1691
  if (Mival.type == 1) {
1503
1692
  this.saveAuthorize(Mival.data.userId)
1504
1693
  this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1505
1694
  }
1506
1695
  console.log('33001 done')
1696
+ } else if (Mival.typeId == 2210 && this.state.sessionId == Mival.sessionId) {
1697
+ if (Mival.status == 1) {
1698
+ // 开启了业务录制
1699
+ console.log('业务录制开启')
1700
+ this.state.businessId = Mival.id;
1701
+ this.saveLog('Start business recording')
1702
+ this.enableServerRecording( Mival.id)
1703
+
1704
+ this.startFaceDetection();
1705
+ this.startImageDetection();
1706
+ } else if (Mival.status == 2) {
1707
+ // 关闭了业务录制
1708
+ console.log('业务录制关闭')
1709
+ this.saveLog('Stop business recording')
1710
+ this.test_controller.StopRemoteRecord(this.state.businessRecordId)
1711
+ this.state.businessId = '';
1712
+ clearInterval(this.state.faceDetectionTimer);
1713
+ clearInterval(this.state.imageDetectionTimer);
1714
+ }
1715
+ } else if (Mival.typeId == 2002 && this.state.sessionId == Mival.sessionId) {
1716
+ // 会议到时间
1717
+ console.log('会议超过时间限制')
1718
+ this.endSessionValue();
1507
1719
  }
1508
1720
  }
1721
+ startFaceDetection = () => {
1722
+ console.log('startFaceDetection!!!!')
1723
+ clearInterval(this.state.faceDetectionTimer);
1724
+ const timer = setInterval( async () => {
1725
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1726
+ try {
1727
+ let result = await API.faceDetection({
1728
+ activityId: this.props.businessNumber,
1729
+ sessionId: `${this.props.tellerAccount}_${Date.now()}`,
1730
+ // sessionId: this.state.sessionId,
1731
+ roomId: this.state.channelId + '',
1732
+ appId: this.state.appId,
1733
+ recordId: this.state.recordId,
1734
+ base64Image: path.replace('data:image/png;base64,', '')
1735
+ });
1736
+ if (result.faceNum == 0) {
1737
+ // 人脸出框
1738
+ this.messageClick('检测到您的人脸已出框', 'error')
1739
+ // 打点
1740
+ this.saveVideoPoint('ffd', 'RM端人脸离框');
1741
+ }
1742
+ } catch (err) {
1743
+ console.error(err);
1744
+ if (err.status == 502 || err.status == 404) {
1745
+ }
1746
+ }
1747
+ }, 5000);
1748
+
1749
+ this.state.faceDetectionTimer = timer;
1750
+ }
1751
+ startImageDetection = () => {
1752
+ console.log('startImageDetection!!!!')
1753
+ clearInterval(this.state.imageDetectionTimer);
1754
+ const timer = setInterval( async () => {
1755
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1756
+ const img = new Image()
1757
+ img.src = path;
1758
+ img.width = 300 //
1759
+ img.onload = () => {
1760
+ const origin = cv.imread(img)
1761
+ // let start = new Date().getTime()
1762
+ const res = isLight(origin)
1763
+ if (res==1 || res== -1){
1764
+ // 背景曝光过度
1765
+ this.messageClick('检测到当前背光、曝光过度', 'error')
1766
+ this.saveVideoPoint('env', 'RM端背光、曝光过度');
1767
+ }
1768
+ origin.delete()
1769
+ // let end = new Date().getTime()
1770
+ // console.log('执行时间(s) ', (end - start)/1000 )
1771
+ }
1772
+ }, 3000);
1773
+
1774
+ this.state.imageDetectionTimer = timer;
1775
+ }
1776
+ lightDetect() {
1777
+ try {
1778
+ if (document.getElementById("publish_video1").name) {
1779
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1780
+ console.log('检测图像长度',path.length)
1781
+ const img = new Image()
1782
+ img.src = path;
1783
+ img.width = 300 //
1784
+ img.onload = () => {
1785
+ const origin = cv.imread(img)
1786
+ // let start = new Date().getTime()
1787
+ const res = isLight(origin)
1788
+ if (res==1 || res==-1){
1789
+ // 背景曝光过度
1790
+ this.state.envInfo.lightResult = '不合格'
1791
+ } else {
1792
+ this.state.envInfo.lightResult = '合格'
1793
+ }
1794
+ this.setState({
1795
+ envInfo: this.state.envInfo
1796
+ })
1797
+ origin.delete()
1798
+ }
1799
+ }
1800
+ // else {
1801
+ // setTimeout(() => {
1802
+ // this.lightDetect()
1803
+ // }, 1000);
1804
+ // }
1805
+ }catch(err){
1806
+ console.error(err)
1807
+ }
1808
+ }
1809
+ saveVideoPoint = async (code, content) => {
1810
+ try {
1811
+ let result = await API.saveVideoPoint({
1812
+ title: POINT_TYPE[code],
1813
+ content: [content],
1814
+ code,
1815
+ activityId: this.props.businessNumber,
1816
+ sessionId: this.state.sessionId,
1817
+ roomId: this.state.channelId + '',
1818
+ appId: this.state.appId,
1819
+ recordId: this.state.recordId,
1820
+ });
1821
+ } catch (err) {
1822
+ console.error(err);
1823
+ if (err.status == 502 || err.status == 404) {
1824
+ }
1825
+ }
1826
+ }
1509
1827
  mountClick = () => {
1510
1828
  let data = {
1511
1829
  account: this.props.tellerAccount,
@@ -1602,26 +1920,38 @@ class Video extends Component {
1602
1920
  }
1603
1921
  }
1604
1922
  console.log(objList, objList1, objList2)
1923
+ const cameraList = objList.filter(el => !el.actionname.includes(RECORD_DEVICE_NAME))
1924
+ const recorderDevice = objList.find(el => el.actionname.includes(RECORD_DEVICE_NAME))
1605
1925
  this.setState({
1606
- cameraList: objList,
1926
+ cameraList: cameraList,
1927
+ recorderDevice: recorderDevice,
1607
1928
  microphoneList: objList1,
1608
1929
  speakerList: objList2.length > 0 ? [objList2[0]] : []
1609
1930
  })
1610
1931
  let indexId = 0
1611
- objList.map((item, index) => {
1612
- if (item.actionname.indexOf('Integrated Camera') != -1) {
1932
+ let microId = 0
1933
+ // 摄像头设置默认
1934
+ objList.forEach((item, index) => {
1935
+ if (item.actionname.indexOf('HP Full-HD Camera') != -1) {
1613
1936
  indexId = index
1937
+ } else if (item.actionname.indexOf('Integrated Camera') != -1) {
1938
+ indexId = index
1939
+ }
1940
+ })
1941
+ // 麦克风设置默认
1942
+ objList1.forEach((item, index) => {
1943
+ if (item.actionname.indexOf('Microphone Array (Realtek High Definition Audio(SST))') != -1) {
1944
+ microId = index
1614
1945
  }
1615
1946
  })
1616
- console.log(indexId)
1947
+ console.log(indexId, microId)
1617
1948
  this.setState({
1618
1949
  cameraValue: objList[indexId].actionid,
1619
- microphoneValue: objList1[0].actionid
1950
+ microphoneValue: objList1[microId].actionid
1620
1951
  })
1621
1952
  if (!this.state.appId && !this.state.sessionType) {
1622
1953
  console.log('cameraValue', this.state.cameraValue)
1623
1954
  this.mpaasSig(data);
1624
- this.showEnvDetection()
1625
1955
  } else {
1626
1956
  console.log('cameraValue', this.state.cameraValue)
1627
1957
  this.setState({
@@ -1740,6 +2070,8 @@ class Video extends Component {
1740
2070
  this.test_controller.Publish(publish_config)
1741
2071
  })
1742
2072
  // this.publishAllScreen();
2073
+ // 单独发布录制屏幕设备的流
2074
+ this.publishRecorderDevice()
1743
2075
 
1744
2076
  this.roomCallBack(1, '', 0)
1745
2077
  this.saveLog('mrtc join room success')
@@ -1774,12 +2106,8 @@ class Video extends Component {
1774
2106
  this.mpaasSig(data);
1775
2107
  };
1776
2108
  this.test_controller.OnSendTextMsgSucc = (msgId) => {
1777
- console.log('发送成功', msgId)
1778
- this.setState({
1779
- documentError: '',
1780
- isModalVisibleCustomer: false,
1781
- })
1782
- this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
2109
+ // console.log('发送成功', msgId)
2110
+ // this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
1783
2111
  }
1784
2112
  this.test_controller.OnSendTextMsgFailed = (msgId, code, msg) => {
1785
2113
  console.log('发送失败', msgId, code, msg)
@@ -1794,57 +2122,8 @@ class Video extends Component {
1794
2122
  }
1795
2123
  this.test_controller.OnReceiveTextMsg = (uid, msg) => {
1796
2124
  console.log('收到手机端消息',uid, msg, JSON.parse(msg))
1797
- // 线下demo静音处理
1798
- // if (JSON.parse(msg).typeId == 4004 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1799
- // if (this.isFileSuccuse()) {
1800
- // if (!this.state.voiceStatue) {
1801
- // // 静音本地
1802
- // this.setState({
1803
- // voiceStatue: true,
1804
- // voiceImg: voiceImgCloe,
1805
- // voiceName: '解除静音'
1806
- // });
1807
- // let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1808
- // this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1809
- // callNimIM('sendCustomCmdMsg', {
1810
- // customId: this.state.imRoomId,
1811
- // content: JSON.stringify({
1812
- // 'typeId': 1013,
1813
- // 'muteStatus': 1,
1814
- // 'data': {
1815
- // 'sessionId': this.state.sessionId,
1816
- // 'userId': this.props.tellerAccount
1817
- // }
1818
- // })
1819
- // }, function (code, message, data) {
1820
- // // console.log(data)
1821
- // })
1822
- // }
1823
- // document.getElementById('audio1').muted = true
1824
- // console.log('音频流静音')
1825
- // console.log(document.getElementById('audio1').muted)
1826
- // setTimeout(() => {
1827
- // callNimIM('sendCustomCmdMsg', {
1828
- // customId: this.state.imRoomId,
1829
- // content: JSON.stringify({
1830
- // 'typeId': 1223,
1831
- // 'state': 1, // app解除静音
1832
- // 'sessionId': this.state.sessionId,
1833
- // 'userId': uid //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1834
- // })
1835
- // });
1836
- // }, 1000);
1837
- // }
1838
- // }
1839
- this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
2125
+ // this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
1840
2126
  this.handleReceiveMsg(msg)
1841
- // 33001 已合并到 handleReceiveMsg
1842
- // if (JSON.parse(msg).typeId == 33001 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1843
- // if (JSON.parse(msg).type == 1) {
1844
- // this.saveAuthorize(JSON.parse(msg).data.userId)
1845
- // this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1846
- // }
1847
- // }
1848
2127
  }
1849
2128
  this.test_controller.StreamFilterHandler = async (publish_tag, stream, stream_type, publish_device, media_type) => {
1850
2129
  console.log(`stream processed by client, publish_device=${publish_device}, media_type=${media_type}, publish_tag=${publish_tag},stream_type=${stream_type}`);
@@ -1860,12 +2139,13 @@ class Video extends Component {
1860
2139
  if (publish_tag == 'tag1') {
1861
2140
  console.log('tag1', stream)
1862
2141
  let newStream = stream;
1863
-
1864
2142
  if (stream.getVideoTracks()[0]) {
1865
- await startBeauty(newStream);
1866
- newStream = beautyCaptureStream();
1867
- await startHs(newStream);
1868
- newStream = hsCaptureStream();
2143
+ if (this.state.beautyType || isSuccuseHs){
2144
+ await startBeauty(newStream);
2145
+ newStream = beautyCaptureStream();
2146
+ await startHs(newStream);
2147
+ newStream = hsCaptureStream();
2148
+ }
1869
2149
  // 清理原始流
1870
2150
  newStream.oninactive = function () {
1871
2151
  clearOriginStream(stream);
@@ -1887,9 +2167,26 @@ class Video extends Component {
1887
2167
  }
1888
2168
 
1889
2169
  if (publish_tag == 'projectionWhiteboard' && publish_device == 2) {
1890
-
1891
2170
  let newStream1 = stream;
1892
2171
  if (stream.getVideoTracks()[0]) {
2172
+ try {
2173
+ console.log('共享')
2174
+ console.log(stream.getVideoTracks()[0])
2175
+ if ( stream.getVideoTracks()[0] instanceof BrowserCaptureMediaStreamTrack) {
2176
+ console.log('tab共享')
2177
+ this.saveLog('Share type = tab')
2178
+ } else if (stream.getVideoTracks()[0] instanceof MediaStreamTrack && stream.getVideoTracks()[0].label.includes('screen')) {
2179
+ console.log('屏幕共享')
2180
+ this.saveLog('Share type = screen')
2181
+ } else if (stream.getVideoTracks()[0].label.includes('window')){
2182
+ console.log('窗口共享')
2183
+ this.saveLog('Share type = window')
2184
+ }
2185
+ } catch (err) {
2186
+ console.log('不支持此浏览器记录投屏类型日志')
2187
+ console.log(navigator.userAgent)
2188
+ console.log(err)
2189
+ }
1893
2190
  if (this.state.operateShow) {
1894
2191
  await startMix(newStream1, 'mix');
1895
2192
 
@@ -1901,6 +2198,7 @@ class Video extends Component {
1901
2198
  canvas.width = this.state.widthVideo
1902
2199
  } else {
1903
2200
  await startMix(newStream1, 'none');
2201
+ isGraffiti = false
1904
2202
  }
1905
2203
 
1906
2204
  newStream1 = mixCaptureStream();
@@ -1921,11 +2219,12 @@ class Video extends Component {
1921
2219
  stream = null;
1922
2220
  }
1923
2221
  }
2222
+ if (stream.getAudioTracks()[0] && newStream1.addTrack) {
2223
+ newStream1.addTrack(stream.getAudioTracks()[0])
2224
+ }
1924
2225
  return newStream1
1925
- } else {
1926
- return stream
1927
2226
  }
1928
-
2227
+ return stream
1929
2228
  }
1930
2229
  // 发布媒体流成功
1931
2230
  this.test_controller.OnPublishSucc = (sid) => {
@@ -1938,7 +2237,7 @@ class Video extends Component {
1938
2237
  'sharedScreen': 1,
1939
2238
  'tellerId': this.props.tellerAccount
1940
2239
  })
1941
- if (this.state.screenName == '切换共享') {
2240
+ if (this.state.screenName == '共享屏幕') {
1942
2241
  this.state.isSharedScreen = true
1943
2242
  this.state.isScreenSwitching = false
1944
2243
  }
@@ -1949,6 +2248,10 @@ class Video extends Component {
1949
2248
 
1950
2249
  loading: false,
1951
2250
  });
2251
+ setTimeout(() => {
2252
+ this.showEnvDetection()
2253
+ }, 1500);
2254
+
1952
2255
 
1953
2256
  this.enterRoom()
1954
2257
  this.updateMeetingInfo()
@@ -1968,6 +2271,8 @@ class Video extends Component {
1968
2271
  },
1969
2272
  1000
1970
2273
  );
2274
+ this.mediaInfo = this.generateMediaInfo(document.getElementById("publish_video1").name);
2275
+
1971
2276
  } else {
1972
2277
  var box = document.getElementById("whiteboardDIV");
1973
2278
  var box1 = document.getElementById("operate")
@@ -2042,6 +2347,10 @@ class Video extends Component {
2042
2347
  participants.map((item, index) => {
2043
2348
  if (item.uid != this.state.tellerAccount) {
2044
2349
  item.publish.map((itemOne, indexOne) => {
2350
+ if (itemOne.tag && itemOne.tag.includes('UnSubscribe_RM')) {
2351
+ console.log('过滤订阅的tag:', itemOne.tag)
2352
+ return
2353
+ }
2045
2354
  let array = this.state.roomCustomerList;
2046
2355
  let newArray = [...array];
2047
2356
  newArray.push({
@@ -2102,6 +2411,7 @@ class Video extends Component {
2102
2411
  console.log(config_param)
2103
2412
  console.log('发起订阅')
2104
2413
  this.test_controller.Subscribe(config_param)
2414
+ document.getElementById(config_param.subscribe_video_id).name = 'temp'
2105
2415
 
2106
2416
  }
2107
2417
  })
@@ -2119,6 +2429,10 @@ class Video extends Component {
2119
2429
  this.test_controller.OnNewPublish = (feed) => {
2120
2430
  console.log('有新发布者', feed);
2121
2431
  console.log(new Date())
2432
+ if (feed.tag && feed.tag.includes('UnSubscribe_RM')) {
2433
+ console.log('过滤订阅的tag:', feed.tag)
2434
+ return
2435
+ }
2122
2436
  this.sendMessage({
2123
2437
  'typeId': 1013,
2124
2438
  'muteStatus': this.state.voiceStatue ? 1 : 0,
@@ -2325,6 +2639,10 @@ class Video extends Component {
2325
2639
  // let audio = new Audio(src)
2326
2640
  // audio.play()
2327
2641
  // }
2642
+ if (participant.includes('UnHint')){
2643
+ console.log('过滤掉的uid', participant)
2644
+ return
2645
+ }
2328
2646
 
2329
2647
 
2330
2648
  this.appGetUsernameClick(participant).then((res) => {
@@ -2362,44 +2680,97 @@ class Video extends Component {
2362
2680
  this.test_controller.OnNetworkWeak = (bpsSend, bpsRecv, sid) => {
2363
2681
  console.log('弱网回调', bpsSend, bpsRecv, sid)
2364
2682
  if (sid == document.getElementById('publish_video1').name) {
2365
- this.messageClick('当前网络环境较差', 'error')
2366
- this.saveLog('mrtc OnNetworkWeak')
2683
+
2684
+ this.detectNetworkWeak().then((isWeak) => {
2685
+ console.log('弱网结果:' + isWeak)
2686
+ if (isWeak) {
2687
+ this.messageClick('当前网络环境较差', 'error')
2688
+ this.saveLog('mrtc OnNetworkWeak')
2689
+ this.saveVideoPoint('wnd', 'RM端弱网');
2690
+ if (this.props.isWeakSound && this.state.ablePlayNetweakAudio) {
2691
+ this.state.ablePlayNetweakAudio = false;
2692
+ let src = networkWeakAudio
2693
+ let audio = new Audio(src)
2694
+ audio.play()
2695
+ setTimeout(() => {
2696
+ this.state.ablePlayNetweakAudio = true;
2697
+ }, 30000);
2698
+ }
2699
+ if (this.props.OnNetworkWeak) {
2700
+ this.props.OnNetworkWeak(bpsSend, bpsRecv, sid)
2701
+ }
2702
+ }
2703
+ })
2704
+
2367
2705
  }
2368
2706
  };
2369
2707
  // 开始服务端录制成功
2370
- this.test_controller.OnStartRemoteRecordSucc = (record_id) => {
2371
- console.log('开始服务端录制成功', record_id);
2372
- this.state.recordId = record_id
2373
- this.videoRecordCallback('1', true)
2374
- this.saveLog('mrtc OnStartRemoteRecordSucc')
2708
+ this.test_controller.OnStartRemoteRecordSucc = (record_id, record_third_id) => {
2709
+ console.log('开始服务端录制成功', record_id, record_third_id);
2710
+ if (!record_third_id) {
2711
+ // 全局录制
2712
+ this.state.recordId = record_id
2713
+ this.videoRecordCallback('1', true)
2714
+ this.saveLog('mrtc OnStartRemoteRecordSucc')
2715
+ } else {
2716
+ // 业务录制
2717
+ this.state.businessRecordId = record_id
2718
+ this.businessRecordCallback('1', true, record_third_id)
2719
+ this.saveLog('mrtc OnStartRemoteBusinessRecordSucc, businessId=' + record_third_id)
2720
+ }
2721
+
2722
+ if (this.state.isRecordingeErrorModalVisible) {
2723
+ this.setState({
2724
+ isRecordingeErrorModalVisible: false
2725
+ })
2726
+ }
2375
2727
  };
2376
2728
  // 开始服务端录制失败
2377
2729
  this.test_controller.OnStartRemoteRecordFailed = (
2378
2730
  record_id,
2379
2731
  err_code,
2380
- err_msg
2732
+ err_msg,
2733
+ record_third_id
2381
2734
  ) => {
2382
- this.videoRecordCallback('1', false)
2383
- console.log('开始服务端录制失败', record_id, err_code, err_msg)
2384
- this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2735
+ console.log('开始服务端录制失败', record_id, err_code, err_msg, record_third_id)
2736
+ if (!record_third_id) {
2737
+ this.videoRecordCallback('1', false)
2738
+ this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2739
+ } else {
2740
+ this.businessRecordCallback('1', false, record_third_id)
2741
+ this.saveLog('mrtc OnStartRemoteBusinessRecordFailed, code='+err_code + ',businessId=' + record_third_id)
2742
+ }
2385
2743
  };
2386
2744
  // 结束服务端录制成功
2387
- this.test_controller.OnStopRemoteRecordSucc = (recordId) => {
2388
- console.log('结束服务端录制成功', recordId);
2389
- this.videoRecordCallback('2', true)
2390
- this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2391
- // this.endSessionValue()
2745
+ this.test_controller.OnStopRemoteRecordSucc = (recordId, record_third_id) => {
2746
+ console.log('结束服务端录制成功', recordId, record_third_id);
2747
+ if (!record_third_id) {
2748
+ this.videoRecordCallback('2', true)
2749
+ this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2750
+ this.state.recordId = '';
2751
+ } else {
2752
+ this.businessRecordCallback('2', true, record_third_id)
2753
+ this.saveLog('mrtc OnStopRemoteBusinessRecordSucc, recordId='+recordId + ',businessId=' + record_third_id)
2754
+ this.state.businessRecordId = '';
2755
+ }
2392
2756
  // 获取服务端录制结果
2393
2757
  };
2394
2758
  // 结束服务端录制失败
2395
2759
  this.test_controller.OnStopRemoteRecordFailed = (
2396
2760
  recordId,
2397
2761
  err_code,
2398
- err_msg
2762
+ err_msg,
2763
+ record_third_id
2399
2764
  ) => {
2400
- this.videoRecordCallback('2', false)
2401
- console.log('结束服务端录制失败', recordId, err_code, err_msg)
2402
- this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2765
+ console.log('结束服务端录制失败', recordId, err_code, err_msg, record_third_id)
2766
+ if (!record_third_id) {
2767
+ this.videoRecordCallback('2', false)
2768
+ this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2769
+ } else {
2770
+ this.businessRecordCallback('2', false, record_third_id)
2771
+ this.saveLog('mrtc OnStopRemoteBusinessRecordFailed, err_code='+err_code+',businessId=' + record_third_id)
2772
+ }
2773
+
2403
2774
  };
2404
2775
  // 开启浏览器录制成功
2405
2776
  this.test_controller.OnClientStartRecordSuccess = (
@@ -2522,6 +2893,23 @@ class Video extends Component {
2522
2893
  ) => {
2523
2894
  console.log('下载失败', clientRecordId, code, msg)
2524
2895
  };
2896
+ // 日志上传成功
2897
+ this.test_controller.OnUploadLogSucc = (filePath) => {
2898
+ // const filePath = 'https://mpaas.oss-cn-hk-hsbc-d01-a.ali-ops.cloud.cn.hsbc/log/0E6C7637D9A53DF38D4CFC614EC8915C_41B8EEB302057/wmzTeller_681269134338102_1681269140267_1.log?Expires=1681269740&OSSAccessKeyId=Cq0vGDNN7WQeyn8n&Signature=avYEdwRSdblKIY7LhB6FzwpPAD8%3D'
2899
+
2900
+ console.info('OnUploadLogSucc', filePath)
2901
+ this.saveLog('mrtc OnUploadLogSucc, filePath=' + filePath)
2902
+
2903
+ // const exp1 = /.+\.log/g
2904
+ // const url = filePath.match(exp1)[0]
2905
+ // console.log(url)
2906
+ this.uploadLogCallback(filePath)
2907
+ };
2908
+ this.test_controller.OnUploadLogFail = (code, err_msg) => {
2909
+ // test_controller.trace(`upload log failed, err_code=${code}, err_msg=${JSON.stringify(err_msg)}`);
2910
+ console.info('OnUploadLogFail', code, err_msg)
2911
+ this.saveLog('mrtc OnUploadLogFail, code=' + code, ',msg=' + err_msg)
2912
+ };
2525
2913
  // 切流成功通知
2526
2914
  this.test_controller.OnChangeMediaStreamSuccess = (sid) => {
2527
2915
  console.log('切流成功通知', sid);
@@ -2682,7 +3070,7 @@ class Video extends Component {
2682
3070
  }
2683
3071
  // 停止共享
2684
3072
  this.test_controller.OnDesktopDisplayClosed = () => {
2685
- console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen)
3073
+ console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen, streamShare)
2686
3074
 
2687
3075
  if (this.state.isScreenSwitching) {
2688
3076
  this.state.isScreenSwitching = false
@@ -2841,12 +3229,24 @@ class Video extends Component {
2841
3229
  // duration: 10
2842
3230
  })
2843
3231
  }
3232
+ // 全局录制
2844
3233
  videoRecordCallback = async (type, status) => {
3234
+ if (status) {
3235
+ // 全局录制且开启成功,通知app
3236
+ this.sendMessage({
3237
+ 'typeId': 1030,
3238
+ 'type': type,
3239
+ 'sessionId': this.state.sessionId,
3240
+ 'recordId': this.state.recordId
3241
+ })
3242
+ }
2845
3243
  try {
2846
3244
  let result = await API.videoRecordCallback({
2847
3245
  activityId: this.props.businessNumber,
2848
3246
  sessionId: this.state.sessionId,
2849
3247
  roomId: this.state.channelId + '',
3248
+ appId: this.state.appId,
3249
+ recordId: this.state.recordId,
2850
3250
  type: type,
2851
3251
  status: status
2852
3252
  });
@@ -2857,6 +3257,51 @@ class Video extends Component {
2857
3257
  }
2858
3258
  }
2859
3259
  }
3260
+ // 业务录制回调
3261
+ businessRecordCallback = async (type, status, businessId) => {
3262
+ if (status) {
3263
+ this.sendMessage({
3264
+ 'typeId': 1031,
3265
+ 'type': type,
3266
+ 'id': businessId,
3267
+ 'sessionId': this.state.sessionId,
3268
+ 'recordId': this.state.recordId,
3269
+ 'businessRecordId': this.state.businessRecordId
3270
+ })
3271
+ }
3272
+ try {
3273
+ let result = await API.videoRecordCallback({
3274
+ activityId: this.props.businessNumber,
3275
+ sessionId: this.state.sessionId,
3276
+ roomId: this.state.channelId + '',
3277
+ id: businessId,
3278
+ appId: this.state.appId,
3279
+ recordId: this.state.businessRecordId,
3280
+ type: type,
3281
+ status: status
3282
+ });
3283
+ console.log(result);
3284
+ } catch (err) {
3285
+ console.error(err);
3286
+ if (err.status == 502 || err.status == 404) {
3287
+ }
3288
+ }
3289
+ }
3290
+ uploadLogCallback = async (url) => {
3291
+ try {
3292
+ let result = await API.uploadLogCallback({
3293
+ activityId: this.props.businessNumber,
3294
+ sessionId: this.state.sessionId,
3295
+ roomId: this.state.channelId + '',
3296
+ tellerAccount: this.props.tellerAccount,
3297
+ fileUrl: url
3298
+ });
3299
+ } catch (err) {
3300
+ // console.error(err);
3301
+ if (err.status == 502 || err.status == 404) {
3302
+ }
3303
+ }
3304
+ }
2860
3305
  // 保存mettingInfo
2861
3306
  updateMeetingInfo = async () => {
2862
3307
  let customers
@@ -2925,6 +3370,9 @@ class Video extends Component {
2925
3370
  this.asr_controller.Disconnect()
2926
3371
  }
2927
3372
  message.destroy()
3373
+ clearInterval(this.state.drawCanvasInterval)
3374
+ clearInterval(this.state.faceDetectionTimer);
3375
+ clearInterval(this.state.imageDetectionTimer);
2928
3376
  }
2929
3377
  finishSession = () => {
2930
3378
  // clearInterval(this.state.OnVolumeAnalyserMap.get(sid))
@@ -3042,42 +3490,50 @@ class Video extends Component {
3042
3490
 
3043
3491
  }
3044
3492
  addToScriptClick = () => {
3493
+ let params = `?v=${SDK_VERISON}`
3045
3494
  const _dependScripts = [
3046
- // 'http://121.196.19.70/download/asr_api.js',
3047
- // 'http://121.196.19.70/download/reconnecting-websocket.min.js',
3048
- // 'http://121.196.19.70/download/resampler.js',
3049
- this.props.resourcePath + "/asr_api.js",
3050
- this.props.resourcePath + "/reconnecting-websocket.min.js",
3051
- this.props.resourcePath + "/resampler.js",
3052
- this.props.resourcePath + "/beauty/beauty_frame_pkg.js",
3053
- this.props.resourcePath + "/adapter.js",
3054
- this.props.resourcePath + "/getMediaInfo.js",
3055
- this.props.resourcePath + "/EBML.js",
3056
- this.props.resourcePath + "/mcu.js",
3057
- this.props.resourcePath + "/meeting_desk_stream.js",
3058
- this.props.resourcePath + "/meeting_html_stream.js",
3059
- this.props.resourcePath + "/meeting_file_stream.js",
3060
- this.props.resourcePath + "/meeting_im.js",
3061
- this.props.resourcePath + "/meeting_vod.js",
3062
- this.props.resourcePath + "/meeting_invite.js",
3063
- this.props.resourcePath + "/client_record.js",
3064
- this.props.resourcePath + "/remote_record.js",
3065
- this.props.resourcePath + "/meeting_camera_stream.js",
3066
- this.props.resourcePath + "/meeting_api.js",
3067
-
3068
- this.props.resourcePath + "/eruda.js",
3069
- this.props.resourcePath + "/iconfont.js",
3070
- this.props.resourcePath + "/html2canvas.js",
3071
- this.props.resourcePath + "/dom-to-image.js",
3072
-
3073
- this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js",
3074
- this.props.resourcePath + "/hs/hs_human_segmentation.js",
3075
- this.props.resourcePath + "/hs/hs_human_segmentation.wasm",
3076
-
3077
- this.props.resourcePath + "/mix/mix_frame.js",
3078
- this.props.resourcePath + "/mix/pageBoard.js"
3495
+ // this.props.resourcePath + "/opencv.js" + params,
3496
+ this.props.resourcePath + "/asr_api.js" + params,
3497
+ this.props.resourcePath + "/reconnecting-websocket.min.js" + params,
3498
+ this.props.resourcePath + "/resampler.js" + params,
3499
+ this.props.resourcePath + "/beauty/beauty_frame_pkg.js" + params,
3500
+ this.props.resourcePath + "/adapter.js" + params,
3501
+ this.props.resourcePath + "/getMediaInfo.js" + params,
3502
+ this.props.resourcePath + "/EBML.js" + params,
3503
+ this.props.resourcePath + "/mcu.js" + params,
3504
+ this.props.resourcePath + "/meeting_desk_stream.js" + params,
3505
+ this.props.resourcePath + "/meeting_html_stream.js" + params,
3506
+ this.props.resourcePath + "/meeting_file_stream.js" + params,
3507
+ this.props.resourcePath + "/meeting_im.js" + params,
3508
+ this.props.resourcePath + "/meeting_vod.js" + params,
3509
+ this.props.resourcePath + "/meeting_invite.js" + params,
3510
+ this.props.resourcePath + "/client_record.js" + params,
3511
+ this.props.resourcePath + "/remote_record.js" + params,
3512
+ this.props.resourcePath + "/meeting_camera_stream.js" + params,
3513
+ this.props.resourcePath + "/meeting_api.js" + params,
3514
+
3515
+ this.props.resourcePath + "/eruda.js" + params,
3516
+ this.props.resourcePath + "/iconfont.js" + params,
3517
+ this.props.resourcePath + "/html2canvas.js" + params,
3518
+ this.props.resourcePath + "/dom-to-image.js" + params,
3519
+
3520
+ this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js" + params,
3521
+ this.props.resourcePath + "/hs/hs_human_segmentation.js" + params,
3522
+ this.props.resourcePath + "/hs/hs_human_segmentation.wasm" + params,
3523
+
3524
+ this.props.resourcePath + "/mix/mix_frame.js" + params,
3525
+ this.props.resourcePath + "/mix/pageBoard.js" + params,
3079
3526
 
3080
3527
  ]
3528
+ try{
3529
+ if (!cv){
3530
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3531
+ }
3532
+ } catch(err) {
3533
+ console.log(err)
3534
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3535
+ }
3536
+
3081
3537
  const that = this
3082
3538
  let i = 0
3083
3539
  scriptAdd()
@@ -3092,14 +3548,14 @@ class Video extends Component {
3092
3548
  if (document.all) { //如果是IE
3093
3549
  script.onreadystatechange = () => {
3094
3550
  if (script.readyState == 'loaded' || script.readyState == 'complete') {
3095
- that.test_controller = new McuController();
3551
+ that.test_controller = new MeetingController();
3096
3552
  that.asr_controller = new AsrController()
3097
3553
  that.mountClick()
3098
3554
  }
3099
3555
  }
3100
3556
  } else {
3101
3557
  script.onload = () => {
3102
- that.test_controller = new McuController();
3558
+ that.test_controller = new MeetingController();
3103
3559
  that.asr_controller = new AsrController()
3104
3560
  that.mountClick()
3105
3561
  }
@@ -3123,7 +3579,17 @@ class Video extends Component {
3123
3579
  }
3124
3580
  }
3125
3581
  componentWillMount() {
3126
- console.log('hsbc_teller_sdk', '2.0.7')
3582
+ console.log('hsbc_teller_sdk', SDK_VERISON)
3583
+ // window.document.startRecord = () => {
3584
+ // this.enableServerRecording();
3585
+ // }
3586
+ // window.document.stopRecord = (recordId) => {
3587
+ // this.test_controller.StopRemoteRecord(recordId || this.state.recordId)
3588
+ // }
3589
+ // window.document.detectNetworkWeak = () => {
3590
+ // console.log('detectNetworkWeak')
3591
+ // this.test_controller.detectNetworkWeak()
3592
+ // }
3127
3593
  let arr = []
3128
3594
  for(let i=1;i<=12;i++){
3129
3595
  arr.push({
@@ -3137,6 +3603,18 @@ class Video extends Component {
3137
3603
  }
3138
3604
  this.setState({
3139
3605
  videoList: arr
3606
+ }, () => {
3607
+ // 设置播放回调
3608
+ for(let i=1;i<=12;i++){
3609
+ let dom = document.getElementById('video'+ i)
3610
+ dom.addEventListener("loadedmetadata", (event) => {
3611
+ console.log('video'+ i +' loadedmetadata:' + dom.srcObject.id)
3612
+ this.saveLog('video'+ i +' loadedmetadata, id=' + dom.srcObject.id)
3613
+ // let arrItem = this.state.videoList.find(el => el.idIndex == i) || {}
3614
+ // console.log(arrItem.videoName)
3615
+
3616
+ });
3617
+ }
3140
3618
  })
3141
3619
  if (this.props.sessionId) {
3142
3620
  this.getRoomStatus({
@@ -3162,6 +3640,7 @@ class Video extends Component {
3162
3640
  sid = document.getElementById('publish_streamId1').name
3163
3641
  }
3164
3642
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3643
+ this.saveVideoPoint('mute', 'RM端静音')
3165
3644
  this.sendMessage({
3166
3645
  'typeId': 1013,
3167
3646
  'muteStatus': 1,
@@ -3183,6 +3662,7 @@ class Video extends Component {
3183
3662
  sid = document.getElementById('publish_streamId1').name
3184
3663
  }
3185
3664
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3665
+ this.saveVideoPoint('mute', 'RM端解除静音')
3186
3666
  this.sendMessage({
3187
3667
  'typeId': 1013,
3188
3668
  'muteStatus': 0,
@@ -3192,6 +3672,11 @@ class Video extends Component {
3192
3672
  }
3193
3673
  })
3194
3674
  }
3675
+ if (this.state.isPictureInPicture) {
3676
+ setTimeout(() => {
3677
+ this.pictureInPicture('Refresh')
3678
+ }, 0);
3679
+ }
3195
3680
  }
3196
3681
  };
3197
3682
  isFileSuccuse = () => {
@@ -3252,30 +3737,58 @@ class Video extends Component {
3252
3737
  streamShare = ''
3253
3738
  }
3254
3739
  if (this.state.isSharedScreen) {
3255
- const publish_config = {}
3740
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3741
+ setTimeout(() => {
3256
3742
  publish_config.media_type = 1
3257
3743
  publish_config.publish_device = 2
3744
+ publish_config.need_volume_analyser = true
3258
3745
  publish_config.video_profile_type = 1
3259
- // publish_config.video_profile_type=100
3260
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3746
+ publish_config.desktopStreamToCanvas = false
3261
3747
  publish_config.enableDesktopAudio = true
3262
3748
  publish_config.degradationType = 2
3263
- publish_config.desktopStreamToCanvas = false
3264
- publish_config.sid = document.getElementById('video20').name
3265
- this.test_controller.ChangeMediaStream(publish_config)
3266
- this.state.isScreenSwitching = true
3749
+ publish_config.publish_video_id = 'video20'
3750
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3751
+ publish_config.publish_tag = 'projectionWhiteboard'
3752
+ this.test_controller.Publish(publish_config)
3753
+ }, 300);
3754
+ // const publish_config = {}
3755
+ // publish_config.media_type = 1
3756
+ // publish_config.publish_device = 2
3757
+ // publish_config.video_profile_type = 1
3758
+ // // publish_config.video_profile_type=100
3759
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3760
+ // publish_config.enableDesktopAudio = true
3761
+ // publish_config.degradationType = 2
3762
+ // publish_config.desktopStreamToCanvas = false
3763
+ // publish_config.sid = document.getElementById('video20').name
3764
+ // this.test_controller.ChangeMediaStream(publish_config)
3765
+ // this.state.isScreenSwitching = true
3267
3766
  } else {
3268
3767
  if (document.getElementById('video20').name) {
3269
- publish_config.media_type = 1;
3270
- publish_config.publish_device = 2;
3271
- publish_config.video_profile_type = 1
3272
- // publish_config.video_profile_type=100
3273
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3274
- publish_config.enableDesktopAudio = true
3275
- publish_config.desktopStreamToCanvas = false
3276
- publish_config.degradationType = 2
3277
- publish_config.sid = document.getElementById('video20').name;
3278
- this.test_controller.ChangeMediaStream(publish_config);
3768
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3769
+ setTimeout(() => {
3770
+ publish_config.media_type = 1
3771
+ publish_config.publish_device = 2
3772
+ publish_config.need_volume_analyser = true
3773
+ publish_config.video_profile_type = 1
3774
+ publish_config.desktopStreamToCanvas = false
3775
+ publish_config.enableDesktopAudio = true
3776
+ publish_config.degradationType = 2
3777
+ publish_config.publish_video_id = 'video20'
3778
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3779
+ publish_config.publish_tag = 'projectionWhiteboard'
3780
+ this.test_controller.Publish(publish_config)
3781
+ }, 300);
3782
+ // publish_config.media_type = 1;
3783
+ // publish_config.publish_device = 2;
3784
+ // publish_config.video_profile_type = 1
3785
+ // // publish_config.video_profile_type=100
3786
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3787
+ // publish_config.enableDesktopAudio = true
3788
+ // publish_config.desktopStreamToCanvas = false
3789
+ // publish_config.degradationType = 2
3790
+ // publish_config.sid = document.getElementById('video20').name;
3791
+ // this.test_controller.ChangeMediaStream(publish_config);
3279
3792
  } else {
3280
3793
  publish_config.media_type = 1
3281
3794
  publish_config.publish_device = 2
@@ -3354,9 +3867,11 @@ class Video extends Component {
3354
3867
  sid = document.getElementById('publish_streamId1').name
3355
3868
  }
3356
3869
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10))
3870
+ this.saveVideoPoint('mute', 'RM端静音')
3357
3871
  } else {
3358
3872
  // 当前是
3359
3873
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3874
+ this.saveVideoPoint('mute', 'RM端解除静音')
3360
3875
  this.setState({
3361
3876
  voiceImg: voiceImgOpen,
3362
3877
  voiceName: '静音'
@@ -3375,6 +3890,17 @@ class Video extends Component {
3375
3890
  }
3376
3891
 
3377
3892
  };
3893
+ handleOkPictureConfirm = () => {
3894
+ this.pictureInPictureClick('add')
3895
+ this.setState({isPictureConfirmModalVisible: false})
3896
+ }
3897
+ handleOkRecordConfirm = () => {
3898
+ if (!this.state.isPictureInPicture) {
3899
+ this.pictureInPicture()
3900
+ }
3901
+ this.saveLog('Start recording')
3902
+ this.enableServerRecording()
3903
+ }
3378
3904
  handleOk = () => {
3379
3905
  // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
3380
3906
  this.sendMessage({
@@ -3399,7 +3925,7 @@ class Video extends Component {
3399
3925
  sid = document.getElementById('publish_streamId1').name
3400
3926
  }
3401
3927
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3402
- this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
3928
+ this.saveVideoPoint('mute', 'RM端静音')
3403
3929
  this.setState({
3404
3930
  isModalVisible: false
3405
3931
  })
@@ -3579,6 +4105,9 @@ class Video extends Component {
3579
4105
  // videoList: this.state.videoList
3580
4106
  // })
3581
4107
  this.videoListSort();
4108
+ if (this.state.isPictureInPicture) {
4109
+ this.pictureInPicture('Refresh')
4110
+ }
3582
4111
  } else {
3583
4112
  console.log('1')
3584
4113
  this.messageClick('保持信息失败', 'error')
@@ -3768,6 +4297,7 @@ class Video extends Component {
3768
4297
  })
3769
4298
  // this.messageClick('识别失败', 'error')
3770
4299
  this.errorCodeClick('ocr',result.code)
4300
+ this.saveLog('OCR failed, error code=' + result.code)
3771
4301
  }
3772
4302
  } catch (err) {
3773
4303
  this.setState({
@@ -3866,6 +4396,9 @@ class Video extends Component {
3866
4396
  // videoList: this.state.videoList
3867
4397
  // })
3868
4398
  this.videoListSort();
4399
+ if (this.state.isPictureInPicture) {
4400
+ this.pictureInPicture('Refresh')
4401
+ }
3869
4402
  } else {
3870
4403
  console.log('1')
3871
4404
  this.messageClick('保持信息失败', 'error')
@@ -4098,19 +4631,25 @@ class Video extends Component {
4098
4631
  }
4099
4632
  }
4100
4633
  sgsinImage = () => {
4101
- if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4102
- this.setState({
4103
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4104
- isFaceImage: true,
4105
- facialImgFront: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4106
- })
4107
- } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4108
- this.setState({
4109
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4110
- isFaceImage: true,
4111
- facialImgBack: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4112
- })
4113
- }
4634
+ const imgBase64 = this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png')
4635
+ // console.log(imgBase64)
4636
+
4637
+ compressImage(imgBase64, (compressedImg)=>{
4638
+ // console.log(compressedImg)
4639
+ if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4640
+ this.setState({
4641
+ facialImg: compressedImg,
4642
+ isFaceImage: true,
4643
+ facialImgFront: compressedImg,
4644
+ })
4645
+ } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4646
+ this.setState({
4647
+ facialImg: compressedImg,
4648
+ isFaceImage: true,
4649
+ facialImgBack: compressedImg,
4650
+ })
4651
+ }
4652
+ })
4114
4653
 
4115
4654
  }
4116
4655
  handleChangeOcr = (val) => {
@@ -4122,10 +4661,10 @@ class Video extends Component {
4122
4661
  })
4123
4662
  }
4124
4663
  componentWillReceiveProps(props) {
4125
- this.state.channelId = props.roomId,
4126
- this.state.rtoken = props.mtoken,
4127
- this.state.sessionId = props.sessionId,
4128
- this.state.imRoomId = props.imRoomId
4664
+ this.state.channelId = props.roomId || this.state.channelId
4665
+ this.state.rtoken = props.mtoken || this.state.rtoken
4666
+ this.state.sessionId = props.sessionId || this.state.sessionId
4667
+ this.state.imRoomId = props.imRoomId || this.state.imRoomId
4129
4668
  }
4130
4669
  appGetUsernameClick = async (userId) => {
4131
4670
  let data = ''
@@ -4273,6 +4812,21 @@ class Video extends Component {
4273
4812
  })
4274
4813
  }
4275
4814
  }
4815
+ changePdfRendering = () => {
4816
+ if (this.props.pdfRendering) {
4817
+ // 暂停绘制
4818
+ clearInterval(this.state.drawCanvasInterval)
4819
+ } else {
4820
+ // 继续绘制
4821
+ if (!this.drawFunction) {
4822
+ console.log('未开始远程签署')
4823
+ return
4824
+ }
4825
+ clearInterval(this.state.drawCanvasInterval)
4826
+ this.state.drawCanvasInterval = setInterval(this.drawFunction, 1000 / 20);
4827
+ }
4828
+
4829
+ }
4276
4830
  navigatorClick = () => {
4277
4831
  const that = this
4278
4832
  const publish_config = {};
@@ -4302,8 +4856,10 @@ class Video extends Component {
4302
4856
  canvas.width = 960;
4303
4857
  canvas.height = 540;
4304
4858
 
4305
-
4306
- videoMedia.addEventListener('play', (event) => {
4859
+ if (this.state.whiteboardPlayEvent) {
4860
+ videoMedia.removeEventListener('play', this.state.whiteboardPlayEvent)
4861
+ }
4862
+ this.state.whiteboardPlayEvent = (event) => {
4307
4863
  var $this = this; //cache
4308
4864
  if ($this.state.operateShow) {
4309
4865
  isGraffiti = false
@@ -4314,20 +4870,21 @@ class Video extends Component {
4314
4870
  canvas.width = this.state.whiteboardWidth
4315
4871
  }
4316
4872
  console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
4317
- loop()
4318
- function loop() {
4319
- if (!$this.paused && !$this.ended) {
4320
- // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4321
- cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4322
- // } else {
4323
- // cobj.fillStyle = 'rgb(0 0 0)'
4324
- // cobj.fillRect(0,0,960,540)
4325
- // }
4326
4873
 
4327
- setTimeout(loop, 1000 / 20); // drawing at 30fps
4328
- }
4874
+ if (this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
4875
+ $this.drawFunction = () => {
4876
+ if (!$this.paused && !$this.ended) {
4877
+ // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4878
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4879
+ // } else {
4880
+ // cobj.fillStyle = 'rgb(0 0 0)'
4881
+ // cobj.fillRect(0,0,960,540)
4882
+ // }
4883
+ }
4329
4884
  }
4330
4885
 
4886
+ this.state.drawCanvasInterval = setInterval($this.drawFunction , 1000/ 20);
4887
+
4331
4888
  if (document.getElementById('video20').name) {
4332
4889
  // 代表已经有了进行切流
4333
4890
  publish_config.publish_device = 5
@@ -4350,7 +4907,8 @@ class Video extends Component {
4350
4907
  publish_config.publish_tag = 'projectionWhiteboard'
4351
4908
  this.test_controller.Publish(publish_config)
4352
4909
  }
4353
- }, 0);
4910
+ }
4911
+ videoMedia.addEventListener('play', this.state.whiteboardPlayEvent);
4354
4912
  navigator.mediaDevices.getDisplayMedia({
4355
4913
  video: true,
4356
4914
  preferCurrentTab: true,
@@ -4382,13 +4940,34 @@ class Video extends Component {
4382
4940
  that.test_controller.UnPublish(document.getElementById('video20').name)
4383
4941
  }
4384
4942
  }
4943
+
4944
+ // 关闭当前共享屏幕
4945
+ document.getElementById('video20') && document.getElementById('video20').name ? this.test_controller.UnPublish(document.getElementById('video20').name) : ''
4946
+ that.state.isSharedScreen = false
4947
+ that.state.isScreenSwitching = false
4948
+ that.setState({
4949
+ screenName: '共享模式'
4950
+ });
4951
+ that.tabTitlesClick('RMScreen', 'delect')
4952
+
4385
4953
  }, error => {
4386
4954
  console.log("Unable to acquire screen capture", error);
4387
4955
  });
4388
4956
  }
4389
- // publishAllScreen = () => {
4390
-
4391
- // }
4957
+ publishRecorderDevice = () => {
4958
+ if (this.state.recorderDevice){
4959
+ let publish_config = {}
4960
+ publish_config.media_type = 3
4961
+ publish_config.publish_device = 1
4962
+ publish_config.videoSource = this.state.recorderDevice.actionid
4963
+ publish_config.video_profile_type = 100
4964
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
4965
+ publish_config.publish_video_id = 'publish_video_record_device'
4966
+ publish_config.publish_streamId_id = 'publish_streamId_record_device'
4967
+ publish_config.publish_tag = 'sharedScreen'
4968
+ this.test_controller.Publish(publish_config)
4969
+ }
4970
+ }
4392
4971
  publishAllScreen = () => {
4393
4972
  const that = this
4394
4973
  const publish_config = {};
@@ -4661,6 +5240,7 @@ class Video extends Component {
4661
5240
  jsHeapSizeLimit: '未知', // 上下文内可用堆的最大体积
4662
5241
  totalJSHeapSize: '未知', // 已分配的堆体积
4663
5242
  usedJSHeapSize: '未知', // 当前 JS 堆活跃段(segment)的体积
5243
+ lightResult: this.state.envInfo? this.state.envInfo.lightResult : '未知'
4664
5244
  }
4665
5245
 
4666
5246
  if (navigator) {
@@ -4694,8 +5274,12 @@ class Video extends Component {
4694
5274
  // console.log(`有效网络连接类型: ${effectiveType}`);
4695
5275
  // console.log(`估算的下行速度/带宽: ${downlink}Mb/s`);
4696
5276
  // console.log(`估算的往返时间: ${rtt}ms`);
4697
- if (!window.navigator.onLine) {envInfo.networkInfo = ''}
4698
- else envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5277
+ if (!window.navigator.onLine) {
5278
+ envInfo.networkInfo = ''}
5279
+ else {
5280
+ envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5281
+ envInfo.networkResult = downlink > 0.2? '合格': '不合格'
5282
+ }
4699
5283
  }
4700
5284
  setNetworkInfo()
4701
5285
  navigator.connection.removeEventListener('change', self.envDetection);
@@ -4725,7 +5309,8 @@ class Video extends Component {
4725
5309
  // console.log('当前 JS 堆活跃段(segment)的体积', envInfo.usedJSHeapSize)
4726
5310
  envInfo.memoryResult = '合格'
4727
5311
  }
4728
-
5312
+ // 背景曝光环境检测
5313
+ this.lightDetect()
4729
5314
 
4730
5315
  this.setState({
4731
5316
  // isModalVisibleEnvironment: true,
@@ -4736,6 +5321,9 @@ class Video extends Component {
4736
5321
  this.setState({
4737
5322
  isModalVisibleEnvironment: false,
4738
5323
  })
5324
+ if (!this.state.isPictureInPicture) {
5325
+ this.pictureInPicture()
5326
+ }
4739
5327
  }
4740
5328
  // handleCancelEnvDetection = () => {
4741
5329
  // this.setState({
@@ -4787,16 +5375,39 @@ class Video extends Component {
4787
5375
  this.setState({
4788
5376
  beautyName: '开启美颜'
4789
5377
  })
5378
+ beautyMode = 'none'
4790
5379
  beautySetMode('none')
5380
+ beautyStop()
5381
+ if(!isSuccuseHs) {
5382
+ stopHs()
5383
+ }
4791
5384
  } else {
4792
5385
  this.state.beautyType = true
5386
+ beautyMode = 'beauty'
4793
5387
  beautySetMode('beauty')
4794
5388
  this.setState({
4795
5389
  beautyName: '关闭美颜'
4796
5390
  })
4797
5391
  }
5392
+ this.changeMediaStream();
4798
5393
 
4799
5394
  }
5395
+ changeMediaStream = () => {
5396
+ let publish_config = {}
5397
+ publish_config.sid = document.getElementById('publish_video1').name
5398
+ publish_config.media_type = 1
5399
+ publish_config.publish_device = 1
5400
+ // publish_config.videoSource = this.state.cameraValue
5401
+ // publish_config.audioSource = this.state.microphoneValue
5402
+ publish_config.need_volume_analyser = true
5403
+ publish_config.video_profile_type = 100
5404
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
5405
+ // publish_config.publish_video_id = 'publish_video1'
5406
+ // publish_config.publish_streamId_id = 'publish_streamId1'
5407
+ // publish_config.publish_tag = 'tag1'
5408
+ this.test_controller.ChangeMediaStream(publish_config)
5409
+ }
5410
+
4800
5411
  componentDidMount() {
4801
5412
  var box = document.getElementById("whiteboardDIV");
4802
5413
  var box1 = document.getElementById("operate")
@@ -4909,11 +5520,18 @@ class Video extends Component {
4909
5520
  if (!isSuccuseHs) {
4910
5521
 
4911
5522
  hsSetMode('blur')
5523
+ hsMode = 'blur'
4912
5524
  isSuccuseHs = true
4913
5525
  } else {
4914
5526
  hsSetMode('none')
5527
+ hsMode = 'none'
4915
5528
  isSuccuseHs = false
5529
+ stopHs()
5530
+ if(!this.state.beautyType) {
5531
+ beautyStop()
5532
+ }
4916
5533
  }
5534
+ this.changeMediaStream();
4917
5535
  }
4918
5536
  virtualization = () => {
4919
5537
  this.virtualizationClick()
@@ -4940,6 +5558,17 @@ class Video extends Component {
4940
5558
  return false;
4941
5559
  }
4942
5560
  }
5561
+ isHKPassValidTime=(value)=>{
5562
+ if (!value.split('.') || value.split('.').length < 3 || value.split('.').some(el => el == '')) return false;
5563
+ let start = new Date('2020.01.01').valueOf();
5564
+ let end = new Date('2023.12.31').valueOf();
5565
+ var time = new Date(value).valueOf();
5566
+ if(start<=time && end >= time ){
5567
+ return true;
5568
+ }else{
5569
+ return false;
5570
+ }
5571
+ }
4943
5572
  handleChangeCertificateValidity = (event) => {
4944
5573
  // 护照只有起始日期,单独处理
4945
5574
  if (this.state.documentType == 'PASSPORT_CARD' && event.target.value.split('.').length >2) {
@@ -4960,6 +5589,12 @@ class Video extends Component {
4960
5589
  certificateValidity: event.target.value,
4961
5590
  certificateValidityType: true
4962
5591
  });
5592
+ } else if (this.state.documentType == 'HK_MO_PASS_CARD' && this.isHKPassValidTime(event.target.value.split('-')[1])){
5593
+ // 疫情政策对港澳来往通行证放宽限制,有效期限从2020.1.1到2023.12.31都算有效
5594
+ this.setState({
5595
+ certificateValidity: event.target.value,
5596
+ certificateValidityType: true
5597
+ });
4963
5598
  } else {
4964
5599
  this.setState({
4965
5600
  certificateValidity: event.target.value,
@@ -4974,6 +5609,9 @@ class Video extends Component {
4974
5609
  if (this.props.shareMask != prevProps.shareMask) {
4975
5610
  this.sendNotification()
4976
5611
  }
5612
+ if (this.props.pdfRendering != prevProps.pdfRendering) {
5613
+ this.changePdfRendering()
5614
+ }
4977
5615
  }
4978
5616
  onChangeOCRCustomer = (e) => {
4979
5617
  console.log(e)
@@ -5074,8 +5712,10 @@ class Video extends Component {
5074
5712
 
5075
5713
  }))
5076
5714
  }
5077
-
5078
-
5715
+ this.setState({
5716
+ documentError: '',
5717
+ isModalVisibleCustomer: false,
5718
+ })
5079
5719
  }
5080
5720
  })
5081
5721
  // this.customerFaceClick(this.state.customerList[this.state.customerSelect])
@@ -5524,7 +6164,7 @@ class Video extends Component {
5524
6164
  <audio id={'audio'+(item.idIndex)} autoPlay />
5525
6165
  <label style={{ display: 'none' }} id={'feedId'+(item.idIndex)} type="text" />
5526
6166
 
5527
- <div style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
6167
+ <div onClick={this.muteOpposite.bind(this, 'video'+(item.idIndex))} style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
5528
6168
  {
5529
6169
  item.mute && <img
5530
6170
  alt=""
@@ -5591,6 +6231,23 @@ class Video extends Component {
5591
6231
  !this.state.isSuspend && <span>确定是否暂停会话?</span>
5592
6232
  }
5593
6233
  </Modal>
6234
+ {/* 画中画重新开启确认 */}
6235
+ <Modal closable={false} centered={true} visible={this.state.isPictureConfirmModalVisible} maskClosable={false} footer={[
6236
+ <div key='end'>
6237
+ {/* <Button className="modelButtonCancel" onClick={()=> {this.setState({isPictureConfirmModalVisible: false})}}>取消</Button> */}
6238
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkPictureConfirm}>确定</Button>
6239
+ </div>
6240
+ ]}>
6241
+ <div className='endModal'>画中画已关闭,请重新开启</div>
6242
+ </Modal>
6243
+ {/* 双录中断重新开启确认 */}
6244
+ <Modal closable={false} centered={true} visible={this.state.isRecordingeErrorModalVisible} maskClosable={false} footer={[
6245
+ <div key='end'>
6246
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkRecordConfirm}>确定</Button>
6247
+ </div>
6248
+ ]}>
6249
+ <div className='endModal'>双录异常中断,请重新开启</div>
6250
+ </Modal>
5594
6251
  {/* 是否退出会议*/}
5595
6252
  <Modal closable={false} centered={true} visible={this.state.isModalVisibleEnd} maskClosable={false} footer={[
5596
6253
  <div key='end'>
@@ -5598,7 +6255,7 @@ class Video extends Component {
5598
6255
  <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnd}>确定</Button>
5599
6256
  </div>
5600
6257
  ]}>
5601
- <div className='endModal'>是否要结束并退出会议?</div>
6258
+ <div className='endModal'>{this.state.businessId? '正在进行业务录制,是否确认结束并退出会议?': '是否要结束并退出会议?'}</div>
5602
6259
  </Modal>
5603
6260
  {/* ocr及人脸 */}
5604
6261
  <Modal title={this.state.titleModal} width={800} closable={true} maskClosable={false} onCancel={this.handleCancelFacial} centered={true} visible={this.state.isModalVisibleFacial} footer={[
@@ -5941,22 +6598,26 @@ class Video extends Component {
5941
6598
  <Modal title="环境检测" maskClosable={false} width={650} closable={false} centered={true} visible={this.state.isModalVisibleEnvironment} footer={[
5942
6599
  <div key='env'>
5943
6600
  {/* <Button className="modelButtonCancel" onClick={this.handleCancelEnvDetection}>取消</Button> */}
5944
- <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnvDetection}>确定</Button>
6601
+ <Button className="modelButtonOk" type="primary" disabled={this.state.loading} danger onClick={this.handleOkEnvDetection}>确定</Button>
5945
6602
  </div>
5946
6603
  ]}>
5947
- <Collapse defaultActiveKey={['1', '2', '3', '4', '5']} ghost>
6604
+ <Collapse defaultActiveKey={['1', '2', '3', '4', '5', '6']} ghost>
5948
6605
 
5949
- <Panel header={'网络检测 - ' +this.state.envInfo.networkResult} key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
6606
+ <Panel header={<span>网络检测 - {this.state.envInfo.networkResult } {this.state.envInfo.networkResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6607
+ key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
5950
6608
  <p className='envClass'>网络状态:{this.state.envInfo.networkStatus}</p>
5951
6609
  {this.state.envInfo.networkInfo?<p className='envClass'>{this.state.envInfo.networkInfo}</p>:null}
5952
6610
  </Panel>
5953
- <Panel header={'设备电量 - ' +this.state.envInfo.batteryResult} key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
6611
+ <Panel header={<span>设备电量 - {this.state.envInfo.batteryResult} {this.state.envInfo.batteryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />} </span>}
6612
+ key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
5954
6613
  <p className='envClass'>电量:{this.state.envInfo.batteryLevel}({this.state.envInfo.batteryCharging})</p>
5955
6614
  </Panel>
5956
- <Panel header={'内存检测 - ' +this.state.envInfo.memoryResult} key="1" className={this.state.envInfo.memoryResult=='不合格'? 'panel-error':''}>
6615
+ <Panel header={<span>内存检测 - {this.state.envInfo.memoryResult} {this.state.envInfo.memoryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6616
+ key="1" className={this.state.envInfo.memoryResult=='不合格'? 'panel-error':''}>
5957
6617
  <p className='envClass'>最大可用内存:{this.state.envInfo.jsHeapSizeLimit} ;当前已使用:{this.state.envInfo.usedJSHeapSize} </p>
5958
6618
  </Panel>
5959
- <Panel header={'摄像头设备 - ' +this.state.envInfo.cameraResult} key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
6619
+ <Panel header={<span>摄像头设备 - {this.state.envInfo.cameraResult}{this.state.envInfo.cameraResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6620
+ key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
5960
6621
  <div >
5961
6622
  {
5962
6623
  this.state.cameraList.map((item, index) => {
@@ -5969,7 +6630,7 @@ class Video extends Component {
5969
6630
  {this.state.cameraList.length == 0 ? <p className="envClass">获取不到摄像头设备,请检查</p> : null}
5970
6631
  </div>
5971
6632
  </Panel>
5972
- <Panel header={'麦克风设备 - ' +this.state.envInfo.microResult} key="4" className={this.state.envInfo.microResult=='不合格'? 'panel-error':''}>
6633
+ <Panel header={<span>麦克风设备 - {this.state.envInfo.microResult} {this.state.envInfo.microResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>} key="4" className={this.state.envInfo.microResult=='不合格'? 'panel-error':''}>
5973
6634
  <div>
5974
6635
  {
5975
6636
  this.state.microphoneList.map((item, index) => {
@@ -5981,6 +6642,9 @@ class Video extends Component {
5981
6642
  {this.state.cameraList.length == 0 ? <p className="envClass">获取不到麦克风设备,请检查</p> : null}
5982
6643
  </div>
5983
6644
  </Panel>
6645
+ <Panel header={<span>背光、曝光 - {this.state.envInfo.lightResult} {this.state.envInfo.lightResult=='合格'? <img src={IconSuccess} />: <img src={IconFail} />}</span>} key="6" className={this.state.envInfo.lightResult=='合格'? '':'panel-error'}>
6646
+ <p className="envClass">{this.state.envInfo.lightResult=='合格'? '无过度背光、曝光':'过度背光、曝光'}</p>
6647
+ </Panel>
5984
6648
  </Collapse>
5985
6649
  </Modal>
5986
6650
  <video className="mixedvideo" id="mixedvideo" autoPlay muted={true} width="0" height="0"></video>
@@ -5989,6 +6653,7 @@ class Video extends Component {
5989
6653
 
5990
6654
  <video className="mixedvideo" id="recordvideo" autoPlay width="0" height="0"></video>
5991
6655
  <video className="mixedvideo" id="record_video" muted autoPlay></video>
6656
+ <video className="mixedvideo" id="publish_video_record_device" muted autoPlay></video>
5992
6657
 
5993
6658
  </Spin>
5994
6659
  </div>);
@@ -6023,10 +6688,18 @@ Video.defaultProps = {
6023
6688
  customers: ['--'],
6024
6689
  otherAttendees: undefined
6025
6690
  },
6691
+ pdfRendering: false,
6026
6692
  isTranscribing: false,
6027
6693
  shareMask: false,
6028
6694
  isOpenSound: false, // true开启进出音效 false不开启
6695
+ isWeakSound: false,
6029
6696
  userSide: 2,
6697
+ meetingDuration: null, // 会议时长,单位小时
6698
+ recordMode: 1, // 录制模式 1远程录制 2网点录制
6699
+ defaultBranchCode: "",// 员工网点缩写
6700
+ customerId: "", //客户号
6701
+ salesBranchCode: "", //网点编号(分行号)
6702
+ financialOffice: "", // 理财室
6030
6703
  logUrl: 'http://hsbc.cn-shanghai.log.aliyuncs.com/logstores/hsbc/track?APIVersion=0.6.0&app=meeting-ui',
6031
6704
  internalUrl: 'https://wp-staff-gateway.wealth-platform.uat.ali.cloud.cn.hsbc/meeting-ui/OHB/CN/HSBC?chnlID=OHB&locale=zh_CN&chnlCC=CN&chnlGMC=HSBC&targetFunc=supervisorMeeting&sourceFunc=rmMeeting'
6032
6705
  }