react_hsbc_teller 2.0.7 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.9'
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
 
@@ -321,6 +350,12 @@ class Video extends Component {
321
350
  staffId: this.props.tellerAccount,
322
351
  activityId: this.props.businessNumber,
323
352
  callbackUrl: this.props.callbackUrl,
353
+ meetingDuration: this.props.meetingDuration,
354
+ recordMode: this.props.recordMode,
355
+ defaultBranchCode: this.props.defaultBranchCode,
356
+ customerId: this.props.customerId,
357
+ salesBranchCode: this.props.salesBranchCode,
358
+ financialOffice: this.props.financialOffice,
324
359
  roomId: this.state.channelId,
325
360
  mtoken: this.state.rtoken,
326
361
  type: 2
@@ -345,6 +380,8 @@ class Video extends Component {
345
380
  this.test_controller.Publish(publish_config)
346
381
  })
347
382
  // this.publishAllScreen();
383
+ // 单独发布录制屏幕设备的流
384
+ this.publishRecorderDevice()
348
385
 
349
386
  this.props.createRoomCallback({
350
387
  type: 1,
@@ -497,37 +534,31 @@ class Video extends Component {
497
534
  {
498
535
  subscribe_video_id: 'video1',
499
536
  subscribe_audio_id: 'audio1',
500
- subscribe_streamId_id: 'subscribe_streamId1',
501
537
  feedId_id: 'feedId1'
502
538
  },
503
539
  {
504
540
  subscribe_video_id: 'video2',
505
541
  subscribe_audio_id: 'audio2',
506
- subscribe_streamId_id: 'subscribe_streamId2',
507
542
  feedId_id: 'feedId2'
508
543
  },
509
544
  {
510
545
  subscribe_video_id: 'video3',
511
546
  subscribe_audio_id: 'audio3',
512
- subscribe_streamId_id: 'subscribe_streamId3',
513
547
  feedId_id: 'feedId3'
514
548
  },
515
549
  {
516
550
  subscribe_video_id: 'video4',
517
551
  subscribe_audio_id: 'audio4',
518
- subscribe_streamId_id: 'subscribe_streamId4',
519
552
  feedId_id: 'feedId4'
520
553
  },
521
554
  {
522
555
  subscribe_video_id: 'video5',
523
556
  subscribe_audio_id: 'audio5',
524
- subscribe_streamId_id: 'subscribe_streamId5',
525
557
  feedId_id: 'feedId5'
526
558
  },
527
559
  {
528
560
  subscribe_video_id: 'video6',
529
561
  subscribe_audio_id: 'audio6',
530
- subscribe_streamId_id: 'subscribe_streamId6',
531
562
  feedId_id: 'feedId6'
532
563
  }
533
564
  ];
@@ -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({
@@ -2057,8 +2366,6 @@ class Video extends Component {
2057
2366
  config_param = {
2058
2367
  subscribe_video_id: 'video21',
2059
2368
  subscribe_audio_id: 'audio21',
2060
- subscribe_streamId_id: 'subscribe_streamId21',
2061
- feedId_id: 'feedId21',
2062
2369
  feedId: itemOne.feedId
2063
2370
  }
2064
2371
 
@@ -2072,8 +2379,6 @@ class Video extends Component {
2072
2379
  config_param = {
2073
2380
  subscribe_video_id: 'video20',
2074
2381
  subscribe_audio_id: 'audio20',
2075
- subscribe_streamId_id: 'subscribe_streamId20',
2076
- feedId_id: 'feedId20',
2077
2382
  feedId: itemOne.feedId
2078
2383
  }
2079
2384
 
@@ -2089,7 +2394,6 @@ class Video extends Component {
2089
2394
  config_param = {
2090
2395
  subscribe_video_id: 'video'+i,
2091
2396
  subscribe_audio_id: 'audio'+i,
2092
- subscribe_streamId_id: 'subscribe_streamId'+i,
2093
2397
  feedId_id: 'feedId'+i,
2094
2398
  feedId: itemOne.feedId
2095
2399
  }
@@ -2102,6 +2406,7 @@ class Video extends Component {
2102
2406
  console.log(config_param)
2103
2407
  console.log('发起订阅')
2104
2408
  this.test_controller.Subscribe(config_param)
2409
+ document.getElementById(config_param.subscribe_video_id).name = 'temp'
2105
2410
 
2106
2411
  }
2107
2412
  })
@@ -2119,6 +2424,10 @@ class Video extends Component {
2119
2424
  this.test_controller.OnNewPublish = (feed) => {
2120
2425
  console.log('有新发布者', feed);
2121
2426
  console.log(new Date())
2427
+ if (feed.tag && feed.tag.includes('UnSubscribe_RM')) {
2428
+ console.log('过滤订阅的tag:', feed.tag)
2429
+ return
2430
+ }
2122
2431
  this.sendMessage({
2123
2432
  'typeId': 1013,
2124
2433
  'muteStatus': this.state.voiceStatue ? 1 : 0,
@@ -2154,8 +2463,6 @@ class Video extends Component {
2154
2463
  config_param = {
2155
2464
  subscribe_video_id: 'video21',
2156
2465
  subscribe_audio_id: 'audio21',
2157
- subscribe_streamId_id: 'subscribe_streamId21',
2158
- feedId_id: 'feedId21',
2159
2466
  feedId: feed.feedId
2160
2467
  }
2161
2468
 
@@ -2175,8 +2482,6 @@ class Video extends Component {
2175
2482
  config_param = {
2176
2483
  subscribe_video_id: 'video20',
2177
2484
  subscribe_audio_id: 'audio20',
2178
- subscribe_streamId_id: 'subscribe_streamId20',
2179
- feedId_id: 'feedId20',
2180
2485
  feedId: feed.feedId
2181
2486
  }
2182
2487
 
@@ -2198,7 +2503,6 @@ class Video extends Component {
2198
2503
  config_param = {
2199
2504
  subscribe_video_id: 'video'+i,
2200
2505
  subscribe_audio_id: 'audio'+i,
2201
- subscribe_streamId_id: 'subscribe_streamId'+i,
2202
2506
  feedId_id: 'feedId'+i,
2203
2507
  feedId: feed.feedId
2204
2508
  }
@@ -2325,6 +2629,10 @@ class Video extends Component {
2325
2629
  // let audio = new Audio(src)
2326
2630
  // audio.play()
2327
2631
  // }
2632
+ if (participant.includes('UnHint')){
2633
+ console.log('过滤掉的uid', participant)
2634
+ return
2635
+ }
2328
2636
 
2329
2637
 
2330
2638
  this.appGetUsernameClick(participant).then((res) => {
@@ -2362,44 +2670,97 @@ class Video extends Component {
2362
2670
  this.test_controller.OnNetworkWeak = (bpsSend, bpsRecv, sid) => {
2363
2671
  console.log('弱网回调', bpsSend, bpsRecv, sid)
2364
2672
  if (sid == document.getElementById('publish_video1').name) {
2365
- this.messageClick('当前网络环境较差', 'error')
2366
- this.saveLog('mrtc OnNetworkWeak')
2673
+
2674
+ this.detectNetworkWeak().then((isWeak) => {
2675
+ console.log('弱网结果:' + isWeak)
2676
+ if (isWeak) {
2677
+ this.messageClick('当前网络环境较差', 'error')
2678
+ this.saveLog('mrtc OnNetworkWeak')
2679
+ this.saveVideoPoint('wnd', 'RM端弱网');
2680
+ if (this.props.isWeakSound && this.state.ablePlayNetweakAudio) {
2681
+ this.state.ablePlayNetweakAudio = false;
2682
+ let src = networkWeakAudio
2683
+ let audio = new Audio(src)
2684
+ audio.play()
2685
+ setTimeout(() => {
2686
+ this.state.ablePlayNetweakAudio = true;
2687
+ }, 30000);
2688
+ }
2689
+ if (this.props.OnNetworkWeak) {
2690
+ this.props.OnNetworkWeak(bpsSend, bpsRecv, sid)
2691
+ }
2692
+ }
2693
+ })
2694
+
2367
2695
  }
2368
2696
  };
2369
2697
  // 开始服务端录制成功
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')
2698
+ this.test_controller.OnStartRemoteRecordSucc = (record_id, record_third_id) => {
2699
+ console.log('开始服务端录制成功', record_id, record_third_id);
2700
+ if (!record_third_id) {
2701
+ // 全局录制
2702
+ this.state.recordId = record_id
2703
+ this.videoRecordCallback('1', true)
2704
+ this.saveLog('mrtc OnStartRemoteRecordSucc')
2705
+ } else {
2706
+ // 业务录制
2707
+ this.state.businessRecordId = record_id
2708
+ this.businessRecordCallback('1', true, record_third_id)
2709
+ this.saveLog('mrtc OnStartRemoteBusinessRecordSucc, businessId=' + record_third_id)
2710
+ }
2711
+
2712
+ if (this.state.isRecordingeErrorModalVisible) {
2713
+ this.setState({
2714
+ isRecordingeErrorModalVisible: false
2715
+ })
2716
+ }
2375
2717
  };
2376
2718
  // 开始服务端录制失败
2377
2719
  this.test_controller.OnStartRemoteRecordFailed = (
2378
2720
  record_id,
2379
2721
  err_code,
2380
- err_msg
2722
+ err_msg,
2723
+ record_third_id
2381
2724
  ) => {
2382
- this.videoRecordCallback('1', false)
2383
- console.log('开始服务端录制失败', record_id, err_code, err_msg)
2384
- this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2725
+ console.log('开始服务端录制失败', record_id, err_code, err_msg, record_third_id)
2726
+ if (!record_third_id) {
2727
+ this.videoRecordCallback('1', false)
2728
+ this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2729
+ } else {
2730
+ this.businessRecordCallback('1', false, record_third_id)
2731
+ this.saveLog('mrtc OnStartRemoteBusinessRecordFailed, code='+err_code + ',businessId=' + record_third_id)
2732
+ }
2385
2733
  };
2386
2734
  // 结束服务端录制成功
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()
2735
+ this.test_controller.OnStopRemoteRecordSucc = (recordId, record_third_id) => {
2736
+ console.log('结束服务端录制成功', recordId, record_third_id);
2737
+ if (!record_third_id) {
2738
+ this.videoRecordCallback('2', true)
2739
+ this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2740
+ this.state.recordId = '';
2741
+ } else {
2742
+ this.businessRecordCallback('2', true, record_third_id)
2743
+ this.saveLog('mrtc OnStopRemoteBusinessRecordSucc, recordId='+recordId + ',businessId=' + record_third_id)
2744
+ this.state.businessRecordId = '';
2745
+ }
2392
2746
  // 获取服务端录制结果
2393
2747
  };
2394
2748
  // 结束服务端录制失败
2395
2749
  this.test_controller.OnStopRemoteRecordFailed = (
2396
2750
  recordId,
2397
2751
  err_code,
2398
- err_msg
2752
+ err_msg,
2753
+ record_third_id
2399
2754
  ) => {
2400
- this.videoRecordCallback('2', false)
2401
- console.log('结束服务端录制失败', recordId, err_code, err_msg)
2402
- this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2755
+ console.log('结束服务端录制失败', recordId, err_code, err_msg, record_third_id)
2756
+ if (!record_third_id) {
2757
+ this.videoRecordCallback('2', false)
2758
+ this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2759
+ } else {
2760
+ this.businessRecordCallback('2', false, record_third_id)
2761
+ this.saveLog('mrtc OnStopRemoteBusinessRecordFailed, err_code='+err_code+',businessId=' + record_third_id)
2762
+ }
2763
+
2403
2764
  };
2404
2765
  // 开启浏览器录制成功
2405
2766
  this.test_controller.OnClientStartRecordSuccess = (
@@ -2522,6 +2883,23 @@ class Video extends Component {
2522
2883
  ) => {
2523
2884
  console.log('下载失败', clientRecordId, code, msg)
2524
2885
  };
2886
+ // 日志上传成功
2887
+ this.test_controller.OnUploadLogSucc = (filePath) => {
2888
+ // 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'
2889
+
2890
+ console.info('OnUploadLogSucc', filePath)
2891
+ this.saveLog('mrtc OnUploadLogSucc, filePath=' + filePath)
2892
+
2893
+ // const exp1 = /.+\.log/g
2894
+ // const url = filePath.match(exp1)[0]
2895
+ // console.log(url)
2896
+ this.uploadLogCallback(filePath)
2897
+ };
2898
+ this.test_controller.OnUploadLogFail = (code, err_msg) => {
2899
+ // test_controller.trace(`upload log failed, err_code=${code}, err_msg=${JSON.stringify(err_msg)}`);
2900
+ console.info('OnUploadLogFail', code, err_msg)
2901
+ this.saveLog('mrtc OnUploadLogFail, code=' + code, ',msg=' + err_msg)
2902
+ };
2525
2903
  // 切流成功通知
2526
2904
  this.test_controller.OnChangeMediaStreamSuccess = (sid) => {
2527
2905
  console.log('切流成功通知', sid);
@@ -2682,7 +3060,7 @@ class Video extends Component {
2682
3060
  }
2683
3061
  // 停止共享
2684
3062
  this.test_controller.OnDesktopDisplayClosed = () => {
2685
- console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen)
3063
+ console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen, streamShare)
2686
3064
 
2687
3065
  if (this.state.isScreenSwitching) {
2688
3066
  this.state.isScreenSwitching = false
@@ -2841,12 +3219,24 @@ class Video extends Component {
2841
3219
  // duration: 10
2842
3220
  })
2843
3221
  }
3222
+ // 全局录制
2844
3223
  videoRecordCallback = async (type, status) => {
3224
+ if (status) {
3225
+ // 全局录制且开启成功,通知app
3226
+ this.sendMessage({
3227
+ 'typeId': 1030,
3228
+ 'type': type,
3229
+ 'sessionId': this.state.sessionId,
3230
+ 'recordId': this.state.recordId
3231
+ })
3232
+ }
2845
3233
  try {
2846
3234
  let result = await API.videoRecordCallback({
2847
3235
  activityId: this.props.businessNumber,
2848
3236
  sessionId: this.state.sessionId,
2849
3237
  roomId: this.state.channelId + '',
3238
+ appId: this.state.appId,
3239
+ recordId: this.state.recordId,
2850
3240
  type: type,
2851
3241
  status: status
2852
3242
  });
@@ -2857,6 +3247,51 @@ class Video extends Component {
2857
3247
  }
2858
3248
  }
2859
3249
  }
3250
+ // 业务录制回调
3251
+ businessRecordCallback = async (type, status, businessId) => {
3252
+ if (status) {
3253
+ this.sendMessage({
3254
+ 'typeId': 1031,
3255
+ 'type': type,
3256
+ 'id': businessId,
3257
+ 'sessionId': this.state.sessionId,
3258
+ 'recordId': this.state.recordId,
3259
+ 'businessRecordId': this.state.businessRecordId
3260
+ })
3261
+ }
3262
+ try {
3263
+ let result = await API.videoRecordCallback({
3264
+ activityId: this.props.businessNumber,
3265
+ sessionId: this.state.sessionId,
3266
+ roomId: this.state.channelId + '',
3267
+ id: businessId,
3268
+ appId: this.state.appId,
3269
+ recordId: this.state.businessRecordId,
3270
+ type: type,
3271
+ status: status
3272
+ });
3273
+ console.log(result);
3274
+ } catch (err) {
3275
+ console.error(err);
3276
+ if (err.status == 502 || err.status == 404) {
3277
+ }
3278
+ }
3279
+ }
3280
+ uploadLogCallback = async (url) => {
3281
+ try {
3282
+ let result = await API.uploadLogCallback({
3283
+ activityId: this.props.businessNumber,
3284
+ sessionId: this.state.sessionId,
3285
+ roomId: this.state.channelId + '',
3286
+ tellerAccount: this.props.tellerAccount,
3287
+ fileUrl: url
3288
+ });
3289
+ } catch (err) {
3290
+ // console.error(err);
3291
+ if (err.status == 502 || err.status == 404) {
3292
+ }
3293
+ }
3294
+ }
2860
3295
  // 保存mettingInfo
2861
3296
  updateMeetingInfo = async () => {
2862
3297
  let customers
@@ -2925,6 +3360,9 @@ class Video extends Component {
2925
3360
  this.asr_controller.Disconnect()
2926
3361
  }
2927
3362
  message.destroy()
3363
+ clearInterval(this.state.drawCanvasInterval)
3364
+ clearInterval(this.state.faceDetectionTimer);
3365
+ clearInterval(this.state.imageDetectionTimer);
2928
3366
  }
2929
3367
  finishSession = () => {
2930
3368
  // clearInterval(this.state.OnVolumeAnalyserMap.get(sid))
@@ -3042,42 +3480,50 @@ class Video extends Component {
3042
3480
 
3043
3481
  }
3044
3482
  addToScriptClick = () => {
3483
+ let params = `?v=${SDK_VERISON}`
3045
3484
  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"
3485
+ // this.props.resourcePath + "/opencv.js" + params,
3486
+ this.props.resourcePath + "/asr_api.js" + params,
3487
+ this.props.resourcePath + "/reconnecting-websocket.min.js" + params,
3488
+ this.props.resourcePath + "/resampler.js" + params,
3489
+ this.props.resourcePath + "/beauty/beauty_frame_pkg.js" + params,
3490
+ this.props.resourcePath + "/adapter.js" + params,
3491
+ this.props.resourcePath + "/getMediaInfo.js" + params,
3492
+ this.props.resourcePath + "/EBML.js" + params,
3493
+ this.props.resourcePath + "/mcu.js" + params,
3494
+ this.props.resourcePath + "/meeting_desk_stream.js" + params,
3495
+ this.props.resourcePath + "/meeting_html_stream.js" + params,
3496
+ this.props.resourcePath + "/meeting_file_stream.js" + params,
3497
+ this.props.resourcePath + "/meeting_im.js" + params,
3498
+ this.props.resourcePath + "/meeting_vod.js" + params,
3499
+ this.props.resourcePath + "/meeting_invite.js" + params,
3500
+ this.props.resourcePath + "/client_record.js" + params,
3501
+ this.props.resourcePath + "/remote_record.js" + params,
3502
+ this.props.resourcePath + "/meeting_camera_stream.js" + params,
3503
+ this.props.resourcePath + "/meeting_api.js" + params,
3504
+
3505
+ this.props.resourcePath + "/eruda.js" + params,
3506
+ this.props.resourcePath + "/iconfont.js" + params,
3507
+ this.props.resourcePath + "/html2canvas.js" + params,
3508
+ this.props.resourcePath + "/dom-to-image.js" + params,
3509
+
3510
+ this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js" + params,
3511
+ this.props.resourcePath + "/hs/hs_human_segmentation.js" + params,
3512
+ this.props.resourcePath + "/hs/hs_human_segmentation.wasm" + params,
3513
+
3514
+ this.props.resourcePath + "/mix/mix_frame.js" + params,
3515
+ this.props.resourcePath + "/mix/pageBoard.js" + params,
3079
3516
 
3080
3517
  ]
3518
+ try{
3519
+ if (!cv){
3520
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3521
+ }
3522
+ } catch(err) {
3523
+ console.log(err)
3524
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3525
+ }
3526
+
3081
3527
  const that = this
3082
3528
  let i = 0
3083
3529
  scriptAdd()
@@ -3092,14 +3538,14 @@ class Video extends Component {
3092
3538
  if (document.all) { //如果是IE
3093
3539
  script.onreadystatechange = () => {
3094
3540
  if (script.readyState == 'loaded' || script.readyState == 'complete') {
3095
- that.test_controller = new McuController();
3541
+ that.test_controller = new MeetingController();
3096
3542
  that.asr_controller = new AsrController()
3097
3543
  that.mountClick()
3098
3544
  }
3099
3545
  }
3100
3546
  } else {
3101
3547
  script.onload = () => {
3102
- that.test_controller = new McuController();
3548
+ that.test_controller = new MeetingController();
3103
3549
  that.asr_controller = new AsrController()
3104
3550
  that.mountClick()
3105
3551
  }
@@ -3123,7 +3569,17 @@ class Video extends Component {
3123
3569
  }
3124
3570
  }
3125
3571
  componentWillMount() {
3126
- console.log('hsbc_teller_sdk', '2.0.7')
3572
+ console.log('hsbc_teller_sdk', SDK_VERISON)
3573
+ // window.document.startRecord = () => {
3574
+ // this.enableServerRecording();
3575
+ // }
3576
+ // window.document.stopRecord = (recordId) => {
3577
+ // this.test_controller.StopRemoteRecord(recordId || this.state.recordId)
3578
+ // }
3579
+ // window.document.detectNetworkWeak = () => {
3580
+ // console.log('detectNetworkWeak')
3581
+ // this.test_controller.detectNetworkWeak()
3582
+ // }
3127
3583
  let arr = []
3128
3584
  for(let i=1;i<=12;i++){
3129
3585
  arr.push({
@@ -3137,6 +3593,18 @@ class Video extends Component {
3137
3593
  }
3138
3594
  this.setState({
3139
3595
  videoList: arr
3596
+ }, () => {
3597
+ // 设置播放回调
3598
+ for(let i=1;i<=12;i++){
3599
+ let dom = document.getElementById('video'+ i)
3600
+ dom.addEventListener("loadedmetadata", (event) => {
3601
+ console.log('video'+ i +' loadedmetadata:' + dom.srcObject.id)
3602
+ this.saveLog('video'+ i +' loadedmetadata, id=' + dom.srcObject.id)
3603
+ // let arrItem = this.state.videoList.find(el => el.idIndex == i) || {}
3604
+ // console.log(arrItem.videoName)
3605
+
3606
+ });
3607
+ }
3140
3608
  })
3141
3609
  if (this.props.sessionId) {
3142
3610
  this.getRoomStatus({
@@ -3162,6 +3630,7 @@ class Video extends Component {
3162
3630
  sid = document.getElementById('publish_streamId1').name
3163
3631
  }
3164
3632
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3633
+ this.saveVideoPoint('mute', 'RM端静音')
3165
3634
  this.sendMessage({
3166
3635
  'typeId': 1013,
3167
3636
  'muteStatus': 1,
@@ -3183,6 +3652,7 @@ class Video extends Component {
3183
3652
  sid = document.getElementById('publish_streamId1').name
3184
3653
  }
3185
3654
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3655
+ this.saveVideoPoint('mute', 'RM端解除静音')
3186
3656
  this.sendMessage({
3187
3657
  'typeId': 1013,
3188
3658
  'muteStatus': 0,
@@ -3192,6 +3662,11 @@ class Video extends Component {
3192
3662
  }
3193
3663
  })
3194
3664
  }
3665
+ if (this.state.isPictureInPicture) {
3666
+ setTimeout(() => {
3667
+ this.pictureInPicture('Refresh')
3668
+ }, 0);
3669
+ }
3195
3670
  }
3196
3671
  };
3197
3672
  isFileSuccuse = () => {
@@ -3252,30 +3727,58 @@ class Video extends Component {
3252
3727
  streamShare = ''
3253
3728
  }
3254
3729
  if (this.state.isSharedScreen) {
3255
- const publish_config = {}
3730
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3731
+ setTimeout(() => {
3256
3732
  publish_config.media_type = 1
3257
3733
  publish_config.publish_device = 2
3734
+ publish_config.need_volume_analyser = true
3258
3735
  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}
3736
+ publish_config.desktopStreamToCanvas = false
3261
3737
  publish_config.enableDesktopAudio = true
3262
3738
  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
3739
+ publish_config.publish_video_id = 'video20'
3740
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3741
+ publish_config.publish_tag = 'projectionWhiteboard'
3742
+ this.test_controller.Publish(publish_config)
3743
+ }, 300);
3744
+ // const publish_config = {}
3745
+ // publish_config.media_type = 1
3746
+ // publish_config.publish_device = 2
3747
+ // publish_config.video_profile_type = 1
3748
+ // // publish_config.video_profile_type=100
3749
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3750
+ // publish_config.enableDesktopAudio = true
3751
+ // publish_config.degradationType = 2
3752
+ // publish_config.desktopStreamToCanvas = false
3753
+ // publish_config.sid = document.getElementById('video20').name
3754
+ // this.test_controller.ChangeMediaStream(publish_config)
3755
+ // this.state.isScreenSwitching = true
3267
3756
  } else {
3268
3757
  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);
3758
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3759
+ setTimeout(() => {
3760
+ publish_config.media_type = 1
3761
+ publish_config.publish_device = 2
3762
+ publish_config.need_volume_analyser = true
3763
+ publish_config.video_profile_type = 1
3764
+ publish_config.desktopStreamToCanvas = false
3765
+ publish_config.enableDesktopAudio = true
3766
+ publish_config.degradationType = 2
3767
+ publish_config.publish_video_id = 'video20'
3768
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3769
+ publish_config.publish_tag = 'projectionWhiteboard'
3770
+ this.test_controller.Publish(publish_config)
3771
+ }, 300);
3772
+ // publish_config.media_type = 1;
3773
+ // publish_config.publish_device = 2;
3774
+ // publish_config.video_profile_type = 1
3775
+ // // publish_config.video_profile_type=100
3776
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3777
+ // publish_config.enableDesktopAudio = true
3778
+ // publish_config.desktopStreamToCanvas = false
3779
+ // publish_config.degradationType = 2
3780
+ // publish_config.sid = document.getElementById('video20').name;
3781
+ // this.test_controller.ChangeMediaStream(publish_config);
3279
3782
  } else {
3280
3783
  publish_config.media_type = 1
3281
3784
  publish_config.publish_device = 2
@@ -3354,9 +3857,11 @@ class Video extends Component {
3354
3857
  sid = document.getElementById('publish_streamId1').name
3355
3858
  }
3356
3859
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10))
3860
+ this.saveVideoPoint('mute', 'RM端静音')
3357
3861
  } else {
3358
3862
  // 当前是
3359
3863
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3864
+ this.saveVideoPoint('mute', 'RM端解除静音')
3360
3865
  this.setState({
3361
3866
  voiceImg: voiceImgOpen,
3362
3867
  voiceName: '静音'
@@ -3375,6 +3880,17 @@ class Video extends Component {
3375
3880
  }
3376
3881
 
3377
3882
  };
3883
+ handleOkPictureConfirm = () => {
3884
+ this.pictureInPictureClick('add')
3885
+ this.setState({isPictureConfirmModalVisible: false})
3886
+ }
3887
+ handleOkRecordConfirm = () => {
3888
+ if (!this.state.isPictureInPicture) {
3889
+ this.pictureInPicture()
3890
+ }
3891
+ this.saveLog('Start recording')
3892
+ this.enableServerRecording()
3893
+ }
3378
3894
  handleOk = () => {
3379
3895
  // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
3380
3896
  this.sendMessage({
@@ -3399,7 +3915,7 @@ class Video extends Component {
3399
3915
  sid = document.getElementById('publish_streamId1').name
3400
3916
  }
3401
3917
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3402
- this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
3918
+ this.saveVideoPoint('mute', 'RM端静音')
3403
3919
  this.setState({
3404
3920
  isModalVisible: false
3405
3921
  })
@@ -3579,6 +4095,9 @@ class Video extends Component {
3579
4095
  // videoList: this.state.videoList
3580
4096
  // })
3581
4097
  this.videoListSort();
4098
+ if (this.state.isPictureInPicture) {
4099
+ this.pictureInPicture('Refresh')
4100
+ }
3582
4101
  } else {
3583
4102
  console.log('1')
3584
4103
  this.messageClick('保持信息失败', 'error')
@@ -3768,6 +4287,7 @@ class Video extends Component {
3768
4287
  })
3769
4288
  // this.messageClick('识别失败', 'error')
3770
4289
  this.errorCodeClick('ocr',result.code)
4290
+ this.saveLog('OCR failed, error code=' + result.code)
3771
4291
  }
3772
4292
  } catch (err) {
3773
4293
  this.setState({
@@ -3866,6 +4386,9 @@ class Video extends Component {
3866
4386
  // videoList: this.state.videoList
3867
4387
  // })
3868
4388
  this.videoListSort();
4389
+ if (this.state.isPictureInPicture) {
4390
+ this.pictureInPicture('Refresh')
4391
+ }
3869
4392
  } else {
3870
4393
  console.log('1')
3871
4394
  this.messageClick('保持信息失败', 'error')
@@ -4098,19 +4621,25 @@ class Video extends Component {
4098
4621
  }
4099
4622
  }
4100
4623
  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
- }
4624
+ const imgBase64 = this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png')
4625
+ // console.log(imgBase64)
4626
+
4627
+ compressImage(imgBase64, (compressedImg)=>{
4628
+ // console.log(compressedImg)
4629
+ if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4630
+ this.setState({
4631
+ facialImg: compressedImg,
4632
+ isFaceImage: true,
4633
+ facialImgFront: compressedImg,
4634
+ })
4635
+ } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4636
+ this.setState({
4637
+ facialImg: compressedImg,
4638
+ isFaceImage: true,
4639
+ facialImgBack: compressedImg,
4640
+ })
4641
+ }
4642
+ })
4114
4643
 
4115
4644
  }
4116
4645
  handleChangeOcr = (val) => {
@@ -4122,10 +4651,10 @@ class Video extends Component {
4122
4651
  })
4123
4652
  }
4124
4653
  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
4654
+ this.state.channelId = props.roomId || this.state.channelId
4655
+ this.state.rtoken = props.mtoken || this.state.rtoken
4656
+ this.state.sessionId = props.sessionId || this.state.sessionId
4657
+ this.state.imRoomId = props.imRoomId || this.state.imRoomId
4129
4658
  }
4130
4659
  appGetUsernameClick = async (userId) => {
4131
4660
  let data = ''
@@ -4273,6 +4802,21 @@ class Video extends Component {
4273
4802
  })
4274
4803
  }
4275
4804
  }
4805
+ changePdfRendering = () => {
4806
+ if (this.props.pdfRendering) {
4807
+ // 暂停绘制
4808
+ clearInterval(this.state.drawCanvasInterval)
4809
+ } else {
4810
+ // 继续绘制
4811
+ if (!this.drawFunction) {
4812
+ console.log('未开始远程签署')
4813
+ return
4814
+ }
4815
+ clearInterval(this.state.drawCanvasInterval)
4816
+ this.state.drawCanvasInterval = setInterval(this.drawFunction, 1000 / 20);
4817
+ }
4818
+
4819
+ }
4276
4820
  navigatorClick = () => {
4277
4821
  const that = this
4278
4822
  const publish_config = {};
@@ -4302,8 +4846,10 @@ class Video extends Component {
4302
4846
  canvas.width = 960;
4303
4847
  canvas.height = 540;
4304
4848
 
4305
-
4306
- videoMedia.addEventListener('play', (event) => {
4849
+ if (this.state.whiteboardPlayEvent) {
4850
+ videoMedia.removeEventListener('play', this.state.whiteboardPlayEvent)
4851
+ }
4852
+ this.state.whiteboardPlayEvent = (event) => {
4307
4853
  var $this = this; //cache
4308
4854
  if ($this.state.operateShow) {
4309
4855
  isGraffiti = false
@@ -4314,20 +4860,21 @@ class Video extends Component {
4314
4860
  canvas.width = this.state.whiteboardWidth
4315
4861
  }
4316
4862
  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
4863
 
4327
- setTimeout(loop, 1000 / 20); // drawing at 30fps
4328
- }
4864
+ if (this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
4865
+ $this.drawFunction = () => {
4866
+ if (!$this.paused && !$this.ended) {
4867
+ // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4868
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4869
+ // } else {
4870
+ // cobj.fillStyle = 'rgb(0 0 0)'
4871
+ // cobj.fillRect(0,0,960,540)
4872
+ // }
4873
+ }
4329
4874
  }
4330
4875
 
4876
+ this.state.drawCanvasInterval = setInterval($this.drawFunction , 1000/ 20);
4877
+
4331
4878
  if (document.getElementById('video20').name) {
4332
4879
  // 代表已经有了进行切流
4333
4880
  publish_config.publish_device = 5
@@ -4350,7 +4897,8 @@ class Video extends Component {
4350
4897
  publish_config.publish_tag = 'projectionWhiteboard'
4351
4898
  this.test_controller.Publish(publish_config)
4352
4899
  }
4353
- }, 0);
4900
+ }
4901
+ videoMedia.addEventListener('play', this.state.whiteboardPlayEvent);
4354
4902
  navigator.mediaDevices.getDisplayMedia({
4355
4903
  video: true,
4356
4904
  preferCurrentTab: true,
@@ -4382,13 +4930,34 @@ class Video extends Component {
4382
4930
  that.test_controller.UnPublish(document.getElementById('video20').name)
4383
4931
  }
4384
4932
  }
4933
+
4934
+ // 关闭当前共享屏幕
4935
+ document.getElementById('video20') && document.getElementById('video20').name ? this.test_controller.UnPublish(document.getElementById('video20').name) : ''
4936
+ that.state.isSharedScreen = false
4937
+ that.state.isScreenSwitching = false
4938
+ that.setState({
4939
+ screenName: '共享模式'
4940
+ });
4941
+ that.tabTitlesClick('RMScreen', 'delect')
4942
+
4385
4943
  }, error => {
4386
4944
  console.log("Unable to acquire screen capture", error);
4387
4945
  });
4388
4946
  }
4389
- // publishAllScreen = () => {
4390
-
4391
- // }
4947
+ publishRecorderDevice = () => {
4948
+ if (this.state.recorderDevice){
4949
+ let publish_config = {}
4950
+ publish_config.media_type = 3
4951
+ publish_config.publish_device = 1
4952
+ publish_config.videoSource = this.state.recorderDevice.actionid
4953
+ publish_config.video_profile_type = 100
4954
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
4955
+ publish_config.publish_video_id = 'publish_video_record_device'
4956
+ publish_config.publish_streamId_id = 'publish_streamId_record_device'
4957
+ publish_config.publish_tag = 'sharedScreen'
4958
+ this.test_controller.Publish(publish_config)
4959
+ }
4960
+ }
4392
4961
  publishAllScreen = () => {
4393
4962
  const that = this
4394
4963
  const publish_config = {};
@@ -4661,6 +5230,7 @@ class Video extends Component {
4661
5230
  jsHeapSizeLimit: '未知', // 上下文内可用堆的最大体积
4662
5231
  totalJSHeapSize: '未知', // 已分配的堆体积
4663
5232
  usedJSHeapSize: '未知', // 当前 JS 堆活跃段(segment)的体积
5233
+ lightResult: this.state.envInfo? this.state.envInfo.lightResult : '未知'
4664
5234
  }
4665
5235
 
4666
5236
  if (navigator) {
@@ -4694,8 +5264,12 @@ class Video extends Component {
4694
5264
  // console.log(`有效网络连接类型: ${effectiveType}`);
4695
5265
  // console.log(`估算的下行速度/带宽: ${downlink}Mb/s`);
4696
5266
  // console.log(`估算的往返时间: ${rtt}ms`);
4697
- if (!window.navigator.onLine) {envInfo.networkInfo = ''}
4698
- else envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5267
+ if (!window.navigator.onLine) {
5268
+ envInfo.networkInfo = ''}
5269
+ else {
5270
+ envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5271
+ envInfo.networkResult = downlink > 0.2? '合格': '不合格'
5272
+ }
4699
5273
  }
4700
5274
  setNetworkInfo()
4701
5275
  navigator.connection.removeEventListener('change', self.envDetection);
@@ -4725,7 +5299,8 @@ class Video extends Component {
4725
5299
  // console.log('当前 JS 堆活跃段(segment)的体积', envInfo.usedJSHeapSize)
4726
5300
  envInfo.memoryResult = '合格'
4727
5301
  }
4728
-
5302
+ // 背景曝光环境检测
5303
+ this.lightDetect()
4729
5304
 
4730
5305
  this.setState({
4731
5306
  // isModalVisibleEnvironment: true,
@@ -4736,6 +5311,9 @@ class Video extends Component {
4736
5311
  this.setState({
4737
5312
  isModalVisibleEnvironment: false,
4738
5313
  })
5314
+ if (!this.state.isPictureInPicture) {
5315
+ this.pictureInPicture()
5316
+ }
4739
5317
  }
4740
5318
  // handleCancelEnvDetection = () => {
4741
5319
  // this.setState({
@@ -4787,16 +5365,39 @@ class Video extends Component {
4787
5365
  this.setState({
4788
5366
  beautyName: '开启美颜'
4789
5367
  })
5368
+ beautyMode = 'none'
4790
5369
  beautySetMode('none')
5370
+ beautyStop()
5371
+ if(!isSuccuseHs) {
5372
+ stopHs()
5373
+ }
4791
5374
  } else {
4792
5375
  this.state.beautyType = true
5376
+ beautyMode = 'beauty'
4793
5377
  beautySetMode('beauty')
4794
5378
  this.setState({
4795
5379
  beautyName: '关闭美颜'
4796
5380
  })
4797
5381
  }
5382
+ this.changeMediaStream();
4798
5383
 
4799
5384
  }
5385
+ changeMediaStream = () => {
5386
+ let publish_config = {}
5387
+ publish_config.sid = document.getElementById('publish_video1').name
5388
+ publish_config.media_type = 1
5389
+ publish_config.publish_device = 1
5390
+ // publish_config.videoSource = this.state.cameraValue
5391
+ // publish_config.audioSource = this.state.microphoneValue
5392
+ publish_config.need_volume_analyser = true
5393
+ publish_config.video_profile_type = 100
5394
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
5395
+ // publish_config.publish_video_id = 'publish_video1'
5396
+ // publish_config.publish_streamId_id = 'publish_streamId1'
5397
+ // publish_config.publish_tag = 'tag1'
5398
+ this.test_controller.ChangeMediaStream(publish_config)
5399
+ }
5400
+
4800
5401
  componentDidMount() {
4801
5402
  var box = document.getElementById("whiteboardDIV");
4802
5403
  var box1 = document.getElementById("operate")
@@ -4909,11 +5510,18 @@ class Video extends Component {
4909
5510
  if (!isSuccuseHs) {
4910
5511
 
4911
5512
  hsSetMode('blur')
5513
+ hsMode = 'blur'
4912
5514
  isSuccuseHs = true
4913
5515
  } else {
4914
5516
  hsSetMode('none')
5517
+ hsMode = 'none'
4915
5518
  isSuccuseHs = false
5519
+ stopHs()
5520
+ if(!this.state.beautyType) {
5521
+ beautyStop()
5522
+ }
4916
5523
  }
5524
+ this.changeMediaStream();
4917
5525
  }
4918
5526
  virtualization = () => {
4919
5527
  this.virtualizationClick()
@@ -4940,6 +5548,17 @@ class Video extends Component {
4940
5548
  return false;
4941
5549
  }
4942
5550
  }
5551
+ isHKPassValidTime=(value)=>{
5552
+ if (!value.split('.') || value.split('.').length < 3 || value.split('.').some(el => el == '')) return false;
5553
+ let start = new Date('2020.01.01').valueOf();
5554
+ let end = new Date('2023.12.31').valueOf();
5555
+ var time = new Date(value).valueOf();
5556
+ if(start<=time && end >= time ){
5557
+ return true;
5558
+ }else{
5559
+ return false;
5560
+ }
5561
+ }
4943
5562
  handleChangeCertificateValidity = (event) => {
4944
5563
  // 护照只有起始日期,单独处理
4945
5564
  if (this.state.documentType == 'PASSPORT_CARD' && event.target.value.split('.').length >2) {
@@ -4960,6 +5579,12 @@ class Video extends Component {
4960
5579
  certificateValidity: event.target.value,
4961
5580
  certificateValidityType: true
4962
5581
  });
5582
+ } else if (this.state.documentType == 'HK_MO_PASS_CARD' && this.isHKPassValidTime(event.target.value.split('-')[1])){
5583
+ // 疫情政策对港澳来往通行证放宽限制,有效期限从2020.1.1到2023.12.31都算有效
5584
+ this.setState({
5585
+ certificateValidity: event.target.value,
5586
+ certificateValidityType: true
5587
+ });
4963
5588
  } else {
4964
5589
  this.setState({
4965
5590
  certificateValidity: event.target.value,
@@ -4974,6 +5599,9 @@ class Video extends Component {
4974
5599
  if (this.props.shareMask != prevProps.shareMask) {
4975
5600
  this.sendNotification()
4976
5601
  }
5602
+ if (this.props.pdfRendering != prevProps.pdfRendering) {
5603
+ this.changePdfRendering()
5604
+ }
4977
5605
  }
4978
5606
  onChangeOCRCustomer = (e) => {
4979
5607
  console.log(e)
@@ -5074,8 +5702,10 @@ class Video extends Component {
5074
5702
 
5075
5703
  }))
5076
5704
  }
5077
-
5078
-
5705
+ this.setState({
5706
+ documentError: '',
5707
+ isModalVisibleCustomer: false,
5708
+ })
5079
5709
  }
5080
5710
  })
5081
5711
  // this.customerFaceClick(this.state.customerList[this.state.customerSelect])
@@ -5524,7 +6154,7 @@ class Video extends Component {
5524
6154
  <audio id={'audio'+(item.idIndex)} autoPlay />
5525
6155
  <label style={{ display: 'none' }} id={'feedId'+(item.idIndex)} type="text" />
5526
6156
 
5527
- <div style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
6157
+ <div onClick={this.muteOpposite.bind(this, 'video'+(item.idIndex))} style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
5528
6158
  {
5529
6159
  item.mute && <img
5530
6160
  alt=""
@@ -5591,6 +6221,23 @@ class Video extends Component {
5591
6221
  !this.state.isSuspend && <span>确定是否暂停会话?</span>
5592
6222
  }
5593
6223
  </Modal>
6224
+ {/* 画中画重新开启确认 */}
6225
+ <Modal closable={false} centered={true} visible={this.state.isPictureConfirmModalVisible} maskClosable={false} footer={[
6226
+ <div key='end'>
6227
+ {/* <Button className="modelButtonCancel" onClick={()=> {this.setState({isPictureConfirmModalVisible: false})}}>取消</Button> */}
6228
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkPictureConfirm}>确定</Button>
6229
+ </div>
6230
+ ]}>
6231
+ <div className='endModal'>画中画已关闭,请重新开启</div>
6232
+ </Modal>
6233
+ {/* 双录中断重新开启确认 */}
6234
+ <Modal closable={false} centered={true} visible={this.state.isRecordingeErrorModalVisible} maskClosable={false} footer={[
6235
+ <div key='end'>
6236
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkRecordConfirm}>确定</Button>
6237
+ </div>
6238
+ ]}>
6239
+ <div className='endModal'>双录异常中断,请重新开启</div>
6240
+ </Modal>
5594
6241
  {/* 是否退出会议*/}
5595
6242
  <Modal closable={false} centered={true} visible={this.state.isModalVisibleEnd} maskClosable={false} footer={[
5596
6243
  <div key='end'>
@@ -5598,7 +6245,7 @@ class Video extends Component {
5598
6245
  <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnd}>确定</Button>
5599
6246
  </div>
5600
6247
  ]}>
5601
- <div className='endModal'>是否要结束并退出会议?</div>
6248
+ <div className='endModal'>{this.state.businessId? '正在进行业务录制,是否确认结束并退出会议?': '是否要结束并退出会议?'}</div>
5602
6249
  </Modal>
5603
6250
  {/* ocr及人脸 */}
5604
6251
  <Modal title={this.state.titleModal} width={800} closable={true} maskClosable={false} onCancel={this.handleCancelFacial} centered={true} visible={this.state.isModalVisibleFacial} footer={[
@@ -5941,22 +6588,26 @@ class Video extends Component {
5941
6588
  <Modal title="环境检测" maskClosable={false} width={650} closable={false} centered={true} visible={this.state.isModalVisibleEnvironment} footer={[
5942
6589
  <div key='env'>
5943
6590
  {/* <Button className="modelButtonCancel" onClick={this.handleCancelEnvDetection}>取消</Button> */}
5944
- <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnvDetection}>确定</Button>
6591
+ <Button className="modelButtonOk" type="primary" disabled={this.state.loading} danger onClick={this.handleOkEnvDetection}>确定</Button>
5945
6592
  </div>
5946
6593
  ]}>
5947
- <Collapse defaultActiveKey={['1', '2', '3', '4', '5']} ghost>
6594
+ <Collapse defaultActiveKey={['1', '2', '3', '4', '5', '6']} ghost>
5948
6595
 
5949
- <Panel header={'网络检测 - ' +this.state.envInfo.networkResult} key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
6596
+ <Panel header={<span>网络检测 - {this.state.envInfo.networkResult } {this.state.envInfo.networkResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6597
+ key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
5950
6598
  <p className='envClass'>网络状态:{this.state.envInfo.networkStatus}</p>
5951
6599
  {this.state.envInfo.networkInfo?<p className='envClass'>{this.state.envInfo.networkInfo}</p>:null}
5952
6600
  </Panel>
5953
- <Panel header={'设备电量 - ' +this.state.envInfo.batteryResult} key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
6601
+ <Panel header={<span>设备电量 - {this.state.envInfo.batteryResult} {this.state.envInfo.batteryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />} </span>}
6602
+ key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
5954
6603
  <p className='envClass'>电量:{this.state.envInfo.batteryLevel}({this.state.envInfo.batteryCharging})</p>
5955
6604
  </Panel>
5956
- <Panel header={'内存检测 - ' +this.state.envInfo.memoryResult} key="1" className={this.state.envInfo.memoryResult=='不合格'? 'panel-error':''}>
6605
+ <Panel header={<span>内存检测 - {this.state.envInfo.memoryResult} {this.state.envInfo.memoryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6606
+ key="1" className={this.state.envInfo.memoryResult=='不合格'? 'panel-error':''}>
5957
6607
  <p className='envClass'>最大可用内存:{this.state.envInfo.jsHeapSizeLimit} ;当前已使用:{this.state.envInfo.usedJSHeapSize} </p>
5958
6608
  </Panel>
5959
- <Panel header={'摄像头设备 - ' +this.state.envInfo.cameraResult} key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
6609
+ <Panel header={<span>摄像头设备 - {this.state.envInfo.cameraResult}{this.state.envInfo.cameraResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6610
+ key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
5960
6611
  <div >
5961
6612
  {
5962
6613
  this.state.cameraList.map((item, index) => {
@@ -5969,7 +6620,7 @@ class Video extends Component {
5969
6620
  {this.state.cameraList.length == 0 ? <p className="envClass">获取不到摄像头设备,请检查</p> : null}
5970
6621
  </div>
5971
6622
  </Panel>
5972
- <Panel header={'麦克风设备 - ' +this.state.envInfo.microResult} key="4" className={this.state.envInfo.microResult=='不合格'? 'panel-error':''}>
6623
+ <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
6624
  <div>
5974
6625
  {
5975
6626
  this.state.microphoneList.map((item, index) => {
@@ -5981,6 +6632,9 @@ class Video extends Component {
5981
6632
  {this.state.cameraList.length == 0 ? <p className="envClass">获取不到麦克风设备,请检查</p> : null}
5982
6633
  </div>
5983
6634
  </Panel>
6635
+ <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'}>
6636
+ <p className="envClass">{this.state.envInfo.lightResult=='合格'? '无过度背光、曝光':'过度背光、曝光'}</p>
6637
+ </Panel>
5984
6638
  </Collapse>
5985
6639
  </Modal>
5986
6640
  <video className="mixedvideo" id="mixedvideo" autoPlay muted={true} width="0" height="0"></video>
@@ -5989,6 +6643,7 @@ class Video extends Component {
5989
6643
 
5990
6644
  <video className="mixedvideo" id="recordvideo" autoPlay width="0" height="0"></video>
5991
6645
  <video className="mixedvideo" id="record_video" muted autoPlay></video>
6646
+ <video className="mixedvideo" id="publish_video_record_device" muted autoPlay></video>
5992
6647
 
5993
6648
  </Spin>
5994
6649
  </div>);
@@ -6023,10 +6678,18 @@ Video.defaultProps = {
6023
6678
  customers: ['--'],
6024
6679
  otherAttendees: undefined
6025
6680
  },
6681
+ pdfRendering: false,
6026
6682
  isTranscribing: false,
6027
6683
  shareMask: false,
6028
6684
  isOpenSound: false, // true开启进出音效 false不开启
6685
+ isWeakSound: false,
6029
6686
  userSide: 2,
6687
+ meetingDuration: null, // 会议时长,单位小时
6688
+ recordMode: 1, // 录制模式 1远程录制 2网点录制
6689
+ defaultBranchCode: "",// 员工网点缩写
6690
+ customerId: "", //客户号
6691
+ salesBranchCode: "", //网点编号(分行号)
6692
+ financialOffice: "", // 理财室
6030
6693
  logUrl: 'http://hsbc.cn-shanghai.log.aliyuncs.com/logstores/hsbc/track?APIVersion=0.6.0&app=meeting-ui',
6031
6694
  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
6695
  }