react_hsbc_teller 2.0.1 → 2.0.2-4.1

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.
@@ -4,11 +4,13 @@
4
4
  import React, { Component, useState } from 'react';
5
5
  import QRCode from 'qrcode.react';
6
6
  import API from '../../api/api';
7
- import { initWebSocket, joinRoom, disconnect } from '../../common/websocket';
8
7
  import { BoardOperate } from '../../common/index.esm.js';
9
8
  import './video.less'
9
+ import { compressImage, isLight } from '../../utils/utils'
10
10
  import Header from '../header/header.jsx'
11
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'
12
14
  import voiceImgOpen from '../../assets/img/icon_Mute.png'
13
15
  import voiceImgCloe from '../../assets/img/icon_MuteOne.png'
14
16
  import cameraImgOpen from '../../assets/img/icon_camera.png'
@@ -17,11 +19,13 @@ import beautyImg from '../../assets/img/whiteningLut.jpg'
17
19
  import ocrImage from '../../assets/img/jietu.png'
18
20
  import faceImage from '../../assets/img/jietu_face.png'
19
21
  import autod from '../../assets/mp3/joinmeeting.mp3'
22
+ 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
- import { callNimIM } from '../../utils/cell.js'
25
29
  import Modal from "antd/lib/modal";
26
30
  import 'antd/lib/modal/style'
27
31
  import message from "antd/lib/message";
@@ -37,6 +41,9 @@ import 'antd/lib/radio/style'
37
41
 
38
42
  import Space from "antd/lib/space";
39
43
  import 'antd/lib/space/style'
44
+ import { Collapse } from 'antd';
45
+ import 'antd/lib/collapse/style'
46
+ const { Panel } = Collapse;
40
47
 
41
48
 
42
49
  import styled from 'styled-components';
@@ -45,6 +52,8 @@ import SignMy from '../sign/signMy.jsx'
45
52
  import Step from '../components/step/step.jsx'
46
53
  import axios from 'axios';
47
54
  import CryptoJS from "crypto-js";
55
+
56
+ const SDK_VERISON = '2.0.24.1'
48
57
  const IDtypeFront = '请客户在其设备后置摄像头下展示证件正面(如:身份证照片页面)'
49
58
  const IDtypeBack = '请在后置摄像头下展示证件反面(如:身份证国徽页)'
50
59
  const { Option } = Select;
@@ -52,14 +61,33 @@ const LEAVE_TYPE = {
52
61
  TELLER_EXIT: 1, // 坐席退出
53
62
  ROOM_DESTROYED: -1, // 房间异常
54
63
  }
64
+ const POINT_TYPE = {
65
+ tts: '文字转语音',
66
+ asr: '语音转文字',
67
+ ffd: "人脸出框检测",
68
+ env: "环境检测",
69
+ pipd: "画中画显示、关闭",
70
+ pwd: "违禁词检测",
71
+ wnd: "弱网",
72
+ mute: "静音",
73
+ expDark: '曝光、背光',
74
+ fcd: '人脸变化检测'
75
+ }
76
+ const RECORD_DEVICE_NAME = 'screen-capture-recorder'
77
+ // const RECORD_DEVICE_NAME = 'Full HD webcam'
78
+ let media_status = 0
55
79
  let pictureInPictureVideo
56
80
  let mix_stream
57
81
  let worker
58
82
  let streamShare
83
+ let streamRecord
59
84
  let videoName
85
+ let lastFaceNum = 1
60
86
  let muteJson = new Map()
61
- let dateTime = 0
87
+ // let dateTime = 0
62
88
  let messageValue = ''
89
+ let messageValueMap = new Map()
90
+ let third_id_Map = new Map()
63
91
  // let beautyType = false
64
92
  // let beautyNum = 0 // 0-关闭 1--弱 2--中 5---高
65
93
  let rateList = []
@@ -69,6 +97,8 @@ let isSuccuseHs = false
69
97
  let isGraffiti = false
70
98
  let strokeColor = '#333'
71
99
  let clearTime
100
+ let beautyMode = 'none'
101
+ let hsMode = 'none'
72
102
  let CanvasHome = styled.div`
73
103
  position: fixed;
74
104
  z-index: ${props => props.zIndexNum};
@@ -114,7 +144,7 @@ function clearStreamRemain() {
114
144
  };
115
145
  async function startBeauty(stream) {
116
146
  await beautyInit();
117
- beautyStart(stream, "none");
147
+ beautyStart(stream, beautyMode);
118
148
  }
119
149
  async function startMix(stream, onState) {
120
150
  var drawCanvas = document.getElementById('canvas');
@@ -130,21 +160,25 @@ async function startHs(stream) {
130
160
 
131
161
  await hsInit();
132
162
 
133
- hsStart(stream, 'none');
163
+ hsStart(stream, hsMode);
134
164
 
135
165
  }
136
166
 
137
167
  async function stopHs() {
138
- var stop_stream = true;//控制是否内部来进行关闭流
139
- var stream = hsStop(stop_stream);
140
- if (stream != null && stream != undefined) {
141
- stream.getTracks().forEach((track) => {
142
- track.stop();
143
- });
144
- stream = null;
168
+ try {
169
+ var stop_stream = true;//控制是否内部来进行关闭流
170
+ var stream = hsStop(stop_stream);
171
+ if (stream != null && stream != undefined) {
172
+ stream.getTracks().forEach((track) => {
173
+ track.stop();
174
+ });
175
+ stream = null;
176
+ }
177
+ isSuccuseHs = false
178
+ } catch (err) {
179
+ console.log('stopHs Error')
180
+ console.log(err)
145
181
  }
146
- isSuccuseHs = false
147
-
148
182
  }
149
183
  async function mixStopClick() {
150
184
  var stop_stream = true;//控制是否内部来进行关闭流
@@ -169,6 +203,7 @@ class Video extends Component {
169
203
  }
170
204
  cancel = axios.CancelToken.source()
171
205
  state = {
206
+ ablePlayNetweakAudio: true,
172
207
  beautyType: false,
173
208
  beautyName: '开启美颜',
174
209
  signNoClick: false,
@@ -201,6 +236,7 @@ class Video extends Component {
201
236
  isModalVisibleFacial: false,
202
237
  isModalVisibleEnd: false,
203
238
  isModalVisible: false,
239
+ isPictureConfirmModalVisible:false,
204
240
  screenName: '共享模式',
205
241
  suspendName: '暂停',
206
242
  cameraImg: cameraImgOpen,
@@ -240,14 +276,14 @@ class Video extends Component {
240
276
  microphoneList: [],
241
277
  speakerList: [],
242
278
  isModalVisibleInspection: false,
279
+ envInfo: {},
280
+ isModalVisibleEnvironment: false,
243
281
  cameraValue: '',
244
282
  microphoneValue: '',
245
283
  imStatus: false,
246
- imJoinRoom: false,
247
284
  analyserData: new Map(),
248
285
  analyserHeight: new Map(),
249
286
  OnVolumeAnalyserMap: new Map(),
250
- manualClose: false,
251
287
  defaultValue: '1',
252
288
  customOcrSid: '',
253
289
  shareMaskState: false,
@@ -288,6 +324,8 @@ class Video extends Component {
288
324
  cardFailReason: '',
289
325
  videoType: '',
290
326
  certificateValidityType: true,
327
+ drawCanvasInterval: null,
328
+ faceDetectionTimer: null, // 人脸检测定时器
291
329
  };
292
330
  // eslint-disable-next-line no-undef
293
331
  test_controller = '';
@@ -295,7 +333,7 @@ class Video extends Component {
295
333
  saveLog = (val) => {
296
334
  axios({
297
335
  method: 'get',
298
- baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller=2.0.1&logTime=' + Date.now() + '&mtoken=' + encodeURIComponent(this.state.rtoken) + '&roomId=' + encodeURIComponent(this.state.channelId) + '&sessionId=' + encodeURIComponent(this.state.sessionId) + '&appointmentID=' + this.props.businessNumber,
336
+ 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,
299
337
 
300
338
  }).then(res => {
301
339
 
@@ -315,8 +353,16 @@ class Video extends Component {
315
353
  try {
316
354
  let result = await API.createRoom({
317
355
  staffId: this.props.tellerAccount,
356
+ staffName: this.props.staffName,
318
357
  activityId: this.props.businessNumber,
319
358
  callbackUrl: this.props.callbackUrl,
359
+ meetingDuration: this.props.meetingDuration,
360
+ recordMode: this.props.recordMode,
361
+ defaultBranchCode: this.props.defaultBranchCode,
362
+ customerId: this.props.customerId,
363
+ customerType: this.props.customerType.toString(),
364
+ salesBranchCode: this.props.salesBranchCode,
365
+ financialOffice: this.props.financialOffice,
320
366
  roomId: this.state.channelId,
321
367
  mtoken: this.state.rtoken,
322
368
  type: 2
@@ -325,31 +371,24 @@ class Video extends Component {
325
371
  this.state.imRoomId = result.imRoomId,
326
372
  this.state.sessionId = result.sessionId;
327
373
 
328
- this.state.cameraList.forEach((el, i) => {
329
- let publish_config = {}
330
- publish_config.media_type = 1
331
- publish_config.publish_device = 1
332
- publish_config.videoSource = el.actionid
333
- publish_config.audioSource = this.state.microphoneValue
334
- publish_config.need_volume_analyser = true
335
- // publish_config.video_profile_type = 3
336
- publish_config.video_profile_type = 100
337
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
338
- publish_config.publish_video_id = 'publish_video' + (i+1)
339
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
340
- publish_config.publish_tag = 'tag' + (i+1)
341
- this.test_controller.Publish(publish_config)
342
- })
343
-
344
- // eslint-disable-next-line no-undef
345
- setTimeout(() => {
346
- if (this.state.imStatus && !this.state.imJoinRoom) {
347
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
348
- this.state.imJoinRoom = true
349
- this.saveLog('Join im room')
350
- console.log('加入IM房间')
351
- }
352
- })
374
+ let publish_config = {}
375
+ publish_config.media_type = 1
376
+ publish_config.publish_device = 1
377
+ publish_config.videoSource = this.state.cameraValue
378
+ publish_config.audioSource = this.state.microphoneValue
379
+ publish_config.need_volume_analyser = true
380
+ // publish_config.video_profile_type = 3
381
+ publish_config.video_profile_type = 100
382
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
383
+ publish_config.publish_video_id = 'publish_video1'
384
+ publish_config.publish_streamId_id = 'publish_streamId1'
385
+ publish_config.publish_tag = 'tag1'
386
+ this.test_controller.Publish(publish_config)
387
+
388
+ // this.publishAllScreen();
389
+ // 单独发布录制屏幕设备的流
390
+ this.publishRecorderDevice()
391
+
353
392
  this.props.createRoomCallback({
354
393
  type: 1,
355
394
  errorManage: '',
@@ -459,11 +498,6 @@ class Video extends Component {
459
498
  handleEdit = () => {
460
499
  console.log(JSON.parse(window.sessionStorage.getItem('sigData')));
461
500
  // eslint-disable-next-line no-undef
462
- // initWebSocket('wss://im.uat.dsp.hsbcfts.com.cn:443/wealth/im/ws/')
463
- if (!this.state.imStatus) {
464
- this.state.manualClose = false
465
- initWebSocket('wss://' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname + ':' + JSON.parse(window.sessionStorage.getItem('sigData')).webPort + '/ws/');
466
- }
467
501
  const config_param = {};
468
502
  config_param.workspaceId = this.state.workSpaceId;
469
503
  config_param.uid = this.props.tellerAccount;
@@ -491,57 +525,55 @@ class Video extends Component {
491
525
  publish_streamId_id: 'publish_streamId1',
492
526
  publish_tag: 'tag1'
493
527
  },
494
- {
495
- publish_video_id: 'publish_video2',
496
- publish_streamId_id: 'publish_streamId2',
497
- publish_tag: 'tag2'
498
- },
499
- {
500
- publish_video_id: 'publish_video3',
501
- publish_streamId_id: 'publish_streamId3',
502
- publish_tag: 'tag3'
503
- }
528
+ // {
529
+ // publish_video_id: 'publish_video2',
530
+ // publish_streamId_id: 'publish_streamId2',
531
+ // publish_tag: 'tag2'
532
+ // },
533
+ // {
534
+ // publish_video_id: 'publish_video3',
535
+ // publish_streamId_id: 'publish_streamId3',
536
+ // publish_tag: 'tag3'
537
+ // }
504
538
  ];
505
539
  config_param.initSubscribe = [
506
540
  {
507
541
  subscribe_video_id: 'video1',
508
542
  subscribe_audio_id: 'audio1',
509
- subscribe_streamId_id: 'subscribe_streamId1',
510
543
  feedId_id: 'feedId1'
511
544
  },
512
545
  {
513
546
  subscribe_video_id: 'video2',
514
547
  subscribe_audio_id: 'audio2',
515
- subscribe_streamId_id: 'subscribe_streamId2',
516
548
  feedId_id: 'feedId2'
517
549
  },
518
550
  {
519
551
  subscribe_video_id: 'video3',
520
552
  subscribe_audio_id: 'audio3',
521
- subscribe_streamId_id: 'subscribe_streamId3',
522
553
  feedId_id: 'feedId3'
523
554
  },
524
555
  {
525
556
  subscribe_video_id: 'video4',
526
557
  subscribe_audio_id: 'audio4',
527
- subscribe_streamId_id: 'subscribe_streamId4',
528
558
  feedId_id: 'feedId4'
529
559
  },
530
560
  {
531
561
  subscribe_video_id: 'video5',
532
562
  subscribe_audio_id: 'audio5',
533
- subscribe_streamId_id: 'subscribe_streamId5',
534
563
  feedId_id: 'feedId5'
535
564
  },
536
565
  {
537
566
  subscribe_video_id: 'video6',
538
567
  subscribe_audio_id: 'audio6',
539
- subscribe_streamId_id: 'subscribe_streamId6',
540
568
  feedId_id: 'feedId6'
541
569
  }
542
570
  ];
543
571
  this.test_controller.InitRoomConfig(config_param)
544
572
  this.saveLog('mrtc InitRoomConfig start')
573
+ // 预热摄像头
574
+ config_param.videoSource = this.state.cameraValue
575
+ config_param.audioSource = this.state.microphoneValue
576
+ this.test_controller.PreOpenLocalMedia(config_param)
545
577
  };
546
578
  rateAll = async () => {
547
579
  let data = ''
@@ -558,7 +590,7 @@ class Video extends Component {
558
590
  }
559
591
  }
560
592
  // 开启录制
561
- enableServerRecording = () => {
593
+ enableServerRecording = (record_business_id) => {
562
594
  const that = this
563
595
  this.rateAll().then((res) => {
564
596
  console.log('退出房间者', res)
@@ -592,47 +624,54 @@ class Video extends Component {
592
624
  height: 175
593
625
  },
594
626
  {
595
- tag: 'tag2',
627
+ tag: 'customer1',
596
628
  xPosition: 213,
597
629
  yPosition: 0,
598
630
  width: 213,
599
631
  height: 175
600
632
  },
601
633
  {
602
- tag: 'tag3',
634
+ tag: 'customer2',
603
635
  xPosition: 426,
604
636
  yPosition: 0,
605
637
  width: 213,
606
638
  height: 175
607
639
  },
608
640
  {
609
- tag: 'customer1',
641
+ tag: 'customer3',
610
642
  xPosition: 639,
611
643
  yPosition: 0,
612
644
  width: 213,
613
645
  height: 175
614
646
  },
615
647
  {
616
- tag: 'customer2',
648
+ tag: 'customer4',
617
649
  xPosition: 852,
618
650
  yPosition: 0,
619
651
  width: 213,
620
652
  height: 175
621
653
  },
622
654
  {
623
- tag: 'customer3',
655
+ tag: 'customer5',
624
656
  xPosition: 1065,
625
657
  yPosition: 0,
626
658
  width: 213,
627
659
  height: 175
628
660
  },
629
661
  {
630
- tag: 'customer4',
662
+ tag: 'customer6',
631
663
  xPosition: 1278,
632
664
  yPosition: 0,
633
665
  width: 213,
634
666
  height: 175
635
667
  },
668
+ // {
669
+ // tag: 'sharedScreen', // 一期暂时不需要录制
670
+ // xPosition: 960,
671
+ // yPosition: 180,
672
+ // width: 320,
673
+ // height: 180
674
+ // }
636
675
  ]
637
676
  Array.isArray(res) ?
638
677
  res.map((item) => {
@@ -668,12 +707,23 @@ class Video extends Component {
668
707
  recordParam.endType = 1;
669
708
  recordParam.crf = 26
670
709
  recordParam.overlaps = [
710
+ {
711
+ tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
712
+ type: 2, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
713
+ id: 2, // ⽔印 ID
714
+ enable: true,
715
+ xPosition: 640, // x 轴位置
716
+ yPosition: 10, // y 轴位置
717
+ text: `${this.props.recordMode ==1 ?'远程录制' :'网点录制'} ${this.props.salesBranchCode || ''} ${this.state.branchName || ''} ${this.props.financialOffice || ''}`,
718
+ fontSize: 16, // 字体⼤⼩
719
+ url: '' // ⽔印图⽚ HTTP 地址
720
+ },
671
721
  {
672
722
  tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
673
723
  type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
674
724
  id: 1, // ⽔印 ID
675
725
  enable: true,
676
- xPosition: 1000, // x 轴位置
726
+ xPosition: 1080, // x 轴位置
677
727
  yPosition: 10, // y 轴位置
678
728
  text: '', // ⽔印⽂字
679
729
  fontSize: 16, // 字体⼤⼩
@@ -682,7 +732,7 @@ class Video extends Component {
682
732
  ];
683
733
  recordParam.tagPositions = list
684
734
  console.log('recordParam', recordParam);
685
- that.test_controller.StartRemoteRecord(filePath, recordParam, '')
735
+ that.test_controller.StartRemoteRecord(filePath, recordParam, record_business_id)
686
736
 
687
737
  })
688
738
 
@@ -698,6 +748,15 @@ class Video extends Component {
698
748
  })
699
749
  }
700
750
  };
751
+ sendMessage = (msg) => {
752
+ try {
753
+ console.log('发送消息', JSON.stringify(msg))
754
+ this.test_controller.SendTextMsg(JSON.stringify(msg))
755
+ } catch (err) {
756
+ console.error(`内部错误, msg = ${JSON.stringify(msg)} `)
757
+ console.error(err)
758
+ }
759
+ }
701
760
  errorCodeClick=(type,value)=>{
702
761
  if(type == 'ocr'){
703
762
  if(value == -1007 || value == -100701 || value == -100702 || value == -200001 || value == -300901 || value == -300902 || value == -400001) {
@@ -885,47 +944,38 @@ class Video extends Component {
885
944
  this.messageClick('当前暂无客户', 'error')
886
945
  }
887
946
  }
888
- messageClick = (value, valueOne) => {
889
- console.log(value, valueOne)
890
- if (messageValue != value) {
947
+ messageClick = (value, tipType) => {
948
+ console.log('messageClick', value, tipType)
949
+ const intervalSec = 5 // 相同提示触发间隔
950
+ const durationSec = 4.5 // 提示持续时间
951
+ if (messageValueMap.get(value) == undefined) {
952
+ // map中没有相同消息
891
953
  messageValue = value
892
- dateTime = new Date().getTime()
893
- if (valueOne == 'error') {
894
- message.error({
895
- content: value,
896
- icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
897
- className: 'errorClassName',
898
- top: 200,
899
- duration: 10
900
- })
901
- } else if (valueOne == 'success') {
902
- message.success({
903
- content: value,
904
- icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
905
- className: 'successClassName',
906
- top: 200,
907
- duration: 10
908
- })
909
- }
910
- } else if (((new Date().getTime()) - dateTime) / 1000 > 30) {
911
- dateTime = new Date().getTime()
912
- if (valueOne == 'error') {
954
+ messageValueMap.set(value, setTimeout(() => {
955
+ messageValueMap.delete(value)
956
+ }, intervalSec * 1000))
957
+
958
+ if (tipType == 'error') {
913
959
  message.error({
914
960
  content: value,
915
961
  icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
916
962
  className: 'errorClassName',
917
963
  top: 200,
918
- duration: 10
964
+ duration: durationSec
919
965
  })
920
- } else if (valueOne == 'success') {
966
+ } else if (tipType == 'success') {
921
967
  message.success({
922
968
  content: value,
923
969
  icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
924
970
  className: 'successClassName',
925
971
  top: 200,
926
- duration: 10
972
+ duration: durationSec
927
973
  })
928
974
  }
975
+ clearTimeout(this.messageClearTimer)
976
+ this.messageClearTimer = setTimeout(() => {
977
+ messageValue = ''
978
+ }, durationSec * 1000);
929
979
  }
930
980
 
931
981
  }
@@ -939,6 +989,100 @@ class Video extends Component {
939
989
  this.selectCustomer('facial')
940
990
  }
941
991
  };
992
+ generateMediaInfo = (sid) => {
993
+ let that = this
994
+ console.log(that.test_controller, sid)
995
+ console.log(that.test_controller.GetMediaInfo(sid))
996
+ let originalMediaInfo = that.test_controller.GetMediaInfo(sid);
997
+ let mediaInfo = {
998
+ peer_connection_: originalMediaInfo.peer_connection_,
999
+ local_video_width: originalMediaInfo.local_video_width,
1000
+ local_video_height: originalMediaInfo.local_video_height,
1001
+ local_video_frame: originalMediaInfo.local_video_frame,
1002
+ local_video_bitrate: originalMediaInfo.local_video_bitrate,
1003
+ stream_type: originalMediaInfo.stream_type,
1004
+ stat_interval_: 3,
1005
+ video_send_packets_base_: 0,
1006
+ video_recv_packets_base_: 0,
1007
+ video_send_lost_pack_base_: 0,
1008
+ video_recv_lost_pack_base_: 0,
1009
+ audio_send_packets_base_: 0,
1010
+ audio_recv_packets_base_: 0,
1011
+ audio_send_lost_pack_base_: 0,
1012
+ audio_recv_lost_pack_base_: 0,
1013
+ video_send_qpsum_base: 0,
1014
+ video_send_frame_encoded_base: 0,
1015
+ video_recv_qpsum_base: 0,
1016
+ video_recv_frame_decoded_base: 0,
1017
+ video_send_bitrate_base_: 0,
1018
+ video_recv_bitrate_base_: 0,
1019
+ audio_send_bitrate_base_: 0,
1020
+ audio_recv_bitrate_base_: 0,
1021
+ };
1022
+ return mediaInfo;
1023
+ }
1024
+ detectNetworkWeak = () => {
1025
+ return new Promise((resolve, reject) => {
1026
+ let detectionsNumber = 3
1027
+ let finalResult = true
1028
+ let setTimer = () => {
1029
+ setTimeout(() => {
1030
+ this.test_controller.GetStats(this.mediaInfo).then(media_stat => {
1031
+ if (detectionsNumber>2) {
1032
+ // 不考虑第一次的评估结果,重新计算码率
1033
+ detectionsNumber--;
1034
+ setTimer()
1035
+ return
1036
+ }
1037
+ console.log('media_stat:')
1038
+ console.log(media_stat)
1039
+ // 分辨率、帧率
1040
+ let googAvailableSendBandwidth = (media_stat["VideoBwe"]["googAvailableSendBandwidth"] / 1000).toFixed(2);
1041
+ let googTransmitBitrate = (media_stat["VideoBwe"]["googTransmitBitrate"] / 1000).toFixed(2);
1042
+ let ssrcVideoSendLostRate = media_stat["ssrcVideoSend"]["lostRate"];
1043
+ let ssrcAudioSendLostRate = media_stat["ssrcAudioSend"]["lostRate"];
1044
+ let weak_googAvailableSendBandwidth = 200;
1045
+ let weak_ssrcVideoSendLostRate = 20;
1046
+ let weak_ssrcAudioSendLostRate = 20;
1047
+ let weak_str = "网络正常";
1048
+ if (googAvailableSendBandwidth < weak_googAvailableSendBandwidth) {
1049
+ weak_str = "当前网络不佳";
1050
+ }
1051
+ let bpsSend = (media_stat.ssrcVideoSend["bpsSend"] / 1000).toFixed(2)
1052
+ let fps = media_stat["ssrcVideoSend"].googFrameRateSent
1053
+ let str =
1054
+ "带宽评估:" + (googAvailableSendBandwidth == undefined ? "none" : googAvailableSendBandwidth + "kbps") + "; "
1055
+ + "视频码率:" + bpsSend + "kb" + "; "
1056
+ + "音频码率:" + (media_stat.ssrcAudioSend["bpsSend"] / 1000).toFixed(2) + "kb" + "; "
1057
+ + "视频丢包率:" + (ssrcVideoSendLostRate == undefined ? "none" : ssrcVideoSendLostRate + "%") + "; "
1058
+ + "音频丢包率:" + (ssrcAudioSendLostRate == undefined ? "none" : ssrcAudioSendLostRate + "%") + "; "
1059
+ + weak_str + "; "
1060
+ + "当前编码格式:" + media_stat["ssrcVideoSend"].googCodecName + "; "
1061
+ + "分辨率:" + media_stat["ssrcVideoSend"].resolution + "; "
1062
+ + "帧率:" + media_stat["ssrcVideoSend"].googFrameRateSent;
1063
+ console.log('弱网', str)
1064
+ // document.getElementById("publish_media_stat1").innerText = str;
1065
+ let result = (bpsSend < 200 ) && googAvailableSendBandwidth < weak_googAvailableSendBandwidth
1066
+ if (result) {
1067
+ console.log('[!]弱网单次评估' + result);
1068
+ } else {
1069
+ finalResult = false
1070
+ console.log('弱网单次评估' + result);
1071
+ }
1072
+ if (detectionsNumber > 0 && finalResult) {
1073
+ detectionsNumber -= 1
1074
+ setTimer();
1075
+ } else {
1076
+ console.log('弱网综合检测结果:' + finalResult)
1077
+ resolve(finalResult)
1078
+ }
1079
+ });
1080
+
1081
+ }, 3000)
1082
+ }
1083
+ setTimer()
1084
+ })
1085
+ }
942
1086
  ocrClick = () => {
943
1087
  if (this.isFileSuccuse()) {
944
1088
  this.state.faceCustomerType = 2
@@ -954,6 +1098,10 @@ class Video extends Component {
954
1098
  streamShare.getTracks().forEach(track => track.stop());
955
1099
  streamShare = ''
956
1100
  }
1101
+ if (streamRecord) {
1102
+ streamRecord.getTracks().forEach(track => track.stop());
1103
+ streamRecord = ''
1104
+ }
957
1105
  this.finishSession()
958
1106
 
959
1107
  };
@@ -990,14 +1138,14 @@ class Video extends Component {
990
1138
  return a.order - b.order;
991
1139
  })
992
1140
  for (let i =1;i<=12;i++){
993
- if(document.getElementById('video'+i).name){
1141
+ if(sortedlist[i-1].videoName){
994
1142
  list.push({
995
- name: 'video' + i,
996
- title: sortedlist[i-1].videoName,
997
- mute: sortedlist[i-1].mute,
998
- noVideo: sortedlist[i-1].noVideo
999
- })
1000
- }
1143
+ name: 'video' + sortedlist[i-1].idIndex,
1144
+ title: sortedlist[i-1].videoName,
1145
+ mute: sortedlist[i-1].mute,
1146
+ noVideo: sortedlist[i-1].noVideo
1147
+ })
1148
+ }
1001
1149
  }
1002
1150
  console.log(list)
1003
1151
  this.state.listVideoPicture = list
@@ -1029,11 +1177,14 @@ class Video extends Component {
1029
1177
  worker = new Worker(url);
1030
1178
  window.URL.revokeObjectURL(blob);
1031
1179
 
1032
-
1033
1180
  worker.onmessage = () => {
1034
- cobj.clearRect(0, 0, 640, 360 * this.state.listVideoPicture.length);
1181
+ const messageBoxHeight = 50;
1182
+ const recordBoxHeight = 50; // this.state.businessRecordId ? 50 : 0;
1183
+ const baseStartHeight = messageBoxHeight + recordBoxHeight
1184
+
1185
+ cobj.clearRect(0, 0, 640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1035
1186
  canvas.width = 640;
1036
- canvas.height = 360 * this.state.listVideoPicture.length;
1187
+ canvas.height = 360 * this.state.listVideoPicture.length + baseStartHeight;
1037
1188
  for (let i = 0; i < this.state.listVideoPicture.length; i++) {
1038
1189
 
1039
1190
  let videoId = this.state.listVideoPicture[i].name;
@@ -1049,15 +1200,15 @@ class Video extends Component {
1049
1200
  }
1050
1201
  if (this.state.listVideoPicture[i].noVideo) {
1051
1202
  cobj.fillStyle = '#333';
1052
- cobj.fillRect((640 - newVideoWidth) / 2, 360 * i, newVideoWidth, newVideoHeight)
1203
+ cobj.fillRect((640 - newVideoWidth) / 2, 360 * i + baseStartHeight, newVideoWidth, newVideoHeight)
1053
1204
  } else {
1054
- cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i, 640, 360);
1205
+ cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i + baseStartHeight, 640, 360);
1055
1206
 
1056
1207
  }
1057
1208
  cobj.beginPath();
1058
1209
  cobj.strokeStyle = this.props.titleColor;
1059
1210
  cobj.fillStyle = this.props.titleBackground;
1060
- cobj.fillRect(0, 360 * (i + 1) - 60, 300, 60)
1211
+ cobj.fillRect(0, 360 * (i + 1) - 60 + baseStartHeight, 300, 60)
1061
1212
  cobj.fill();
1062
1213
  cobj.stroke();
1063
1214
  cobj.beginPath();
@@ -1075,12 +1226,12 @@ class Video extends Component {
1075
1226
  break;
1076
1227
  }
1077
1228
  }
1078
- cobj.strokeText(str, 70, 360 * (i + 1) - 20);
1229
+ cobj.strokeText(str, 70, 360 * (i + 1) - 20 + baseStartHeight);
1079
1230
  cobj.stroke();
1080
1231
  //左边框
1081
1232
  cobj.beginPath();
1082
- cobj.moveTo(0, 0);
1083
- cobj.lineTo(0, 360 * this.state.listVideoPicture.length);
1233
+ cobj.moveTo(0, 0 + baseStartHeight);
1234
+ cobj.lineTo(0, 360 * this.state.listVideoPicture.length + baseStartHeight);
1084
1235
  cobj.closePath(); //闭合路径
1085
1236
  cobj.lineWidth = 5; //线的边框为10像素
1086
1237
  cobj.strokeStyle = '#d9363e';
@@ -1088,8 +1239,8 @@ class Video extends Component {
1088
1239
 
1089
1240
  //下边框
1090
1241
  cobj.beginPath();
1091
- cobj.moveTo(0, 0);
1092
- cobj.lineTo(640, 0);
1242
+ cobj.moveTo(0, 0 + baseStartHeight);
1243
+ cobj.lineTo(640, 0 + baseStartHeight);
1093
1244
  cobj.closePath(); //闭合路径
1094
1245
  cobj.lineWidth = 5; //线的边框为10像素
1095
1246
  cobj.strokeStyle = '#d9363e';
@@ -1097,8 +1248,8 @@ class Video extends Component {
1097
1248
 
1098
1249
  //右边框
1099
1250
  cobj.beginPath();
1100
- cobj.moveTo(640, 360 * this.state.listVideoPicture.length);
1101
- cobj.lineTo(640, 0);
1251
+ cobj.moveTo(640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1252
+ cobj.lineTo(640, 0 + baseStartHeight);
1102
1253
  cobj.closePath(); //闭合路径
1103
1254
  cobj.lineWidth = 5; //线的边框为10像素
1104
1255
  cobj.strokeStyle = '#d9363e';
@@ -1107,8 +1258,8 @@ class Video extends Component {
1107
1258
 
1108
1259
  //上边框
1109
1260
  cobj.beginPath();
1110
- cobj.moveTo(0, 360 * this.state.listVideoPicture.length);
1111
- cobj.lineTo(640, 360 * this.state.listVideoPicture.length);
1261
+ cobj.moveTo(0, 360 * this.state.listVideoPicture.length + baseStartHeight);
1262
+ cobj.lineTo(640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1112
1263
  cobj.closePath(); //闭合路径
1113
1264
  cobj.lineWidth = 5; //线的边框为10像素
1114
1265
  cobj.strokeStyle = '#d9363e';
@@ -1119,9 +1270,9 @@ class Video extends Component {
1119
1270
  var img = document.getElementById("icon_huatong");
1120
1271
  var img1 = document.getElementById("icon_huatong_close");
1121
1272
  if (this.state.listVideoPicture[i].mute) {
1122
- cobj.drawImage(img1, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1273
+ cobj.drawImage(img1, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1123
1274
  } else {
1124
- cobj.drawImage(img, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1275
+ cobj.drawImage(img, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1125
1276
 
1126
1277
  // 绘制实时音量
1127
1278
  let sid = document.getElementById(this.state.listVideoPicture[i].name).name
@@ -1138,9 +1289,9 @@ class Video extends Component {
1138
1289
  // 以画布左上角为坐标原点
1139
1290
  let drawArea = {
1140
1291
  x1: 28 / 50 * microphoneSize + 10, // 波动范围右下角的点坐标
1141
- y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60,
1292
+ y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1142
1293
  x2: 22 / 50 * microphoneSize + 10, // 波动范围左上角的点坐标
1143
- y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60,
1294
+ y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1144
1295
  }
1145
1296
 
1146
1297
 
@@ -1170,6 +1321,53 @@ class Video extends Component {
1170
1321
  }
1171
1322
 
1172
1323
  }
1324
+ cobj.fillStyle = '#333333';
1325
+ cobj.fillRect(0, 0, 640, baseStartHeight)
1326
+ // 录制中状态
1327
+ if (this.state.businessRecordId) {
1328
+ let str = '· 录制中'
1329
+ // cobj.fillStyle = '#F8F2F3';
1330
+ cobj.font = "normal lighter 30px sans-serif";
1331
+ // cobj.fillRect(0, 0, 640, recordBoxHeight)
1332
+ cobj.textAlign = 'center';
1333
+ cobj.strokeStyle = 'red';
1334
+ cobj.lineWidth = 2
1335
+ cobj.strokeText(str, 320, recordBoxHeight - 15);
1336
+ cobj.stroke();
1337
+ }
1338
+ // 消息提示
1339
+ if (messageValue) {
1340
+ let str = messageValue
1341
+ cobj.fillStyle = '#F8F2F3';
1342
+ cobj.font = "normal lighter 30px sans-serif";
1343
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1344
+ cobj.fillRect(0, recordBoxHeight, 640, messageBoxHeight)
1345
+ cobj.textAlign = 'center';
1346
+ cobj.strokeStyle = 'black';
1347
+ cobj.lineWidth = 2
1348
+ cobj.strokeText(str, 320, recordBoxHeight + messageBoxHeight - 15);
1349
+ cobj.stroke();
1350
+ }
1351
+
1352
+ // 敏感词提示
1353
+ // let str = this.state.sensitiveTitle || ''
1354
+ // if (str)
1355
+ // cobj.fillStyle = 'red';
1356
+ // cobj.font = "normal lighter 32px sans-serif";
1357
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1358
+ // cobj.fillRect(320 - textWidth/ 2, 24, textWidth, 32)
1359
+ // cobj.textAlign = 'center';
1360
+ // cobj.strokeStyle = 'white';
1361
+ // cobj.lineWidth = 2
1362
+ // for (let k = 0; k < str.length; k++) {
1363
+ // if (cobj.measureText(str.substring(0, k + 1)).width > 610) {
1364
+ // str = str.substring(0, k - 2)
1365
+ // str += '...'
1366
+ // break;
1367
+ // }
1368
+ // }
1369
+ // cobj.strokeText(str, 320, 50);
1370
+ // cobj.stroke();
1173
1371
  };
1174
1372
 
1175
1373
  const captureStream = canvas.captureStream();
@@ -1182,17 +1380,37 @@ class Video extends Component {
1182
1380
 
1183
1381
  pictureInPictureVideo.addEventListener('enterpictureinpicture', (event) => {
1184
1382
  //可获取画中画窗口的一些数据,如宽高等
1383
+ console.log('开启画中画')
1185
1384
  pictureInPictureVideo.style.display = 'block';
1186
1385
  pictureInPictureVideo.play();
1187
1386
  this.state.isPictureInPicture = true
1387
+ clearTimeout(this.loopPlay)
1188
1388
  });
1189
1389
 
1190
1390
  pictureInPictureVideo.addEventListener('leavepictureinpicture', (event) => {
1391
+ console.log('关闭画中画')
1191
1392
  pictureInPictureVideo.srcObject = null;
1192
1393
  pictureInPictureVideo.style.display = "none";
1193
1394
  this.state.listVideoPicture = []
1194
1395
  worker.postMessage(false);
1195
1396
  this.state.isPictureInPicture = false
1397
+
1398
+ clearTimeout(this.loopPlay)
1399
+ // 画中画循环播放逻辑
1400
+ if (document.hidden && this.state.businessRecordId) {
1401
+ this.setState({
1402
+ isPictureConfirmModalVisible: true
1403
+ })
1404
+ this.loopPlay = () => {
1405
+ console.log('loopPlay status', this.state.isPictureInPicture);
1406
+ if(!this.state.isPictureInPicture && document.getElementById("publish_video1")){
1407
+ let audio = new Audio(PIPictureClosedAudio)
1408
+ audio.play()
1409
+ setTimeout(this.loopPlay, 3000);
1410
+ }
1411
+ }
1412
+ setTimeout(this.loopPlay, 0);
1413
+ }
1196
1414
  });
1197
1415
 
1198
1416
  }
@@ -1260,9 +1478,8 @@ class Video extends Component {
1260
1478
  })
1261
1479
  }
1262
1480
  }
1263
- mountClick = () => {
1264
- window.IMEvt = msg => {
1265
- console.log(JSON.parse(msg));
1481
+ handleReceiveMsg = (msg) => {
1482
+ console.log(JSON.parse(msg));
1266
1483
  const Mival = JSON.parse(msg);
1267
1484
  if (Mival.typeId == 1210) {
1268
1485
  // 进行初始化操作
@@ -1295,6 +1512,7 @@ class Video extends Component {
1295
1512
  }, ()=>{
1296
1513
  this.pictureInPicture('Refresh')
1297
1514
  })
1515
+ this.messageClick('客户切换其他软件', 'error')
1298
1516
  }
1299
1517
  }
1300
1518
  else if (Mival.typeId == 3003) { // app进入前台
@@ -1311,6 +1529,30 @@ class Video extends Component {
1311
1529
  })
1312
1530
  }
1313
1531
  }
1532
+ else if (Mival.typeId == 5001) { // 客户端离框
1533
+ let TITLE = '客户'
1534
+ if (Mival.data && Mival.data.userId) {
1535
+ TITLE = this.getUserTitle(Mival.data.userId)
1536
+ }
1537
+ this.messageClick(TITLE+'人脸已离框', 'error')
1538
+ // this.saveVideoPoint('ffd', '客户人脸离框');
1539
+ }
1540
+ else if (Mival.typeId == 5002) { // 客户端背光
1541
+ let TITLE = '客户'
1542
+ if (Mival.data && Mival.data.userId) {
1543
+ TITLE = this.getUserTitle(Mival.data.userId)
1544
+ }
1545
+ this.messageClick(TITLE+'背光、曝光过度', 'error')
1546
+ // this.saveVideoPoint('env', '客户端背光、曝光过度');
1547
+ }
1548
+ else if (Mival.typeId == 5003) { // 客户端弱网
1549
+ let TITLE = '客户'
1550
+ if (Mival.data && Mival.data.userId) {
1551
+ TITLE = this.getUserTitle(Mival.data.userId)
1552
+ }
1553
+ this.messageClick(TITLE+'当前网络较弱', 'error')
1554
+ // this.saveVideoPoint('wnd', '客户端弱网');
1555
+ }
1314
1556
  else if (Mival.typeId == 1220) {
1315
1557
  // 一炒多的图片 1214
1316
1558
  if (Mival.sessionId == this.state.sessionId) {
@@ -1341,6 +1583,9 @@ class Video extends Component {
1341
1583
  if (Mival.type == 1) {
1342
1584
  this.switchExternal()
1343
1585
  this.saveLog('whiteboard start, typeId=1218,')
1586
+ if (typeof this.props.sfpCallback === 'function'){
1587
+ this.props.sfpCallback()
1588
+ }
1344
1589
  } else if (Mival.type == 2) {
1345
1590
  if (streamShare) {
1346
1591
  streamShare.getTracks().forEach(track => track.stop());
@@ -1354,6 +1599,7 @@ class Video extends Component {
1354
1599
  } else {
1355
1600
  if (document.getElementById('video20').name) {
1356
1601
  this.test_controller.UnPublish(document.getElementById('video20').name)
1602
+ if(this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
1357
1603
  }
1358
1604
  this.setState({
1359
1605
  isWhiteboard: false
@@ -1384,6 +1630,9 @@ class Video extends Component {
1384
1630
 
1385
1631
  }
1386
1632
  }
1633
+ if (this.state.isPictureInPicture) {
1634
+ this.pictureInPicture('Refresh')
1635
+ }
1387
1636
  }
1388
1637
  } else if (Mival.typeId == 121305) {
1389
1638
  if (Mival.sessionId == this.state.sessionId) {
@@ -1419,33 +1668,25 @@ class Video extends Component {
1419
1668
  });
1420
1669
  let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1421
1670
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1422
- callNimIM('sendCustomCmdMsg', {
1423
- customId: this.state.imRoomId,
1424
- content: JSON.stringify({
1671
+ this.sendMessage({
1425
1672
  'typeId': 1013,
1426
1673
  'muteStatus': 1,
1427
1674
  'data': {
1428
1675
  'sessionId': this.state.sessionId,
1429
1676
  'userId': this.props.tellerAccount
1430
1677
  }
1431
- })
1432
- }, function (code, message, data) {
1433
- // console.log(data)
1434
1678
  })
1435
1679
  }
1436
1680
  document.getElementById('audio1').muted = true
1437
1681
  console.log('音频流静音')
1438
1682
  console.log(document.getElementById('audio1').muted)
1439
1683
  setTimeout(() => {
1440
- callNimIM('sendCustomCmdMsg', {
1441
- customId: this.state.imRoomId,
1442
- content: JSON.stringify({
1443
- 'typeId': 1223,
1444
- 'state': 1, // app解除静音
1445
- 'sessionId': this.state.sessionId,
1446
- 'userId': Mival.data.userId //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1447
- })
1448
- });
1684
+ this.sendMessage({
1685
+ 'typeId': 1223,
1686
+ 'state': 1, // app解除静音
1687
+ 'sessionId': this.state.sessionId,
1688
+ 'userId': Mival.data.userId //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1689
+ })
1449
1690
  }, 1000);
1450
1691
  }
1451
1692
  } else if (Mival.typeId == 1401) {
@@ -1459,37 +1700,186 @@ class Video extends Component {
1459
1700
  this.setState({
1460
1701
  videoList: this.state.videoList
1461
1702
  })
1703
+ if (this.state.isPictureInPicture) {
1704
+ this.pictureInPicture('Refresh')
1705
+ }
1706
+ }
1707
+ } else if (Mival.typeId == 10020) {
1708
+ // 录制中断(模拟测试)
1709
+ // this.messageClick('双录异常中断,请重新开启', 'error')
1710
+ // this.setState({
1711
+ // isRecordingeErrorModalVisible: true,
1712
+ // businessRecordId: '',
1713
+ // })
1714
+ // // 循环播放录制中断语音
1715
+ // clearTimeout(this.recordLoopPlay)
1716
+ // this.recordLoopPlay = () => {
1717
+ // console.log('loop recordId', this.state.recordId, 'businessRecordId ', this.state.businessRecordId)
1718
+ // if(!this.state.businessRecordId && document.getElementById("publish_video1")){
1719
+ // let audio = new Audio(recordErrorAudio)
1720
+ // audio.play()
1721
+ // setTimeout(this.recordLoopPlay, 3000);
1722
+ // }
1723
+ // }
1724
+ // setTimeout(this.recordLoopPlay, 0);
1725
+
1726
+ } else if (Mival.typeId == 33001 && this.state.sessionId == Mival.data.sessionId) {
1727
+ if (Mival.type == 1) {
1728
+ this.saveAuthorize(Mival.data.userId)
1729
+ this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1462
1730
  }
1731
+ console.log('33001 done')
1732
+ } else if (Mival.typeId == 2210 && this.state.sessionId == Mival.sessionId) {
1733
+ if (Mival.status == 1) {
1734
+ // 开启了业务录制
1735
+ console.log('业务录制开启')
1736
+ this.state.businessId = Mival.id;
1737
+ this.saveLog('Start business recording')
1738
+ this.enableServerRecording( Mival.id)
1739
+
1740
+ if (this.props.whetherDetectFace){
1741
+ this.startFaceDetection();
1742
+ }
1743
+ if (this.props.whetherDetectLight){
1744
+ this.startImageDetection();
1745
+ }
1746
+ } else if (Mival.status == 2) {
1747
+ // 关闭了业务录制
1748
+ console.log('业务录制关闭', this.state.businessRecordId)
1749
+ this.saveLog('Stop business recording')
1750
+ this.test_controller.StopRemoteRecord(this.state.businessRecordId)
1751
+ this.state.businessId = '';
1752
+ clearInterval(this.state.faceDetectionTimer);
1753
+ clearInterval(this.state.imageDetectionTimer);
1754
+ }
1755
+ } else if (Mival.typeId == 2002 && this.state.sessionId == Mival.sessionId) {
1756
+ // 会议到时间
1757
+ console.log('会议超过时间限制')
1758
+ this.endSessionValue();
1463
1759
  }
1464
- };
1465
- window.IMOpenfire = msg => {
1466
- console.log('im登录', msg)
1467
- if (msg.status == 'error') {
1468
- this.state.imStatus = false
1469
- this.saveLog('Im connection establishment failed')
1470
- this.roomCallBack(2, 'im建立连接失败', 5)
1471
- } else if (msg.status == 'success') {
1472
- this.state.imStatus = true
1473
- setTimeout(() => {
1474
- if (this.state.imRoomId && !this.state.imJoinRoom) {
1475
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
1476
- this.state.imJoinRoom = true
1477
- console.log('IMOpenfire 加入im房间')
1760
+ }
1761
+ getUserTitle = (userId) => {
1762
+ const user = this.state.videoList.find(el => el.userId == userId)
1763
+ if (!user) return '客户'
1764
+ if (user.isPIBIntranet) return '行内人员'
1765
+ else if (user.userSide == 1) return '访客'
1766
+ else return '客户'
1767
+ }
1768
+ startFaceDetection = () => {
1769
+ console.log('startFaceDetection!!!!')
1770
+ clearInterval(this.state.faceDetectionTimer);
1771
+ const timer = setInterval( async () => {
1772
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1773
+ try {
1774
+ let result = await API.faceDetection({
1775
+ activityId: this.props.businessNumber,
1776
+ sessionId: `${this.props.tellerAccount}_${Date.now()}`,
1777
+ // sessionId: this.state.sessionId,
1778
+ roomId: this.state.channelId + '',
1779
+ appId: this.state.appId,
1780
+ recordId: this.state.recordId,
1781
+ base64Image: path.replace('data:image/png;base64,', '')
1782
+ });
1783
+ const changeNum = lastFaceNum - result.faceNum
1784
+ if (result.faceNum == 0) {
1785
+ // 人脸出框
1786
+ this.messageClick('检测到您的人脸已出框', 'error')
1787
+ this.saveVideoPoint('ffd', 'RM端人脸离框');
1788
+ } else if (lastFaceNum == 0 && result.faceNum == 1) {
1789
+ // 0->1不需要提示
1790
+ } else if (changeNum != 0) {
1791
+ this.messageClick('检测到参会人员数量发生变化', 'error')
1792
+ this.saveVideoPoint('fcd', 'RM端人脸数量发生变化');
1793
+ }
1794
+ lastFaceNum = result.faceNum;
1795
+ } catch (err) {
1796
+ console.error(err);
1797
+ if (err.status == 502 || err.status == 404) {
1478
1798
  }
1479
- }, 200);
1480
- } else if (msg.status == 'close') {
1481
- if (!this.state.manualClose) {
1482
- this.timer && clearInterval(this.timer);
1483
- this.state.imStatus = false
1484
- console.log('IMOpenfireclose')
1485
- this.saveLog('Repeated login of account')
1486
- this.roomCallBack(2, '账号重复登录', 9)
1487
-
1488
1799
  }
1800
+ }, this.props.faceDetectInterval * 1000);
1489
1801
 
1802
+ this.state.faceDetectionTimer = timer;
1803
+ }
1804
+ startImageDetection = () => {
1805
+ console.log('startImageDetection!!!!')
1806
+ clearInterval(this.state.imageDetectionTimer);
1807
+ const timer = setInterval( async () => {
1808
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1809
+ const img = new Image()
1810
+ img.src = path;
1811
+ img.width = 300 //
1812
+ img.onload = () => {
1813
+ const origin = cv.imread(img)
1814
+ // let start = new Date().getTime()
1815
+ const res = isLight(origin)
1816
+ if (res==1 || res== -1){
1817
+ // 背景曝光过度
1818
+ this.messageClick('检测到当前背光、曝光过度', 'error')
1819
+ this.saveVideoPoint('expDark', 'RM端背光、曝光过度');
1820
+ }
1821
+ origin.delete()
1822
+ // let end = new Date().getTime()
1823
+ // console.log('执行时间(s) ', (end - start)/1000 )
1490
1824
  }
1825
+ }, this.props.lightDetectInterval * 1000);
1491
1826
 
1827
+ this.state.imageDetectionTimer = timer;
1828
+ }
1829
+ lightDetect() {
1830
+ try {
1831
+ if (document.getElementById("publish_video1").name) {
1832
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
1833
+ console.log('检测图像长度',path.length)
1834
+ const img = new Image()
1835
+ img.src = path;
1836
+ img.width = 300 //
1837
+ img.onload = () => {
1838
+ const origin = cv.imread(img)
1839
+ // let start = new Date().getTime()
1840
+ const res = isLight(origin)
1841
+ if (res==1 || res==-1){
1842
+ // 背景曝光过度
1843
+ this.state.envInfo.lightResult = '不合格'
1844
+ } else {
1845
+ this.state.envInfo.lightResult = '合格'
1846
+ }
1847
+ this.setState({
1848
+ envInfo: this.state.envInfo
1849
+ })
1850
+ origin.delete()
1851
+ }
1852
+ }
1853
+ // else {
1854
+ // setTimeout(() => {
1855
+ // this.lightDetect()
1856
+ // }, 1000);
1857
+ // }
1858
+ }catch(err){
1859
+ console.error(err)
1860
+ }
1861
+ }
1862
+ saveVideoPoint = async (code, content) => {
1863
+ try {
1864
+ let result = await API.saveVideoPoint({
1865
+ title: POINT_TYPE[code],
1866
+ content: [content],
1867
+ code,
1868
+ activityId: this.props.businessNumber,
1869
+ sessionId: this.state.sessionId,
1870
+ roomId: this.state.channelId + '',
1871
+ appId: this.state.appId,
1872
+ recordId: this.state.recordId,
1873
+ client: 'rm',
1874
+ customerId: this.props.tellerAccount
1875
+ });
1876
+ } catch (err) {
1877
+ console.error(err);
1878
+ if (err.status == 502 || err.status == 404) {
1879
+ }
1492
1880
  }
1881
+ }
1882
+ mountClick = () => {
1493
1883
  let data = {
1494
1884
  account: this.props.tellerAccount,
1495
1885
  type: '2',
@@ -1585,21 +1975,34 @@ class Video extends Component {
1585
1975
  }
1586
1976
  }
1587
1977
  console.log(objList, objList1, objList2)
1978
+ const cameraList = objList.filter(el => !el.actionname.includes(RECORD_DEVICE_NAME))
1979
+ const recorderDevice = objList.find(el => el.actionname.includes(RECORD_DEVICE_NAME))
1588
1980
  this.setState({
1589
- cameraList: objList,
1981
+ cameraList: cameraList,
1982
+ recorderDevice: recorderDevice,
1590
1983
  microphoneList: objList1,
1591
1984
  speakerList: objList2.length > 0 ? [objList2[0]] : []
1592
1985
  })
1593
1986
  let indexId = 0
1594
- objList.map((item, index) => {
1595
- if (item.actionname.indexOf('Integrated Camera') != -1) {
1987
+ let microId = 0
1988
+ // 摄像头设置默认
1989
+ objList.forEach((item, index) => {
1990
+ if (item.actionname.indexOf('HP Full-HD Camera') != -1) {
1596
1991
  indexId = index
1992
+ } else if (item.actionname.indexOf('Integrated Camera') != -1) {
1993
+ indexId = index
1994
+ }
1995
+ })
1996
+ // 麦克风设置默认
1997
+ objList1.forEach((item, index) => {
1998
+ if (item.actionname.indexOf('Microphone Array (Realtek High Definition Audio(SST))') != -1) {
1999
+ microId = index
1597
2000
  }
1598
2001
  })
1599
- console.log(indexId)
2002
+ console.log(indexId, microId)
1600
2003
  this.setState({
1601
2004
  cameraValue: objList[indexId].actionid,
1602
- microphoneValue: objList1[0].actionid
2005
+ microphoneValue: objList1[microId].actionid
1603
2006
  })
1604
2007
  if (!this.state.appId && !this.state.sessionType) {
1605
2008
  console.log('cameraValue', this.state.cameraValue)
@@ -1619,6 +2022,7 @@ class Video extends Component {
1619
2022
  this.state.sessionType = false
1620
2023
  this.messageClick('获取设备失败,请检查摄像头设备是否可用或是否禁用摄像头', 'error')
1621
2024
  this.roomCallBack(2, '获取设备失败', 1)
2025
+ this.showEnvDetection()
1622
2026
  };
1623
2027
  // 建立连接成功
1624
2028
  this.test_controller.OnConnectOK = () => {
@@ -1667,6 +2071,10 @@ class Video extends Component {
1667
2071
  this.state.rtoken = rtoken
1668
2072
  this.createRoom()
1669
2073
  this.saveLog('RM mrtc create room successfully, room_id=' + room_id)
2074
+
2075
+ this.state.imStatus = true
2076
+ this.saveLog('Join im room')
2077
+ console.log('加入IM房间')
1670
2078
  };
1671
2079
  // 创建房间失败
1672
2080
  this.test_controller.OnCreateRoomFailed = (err_code, err_msg) => {
@@ -1701,24 +2109,30 @@ class Video extends Component {
1701
2109
  this.test_controller.OnJoinRoomSucc = () => {
1702
2110
  console.log('加入房间成功')
1703
2111
 
1704
- this.state.cameraList.forEach((el, i) => {
1705
- let publish_config = {}
1706
- publish_config.media_type = 1
1707
- publish_config.publish_device = 1
1708
- publish_config.videoSource = el.actionid
1709
- publish_config.audioSource = this.state.microphoneValue
1710
- publish_config.need_volume_analyser = true
1711
- // publish_config.video_profile_type = 3
1712
- publish_config.video_profile_type = 100
1713
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
1714
- publish_config.publish_video_id = 'publish_video' + (i+1)
1715
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
1716
- publish_config.publish_tag = 'tag' + (i+1)
1717
- this.test_controller.Publish(publish_config)
1718
- })
2112
+ let publish_config = {}
2113
+ publish_config.media_type = 1
2114
+ publish_config.publish_device = 1
2115
+ publish_config.videoSource = this.state.cameraValue
2116
+ publish_config.audioSource = this.state.microphoneValue
2117
+ publish_config.need_volume_analyser = true
2118
+ // publish_config.video_profile_type = 3
2119
+ publish_config.video_profile_type = 100
2120
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
2121
+ publish_config.publish_video_id = 'publish_video1'
2122
+ publish_config.publish_streamId_id = 'publish_streamId1'
2123
+ publish_config.publish_tag = 'tag1'
2124
+ this.test_controller.Publish(publish_config)
2125
+
2126
+ // this.publishAllScreen();
2127
+ // 单独发布录制屏幕设备的流
2128
+ this.publishRecorderDevice()
1719
2129
 
1720
2130
  this.roomCallBack(1, '', 0)
1721
2131
  this.saveLog('mrtc join room success')
2132
+
2133
+ this.state.imStatus = true
2134
+ this.saveLog('Join im room')
2135
+ console.log('加入IM房间')
1722
2136
  };
1723
2137
  // 加入房间失败
1724
2138
  this.test_controller.OnJoinRoomFailed = (err_code, err_msg) => {
@@ -1733,12 +2147,9 @@ class Video extends Component {
1733
2147
  this.state.rtoken = '',
1734
2148
  this.state.sessionId = '',
1735
2149
  this.state.imRoomId = ''
1736
- this.state.imJoinRoom = false
1737
2150
  if (this.state.imStatus) {
1738
2151
  console.log('disconnect断开连接')
1739
- this.state.manualClose = true
1740
2152
  this.state.imStatus = false
1741
- disconnect();
1742
2153
  }
1743
2154
  this.test_controller.Disconnect()
1744
2155
  let data = {
@@ -1749,71 +2160,24 @@ class Video extends Component {
1749
2160
  this.mpaasSig(data);
1750
2161
  };
1751
2162
  this.test_controller.OnSendTextMsgSucc = (msgId) => {
1752
- console.log('发送成功', msgId)
1753
- this.setState({
1754
- documentError: '',
1755
- isModalVisibleCustomer: false,
1756
- })
1757
- this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
2163
+ // console.log('发送成功', msgId)
2164
+ // this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
1758
2165
  }
1759
2166
  this.test_controller.OnSendTextMsgFailed = (msgId, code, msg) => {
1760
2167
  console.log('发送失败', msgId, code, msg)
1761
- this.setState({
1762
- documentError: '推送授权白板失败,请重试'
1763
- })
2168
+ const Mival = JSON.parse(msg)
2169
+ // 失败处理
2170
+ if (Mival.typeId == '3300') {
2171
+ this.setState({
2172
+ documentError: '推送授权白板失败,请重试'
2173
+ })
2174
+ }
1764
2175
  this.saveLog('mrtc OnSendTextMsgFail:' + msgId +', code=' + code + ',msg=' + msg)
1765
2176
  }
1766
2177
  this.test_controller.OnReceiveTextMsg = (uid, msg) => {
1767
- console.log('收到手机端消息', uid, msg, JSON.parse(msg).typeId, JSON.parse(msg).data.sessionId, this.state.sessionId)
1768
- if (JSON.parse(msg).typeId == 33001 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1769
- if (JSON.parse(msg).type == 1) {
1770
- this.saveAuthorize(JSON.parse(msg).data.userId)
1771
- this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1772
- }
1773
- }
1774
- // 线下demo静音处理
1775
- if (JSON.parse(msg).typeId == 4004 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1776
- if (this.isFileSuccuse()) {
1777
- if (!this.state.voiceStatue) {
1778
- // 静音本地
1779
- this.setState({
1780
- voiceStatue: true,
1781
- voiceImg: voiceImgCloe,
1782
- voiceName: '解除静音'
1783
- });
1784
- let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1785
- this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1786
- callNimIM('sendCustomCmdMsg', {
1787
- customId: this.state.imRoomId,
1788
- content: JSON.stringify({
1789
- 'typeId': 1013,
1790
- 'muteStatus': 1,
1791
- 'data': {
1792
- 'sessionId': this.state.sessionId,
1793
- 'userId': this.props.tellerAccount
1794
- }
1795
- })
1796
- }, function (code, message, data) {
1797
- // console.log(data)
1798
- })
1799
- }
1800
- document.getElementById('audio1').muted = true
1801
- console.log('音频流静音')
1802
- console.log(document.getElementById('audio1').muted)
1803
- setTimeout(() => {
1804
- callNimIM('sendCustomCmdMsg', {
1805
- customId: this.state.imRoomId,
1806
- content: JSON.stringify({
1807
- 'typeId': 1223,
1808
- 'state': 1, // app解除静音
1809
- 'sessionId': this.state.sessionId,
1810
- 'userId': uid //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1811
- })
1812
- });
1813
- }, 1000);
1814
- }
1815
- }
1816
- this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
2178
+ console.log('收到手机端消息',uid, msg, JSON.parse(msg))
2179
+ // this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
2180
+ this.handleReceiveMsg(msg)
1817
2181
  }
1818
2182
  this.test_controller.StreamFilterHandler = async (publish_tag, stream, stream_type, publish_device, media_type) => {
1819
2183
  console.log(`stream processed by client, publish_device=${publish_device}, media_type=${media_type}, publish_tag=${publish_tag},stream_type=${stream_type}`);
@@ -1829,28 +2193,13 @@ class Video extends Component {
1829
2193
  if (publish_tag == 'tag1') {
1830
2194
  console.log('tag1', stream)
1831
2195
  let newStream = stream;
1832
- // if (stream.getVideoTracks()[0]) {
1833
- // await startBeauty(newStream);
1834
- // newStream = beautyCaptureStream();
1835
- // // 清理原始流
1836
- // newStream.oninactive = function () {
1837
- // clearOriginStream(stream);
1838
- // };
1839
- // newStream.getVideoTracks()[0].onended = function () {
1840
- // clearOriginStream(stream);
1841
- // };
1842
- // function clearOriginStream(stream) {
1843
- // stream.getTracks().forEach((track) => {
1844
- // track.stop();
1845
- // });
1846
- // stream = null;
1847
- // }
1848
- // };
1849
2196
  if (stream.getVideoTracks()[0]) {
1850
- await startBeauty(newStream);
1851
- newStream = beautyCaptureStream();
1852
- await startHs(newStream);
1853
- newStream = hsCaptureStream();
2197
+ if (this.state.beautyType || isSuccuseHs){
2198
+ await startBeauty(newStream);
2199
+ newStream = beautyCaptureStream();
2200
+ await startHs(newStream);
2201
+ newStream = hsCaptureStream();
2202
+ }
1854
2203
  // 清理原始流
1855
2204
  newStream.oninactive = function () {
1856
2205
  clearOriginStream(stream);
@@ -1872,10 +2221,26 @@ class Video extends Component {
1872
2221
  }
1873
2222
 
1874
2223
  if (publish_tag == 'projectionWhiteboard' && publish_device == 2) {
1875
- // this.graffiti()
1876
- console.log('projectionWhiteboard', stream)
1877
2224
  let newStream1 = stream;
1878
2225
  if (stream.getVideoTracks()[0]) {
2226
+ try {
2227
+ console.log('共享')
2228
+ console.log(stream.getVideoTracks()[0])
2229
+ if ( stream.getVideoTracks()[0] instanceof BrowserCaptureMediaStreamTrack) {
2230
+ console.log('tab共享')
2231
+ this.saveLog('Share type = tab')
2232
+ } else if (stream.getVideoTracks()[0] instanceof MediaStreamTrack && stream.getVideoTracks()[0].label.includes('screen')) {
2233
+ console.log('屏幕共享')
2234
+ this.saveLog('Share type = screen')
2235
+ } else if (stream.getVideoTracks()[0].label.includes('window')){
2236
+ console.log('窗口共享')
2237
+ this.saveLog('Share type = window')
2238
+ }
2239
+ } catch (err) {
2240
+ console.log('不支持此浏览器记录投屏类型日志')
2241
+ console.log(navigator.userAgent)
2242
+ console.log(err)
2243
+ }
1879
2244
  if (this.state.operateShow) {
1880
2245
  await startMix(newStream1, 'mix');
1881
2246
 
@@ -1887,9 +2252,12 @@ class Video extends Component {
1887
2252
  canvas.width = this.state.widthVideo
1888
2253
  } else {
1889
2254
  await startMix(newStream1, 'none');
2255
+ isGraffiti = false
1890
2256
  }
1891
2257
 
1892
2258
  newStream1 = mixCaptureStream();
2259
+ newStream1.getVideoTracks()[0].contentHint = "text"; // 解决清晰度问题
2260
+
1893
2261
  console.log('projectionWhiteboard1', newStream1)
1894
2262
  // 清理原始流
1895
2263
  newStream1.oninactive = function () {
@@ -1905,27 +2273,25 @@ class Video extends Component {
1905
2273
  stream = null;
1906
2274
  }
1907
2275
  }
2276
+ if (stream.getAudioTracks()[0] && newStream1.addTrack) {
2277
+ newStream1.addTrack(stream.getAudioTracks()[0])
2278
+ }
1908
2279
  return newStream1
1909
- } else {
1910
- return stream
1911
2280
  }
1912
-
2281
+ return stream
1913
2282
  }
1914
2283
  // 发布媒体流成功
1915
2284
  this.test_controller.OnPublishSucc = (sid) => {
1916
2285
  console.log('发布媒体流成功', sid)
1917
2286
  this.state.sessionType = true
1918
2287
  if (sid == document.getElementById('video20').name) {
1919
- callNimIM('sendCustomCmdMsg', {
1920
- customId: this.state.imRoomId,
1921
- content: JSON.stringify({
1922
- 'typeId': 2030,
1923
- 'sessionId': this.state.sessionId,
1924
- 'sharedScreen': 1,
1925
- 'tellerId': this.props.tellerAccount
1926
- })
1927
- });
1928
- if (this.state.screenName == '切换共享') {
2288
+ this.sendMessage({
2289
+ 'typeId': 2030,
2290
+ 'sessionId': this.state.sessionId,
2291
+ 'sharedScreen': 1,
2292
+ 'tellerId': this.props.tellerAccount
2293
+ })
2294
+ if (this.state.screenName == '共享屏幕') {
1929
2295
  this.state.isSharedScreen = true
1930
2296
  this.state.isScreenSwitching = false
1931
2297
  }
@@ -1936,29 +2302,31 @@ class Video extends Component {
1936
2302
 
1937
2303
  loading: false,
1938
2304
  });
2305
+ setTimeout(() => {
2306
+ this.showEnvDetection()
2307
+ }, 1500);
2308
+
1939
2309
 
1940
2310
  this.enterRoom()
1941
2311
  this.updateMeetingInfo()
1942
2312
  this.timer = setInterval(
1943
2313
  () => {
1944
2314
  if (!this.state.voiceStatue && this.state.analyserHeight.get(sid).toFixed(2) > 0.1) {
1945
- callNimIM('sendCustomCmdMsg', {
1946
- customId: this.state.imRoomId,
1947
- content: JSON.stringify({
1948
- 'typeId': 3200,
1949
- 'decibelValue': this.state.analyserHeight.get(sid).toFixed(2),
1950
- "data": {
1951
- 'sessionId': this.state.sessionId,
1952
- 'userId': this.props.tellerAccount,
1953
- 'data': (new Date()).valueOf()
1954
- }
1955
-
1956
- })
1957
- });
2315
+ this.sendMessage({
2316
+ 'typeId': 3200,
2317
+ 'decibelValue': this.state.analyserHeight.get(sid).toFixed(2),
2318
+ "data": {
2319
+ 'sessionId': this.state.sessionId,
2320
+ 'userId': this.props.tellerAccount,
2321
+ 'data': (new Date()).valueOf()
2322
+ }
2323
+ })
1958
2324
  }
1959
2325
  },
1960
2326
  1000
1961
2327
  );
2328
+ this.mediaInfo = this.generateMediaInfo(document.getElementById("publish_video1").name);
2329
+
1962
2330
  } else {
1963
2331
  var box = document.getElementById("whiteboardDIV");
1964
2332
  var box1 = document.getElementById("operate")
@@ -2033,6 +2401,10 @@ class Video extends Component {
2033
2401
  participants.map((item, index) => {
2034
2402
  if (item.uid != this.state.tellerAccount) {
2035
2403
  item.publish.map((itemOne, indexOne) => {
2404
+ if (itemOne.tag && itemOne.tag.includes('UnSubscribe_RM')) {
2405
+ console.log('过滤订阅的tag:', itemOne.tag)
2406
+ return
2407
+ }
2036
2408
  let array = this.state.roomCustomerList;
2037
2409
  let newArray = [...array];
2038
2410
  newArray.push({
@@ -2048,8 +2420,6 @@ class Video extends Component {
2048
2420
  config_param = {
2049
2421
  subscribe_video_id: 'video21',
2050
2422
  subscribe_audio_id: 'audio21',
2051
- subscribe_streamId_id: 'subscribe_streamId21',
2052
- feedId_id: 'feedId21',
2053
2423
  feedId: itemOne.feedId
2054
2424
  }
2055
2425
 
@@ -2063,8 +2433,6 @@ class Video extends Component {
2063
2433
  config_param = {
2064
2434
  subscribe_video_id: 'video20',
2065
2435
  subscribe_audio_id: 'audio20',
2066
- subscribe_streamId_id: 'subscribe_streamId20',
2067
- feedId_id: 'feedId20',
2068
2436
  feedId: itemOne.feedId
2069
2437
  }
2070
2438
 
@@ -2080,7 +2448,6 @@ class Video extends Component {
2080
2448
  config_param = {
2081
2449
  subscribe_video_id: 'video'+i,
2082
2450
  subscribe_audio_id: 'audio'+i,
2083
- subscribe_streamId_id: 'subscribe_streamId'+i,
2084
2451
  feedId_id: 'feedId'+i,
2085
2452
  feedId: itemOne.feedId
2086
2453
  }
@@ -2093,6 +2460,7 @@ class Video extends Component {
2093
2460
  console.log(config_param)
2094
2461
  console.log('发起订阅')
2095
2462
  this.test_controller.Subscribe(config_param)
2463
+ document.getElementById(config_param.subscribe_video_id).name = 'temp'
2096
2464
 
2097
2465
  }
2098
2466
  })
@@ -2110,22 +2478,19 @@ class Video extends Component {
2110
2478
  this.test_controller.OnNewPublish = (feed) => {
2111
2479
  console.log('有新发布者', feed);
2112
2480
  console.log(new Date())
2113
- callNimIM('sendCustomCmdMsg', {
2114
- customId: this.state.imRoomId,
2115
- content: JSON.stringify({
2481
+ if (feed.tag && feed.tag.includes('UnSubscribe_RM')) {
2482
+ console.log('过滤订阅的tag:', feed.tag)
2483
+ return
2484
+ }
2485
+ this.sendMessage({
2116
2486
  'typeId': 1013,
2117
2487
  'muteStatus': this.state.voiceStatue ? 1 : 0,
2118
2488
  'data': {
2119
2489
  'sessionId': this.state.sessionId,
2120
2490
  'userId': this.props.tellerAccount
2121
2491
  }
2122
- })
2123
- }, function (code, message, data) {
2124
- console.log(data)
2125
2492
  })
2126
- callNimIM('sendCustomCmdMsg', {
2127
- customId: this.state.imRoomId,
2128
- content: JSON.stringify({
2493
+ this.sendMessage({
2129
2494
  'typeId': 1014,
2130
2495
  'sessionId': this.state.sessionId,
2131
2496
  'meetingInfo': {
@@ -2134,9 +2499,6 @@ class Video extends Component {
2134
2499
  'customers': this.props.meetingInfo.customers,
2135
2500
  'otherAttendees': this.props.meetingInfo.otherAttendees
2136
2501
  }
2137
-
2138
- })
2139
- }, function (code, message, data) {
2140
2502
  })
2141
2503
  this.sendNotification()
2142
2504
  let array = this.state.roomCustomerList;
@@ -2155,8 +2517,6 @@ class Video extends Component {
2155
2517
  config_param = {
2156
2518
  subscribe_video_id: 'video21',
2157
2519
  subscribe_audio_id: 'audio21',
2158
- subscribe_streamId_id: 'subscribe_streamId21',
2159
- feedId_id: 'feedId21',
2160
2520
  feedId: feed.feedId
2161
2521
  }
2162
2522
 
@@ -2176,8 +2536,6 @@ class Video extends Component {
2176
2536
  config_param = {
2177
2537
  subscribe_video_id: 'video20',
2178
2538
  subscribe_audio_id: 'audio20',
2179
- subscribe_streamId_id: 'subscribe_streamId20',
2180
- feedId_id: 'feedId20',
2181
2539
  feedId: feed.feedId
2182
2540
  }
2183
2541
 
@@ -2199,7 +2557,6 @@ class Video extends Component {
2199
2557
  config_param = {
2200
2558
  subscribe_video_id: 'video'+i,
2201
2559
  subscribe_audio_id: 'audio'+i,
2202
- subscribe_streamId_id: 'subscribe_streamId'+i,
2203
2560
  feedId_id: 'feedId'+i,
2204
2561
  feedId: feed.feedId
2205
2562
  }
@@ -2223,14 +2580,11 @@ class Video extends Component {
2223
2580
  this.test_controller.OnUnPublishSucc = (sid) => {
2224
2581
  console.log('取消发布成功', sid, document.getElementById('publish_video1').name)
2225
2582
  if (document.getElementById('publish_video1').name && sid != document.getElementById('publish_video1').name) {
2226
- callNimIM('sendCustomCmdMsg', {
2227
- customId: this.state.imRoomId,
2228
- content: JSON.stringify({
2583
+ this.sendMessage({
2229
2584
  'typeId': 2030,
2230
2585
  'sessionId': this.state.sessionId,
2231
2586
  'sharedScreen': 0,
2232
2587
  'tellerId': this.props.tellerAccount
2233
- })
2234
2588
  })
2235
2589
  this.state.isSharedScreen = false
2236
2590
  this.setState({
@@ -2329,13 +2683,17 @@ class Video extends Component {
2329
2683
  // let audio = new Audio(src)
2330
2684
  // audio.play()
2331
2685
  // }
2686
+ if (participant.includes('UnHint')){
2687
+ console.log('过滤掉的uid', participant)
2688
+ return
2689
+ }
2332
2690
 
2333
2691
 
2334
2692
  this.appGetUsernameClick(participant).then((res) => {
2335
2693
  console.log('退出房间者', res)
2336
2694
  let data = res ? res.username ? res.username : '客户' : '客户'
2337
2695
  console.log(data)
2338
- this.messageClick((data + '已退出会议'), 'error')
2696
+ // this.messageClick((data + '已退出会议'), 'error')
2339
2697
  this.saveLog(data + ' leave room')
2340
2698
  if (res.userType == 1) {
2341
2699
  // 2--坐席  1--客户
@@ -2348,12 +2706,14 @@ class Video extends Component {
2348
2706
  let audio = new Audio(src)
2349
2707
  audio.play()
2350
2708
  }
2709
+ this.messageClick(('客户已退出会议'), 'error')
2351
2710
  } else if (res.userType == 2) {
2352
2711
  if (this.props.isOpenSound) {
2353
2712
  let src = internalLeft
2354
2713
  let audio = new Audio(src)
2355
2714
  audio.play()
2356
2715
  }
2716
+ this.messageClick(('内部人员已退出会议'), 'error')
2357
2717
  }
2358
2718
  // console.log('退出房间者',res)
2359
2719
  // let data = res? res : '客户'
@@ -2366,44 +2726,105 @@ class Video extends Component {
2366
2726
  this.test_controller.OnNetworkWeak = (bpsSend, bpsRecv, sid) => {
2367
2727
  console.log('弱网回调', bpsSend, bpsRecv, sid)
2368
2728
  if (sid == document.getElementById('publish_video1').name) {
2369
- this.messageClick('当前网络环境较差', 'error')
2370
- this.saveLog('mrtc OnNetworkWeak')
2729
+
2730
+ this.detectNetworkWeak().then((isWeak) => {
2731
+ console.log('弱网结果:' + isWeak)
2732
+ if (isWeak) {
2733
+ this.messageClick('当前网络环境较差', 'error')
2734
+ this.saveLog('mrtc OnNetworkWeak')
2735
+ this.saveVideoPoint('wnd', 'RM端弱网');
2736
+ if (this.props.isWeakSound && this.state.ablePlayNetweakAudio) {
2737
+ this.state.ablePlayNetweakAudio = false;
2738
+ let src = networkWeakAudio
2739
+ let audio = new Audio(src)
2740
+ audio.play()
2741
+ setTimeout(() => {
2742
+ this.state.ablePlayNetweakAudio = true;
2743
+ }, 30000);
2744
+ }
2745
+ if (this.props.OnNetworkWeak) {
2746
+ this.props.OnNetworkWeak(bpsSend, bpsRecv, sid)
2747
+ }
2748
+ }
2749
+ })
2750
+
2371
2751
  }
2372
2752
  };
2373
2753
  // 开始服务端录制成功
2374
- this.test_controller.OnStartRemoteRecordSucc = (record_id) => {
2375
- console.log('开始服务端录制成功', record_id);
2376
- this.state.recordId = record_id
2377
- this.videoRecordCallback('1', true)
2378
- this.saveLog('mrtc OnStartRemoteRecordSucc')
2754
+ this.test_controller.OnStartRemoteRecordSucc = (record_id, record_third_id) => {
2755
+ console.log('开始服务端录制成功', record_id, record_third_id);
2756
+ if (!record_third_id) {
2757
+ // 全局录制
2758
+ this.state.recordId = record_id
2759
+ this.videoRecordCallback('1', true)
2760
+ this.saveLog('mrtc OnStartRemoteRecordSucc')
2761
+ } else {
2762
+ // 业务录制
2763
+ this.state.businessRecordId = record_id
2764
+ this.businessRecordCallback('1', true, record_third_id)
2765
+ this.saveLog('mrtc OnStartRemoteBusinessRecordSucc, businessId=' + record_third_id)
2766
+ }
2767
+
2768
+ if (this.state.isRecordingeErrorModalVisible) {
2769
+ this.setState({
2770
+ isRecordingeErrorModalVisible: false
2771
+ })
2772
+ }
2379
2773
  };
2380
2774
  // 开始服务端录制失败
2381
2775
  this.test_controller.OnStartRemoteRecordFailed = (
2382
2776
  record_id,
2383
2777
  err_code,
2384
- err_msg
2778
+ err_msg,
2779
+ record_third_id
2385
2780
  ) => {
2386
- this.videoRecordCallback('1', false)
2387
- console.log('开始服务端录制失败', record_id, err_code, err_msg)
2388
- this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2781
+ console.log('开始服务端录制失败', record_id, err_code, err_msg, record_third_id)
2782
+ if (!record_third_id) {
2783
+ this.videoRecordCallback('1', false)
2784
+ this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
2785
+ } else {
2786
+ this.businessRecordCallback('1', false, record_third_id)
2787
+ this.saveLog('mrtc OnStartRemoteBusinessRecordFailed, code='+err_code + ',businessId=' + record_third_id)
2788
+ }
2389
2789
  };
2390
2790
  // 结束服务端录制成功
2391
- this.test_controller.OnStopRemoteRecordSucc = (recordId) => {
2392
- console.log('结束服务端录制成功', recordId);
2393
- this.videoRecordCallback('2', true)
2394
- this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2395
- // this.endSessionValue()
2791
+ this.test_controller.OnStopRemoteRecordSucc = (recordId, record_third_id) => {
2792
+ console.log('结束服务端录制成功', recordId, record_third_id);
2793
+ // 重进会议前端会丢失之前的third_id,从服务端去取
2794
+ if (!record_third_id && third_id_Map.get(recordId)) {
2795
+ record_third_id = third_id_Map.get(recordId)
2796
+ }
2797
+ if (!record_third_id) {
2798
+ this.videoRecordCallback('2', true)
2799
+ this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2800
+ this.state.recordId = '';
2801
+ } else {
2802
+ this.businessRecordCallback('2', true, record_third_id)
2803
+ this.saveLog('mrtc OnStopRemoteBusinessRecordSucc, recordId='+recordId + ',businessId=' + record_third_id)
2804
+ this.state.businessRecordId = '';
2805
+ }
2396
2806
  // 获取服务端录制结果
2397
2807
  };
2398
2808
  // 结束服务端录制失败
2399
2809
  this.test_controller.OnStopRemoteRecordFailed = (
2400
2810
  recordId,
2401
2811
  err_code,
2402
- err_msg
2812
+ err_msg,
2813
+ record_third_id
2403
2814
  ) => {
2404
- this.videoRecordCallback('2', false)
2405
- console.log('结束服务端录制失败', recordId, err_code, err_msg)
2406
- this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2815
+ console.log('结束服务端录制失败', recordId, err_code, err_msg, record_third_id)
2816
+ // 重进会议前端会丢失之前的third_id,从服务端去取
2817
+ if (!record_third_id && third_id_Map.get(recordId)) {
2818
+ record_third_id = third_id_Map.get(recordId)
2819
+ }
2820
+ if (!record_third_id) {
2821
+ this.videoRecordCallback('2', false)
2822
+ this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
2823
+ } else {
2824
+ this.businessRecordCallback('2', false, record_third_id)
2825
+ this.saveLog('mrtc OnStopRemoteBusinessRecordFailed, err_code='+err_code+',businessId=' + record_third_id)
2826
+ }
2827
+
2407
2828
  };
2408
2829
  // 开启浏览器录制成功
2409
2830
  this.test_controller.OnClientStartRecordSuccess = (
@@ -2467,6 +2888,28 @@ class Video extends Component {
2467
2888
  msg
2468
2889
  ) => {
2469
2890
  console.log('服务端录制失败通知', recordId, feedId, code, msg)
2891
+ this.saveLog(`recording error, recordId=${recordId}`)
2892
+
2893
+ // 如果在业务双录中,需要重新开启;如果是full录制出错,则不用处理
2894
+ if (this.state.businessRecordId == recordId) {
2895
+ // 录制中断
2896
+ this.messageClick('双录异常中断,请重新开启', 'error')
2897
+ this.setState({
2898
+ isRecordingeErrorModalVisible: true,
2899
+ businessRecordId: '',
2900
+ })
2901
+ // 循环播放录制中断语音
2902
+ clearTimeout(this.recordLoopPlay)
2903
+ this.recordLoopPlay = () => {
2904
+ console.log('loop recordId', this.state.recordId, 'businessRecordId ', this.state.businessRecordId)
2905
+ if(!this.state.businessRecordId && document.getElementById("publish_video1")){
2906
+ let audio = new Audio(recordErrorAudio)
2907
+ audio.play()
2908
+ setTimeout(this.recordLoopPlay, 3000);
2909
+ }
2910
+ }
2911
+ setTimeout(this.recordLoopPlay, 0);
2912
+ }
2470
2913
  };
2471
2914
  // 停止浏览器录制成功回调
2472
2915
  this.test_controller.OnClientStopRecordSuccess = (
@@ -2526,6 +2969,23 @@ class Video extends Component {
2526
2969
  ) => {
2527
2970
  console.log('下载失败', clientRecordId, code, msg)
2528
2971
  };
2972
+ // 日志上传成功
2973
+ this.test_controller.OnUploadLogSucc = (filePath) => {
2974
+ // 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'
2975
+
2976
+ console.info('OnUploadLogSucc', filePath)
2977
+ this.saveLog('mrtc OnUploadLogSucc, filePath=' + filePath)
2978
+
2979
+ // const exp1 = /.+\.log/g
2980
+ // const url = filePath.match(exp1)[0]
2981
+ // console.log(url)
2982
+ this.uploadLogCallback(filePath)
2983
+ };
2984
+ this.test_controller.OnUploadLogFail = (code, err_msg) => {
2985
+ // test_controller.trace(`upload log failed, err_code=${code}, err_msg=${JSON.stringify(err_msg)}`);
2986
+ console.info('OnUploadLogFail', code, err_msg)
2987
+ this.saveLog('mrtc OnUploadLogFail, code=' + code, ',msg=' + err_msg)
2988
+ };
2529
2989
  // 切流成功通知
2530
2990
  this.test_controller.OnChangeMediaStreamSuccess = (sid) => {
2531
2991
  console.log('切流成功通知', sid);
@@ -2686,7 +3146,7 @@ class Video extends Component {
2686
3146
  }
2687
3147
  // 停止共享
2688
3148
  this.test_controller.OnDesktopDisplayClosed = () => {
2689
- console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen)
3149
+ console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen, streamShare)
2690
3150
 
2691
3151
  if (this.state.isScreenSwitching) {
2692
3152
  this.state.isScreenSwitching = false
@@ -2715,13 +3175,155 @@ class Video extends Component {
2715
3175
 
2716
3176
 
2717
3177
  };
3178
+
3179
+ const that = this;
3180
+ this.asr_controller.OnGetSign = function(bizName, subBiz, uid) {
3181
+ return 'signature'
3182
+ }
3183
+ // 连接成功回调
3184
+ this.asr_controller.OnAsrConnectOK = function() {
3185
+ // 需要状态控制
3186
+ if (media_status == 1) {
3187
+ return
3188
+ }
3189
+
3190
+ const config_param = {}
3191
+ const biz_name = 'demo'
3192
+ const sub_biz = 'default'
3193
+ const uid = that.props.tellerAccount
3194
+ const sampleRate = 16000
3195
+ const procType = 8
3196
+ config_param.bizName = biz_name
3197
+ config_param.subBiz = sub_biz
3198
+ config_param.uid = uid
3199
+ config_param.sampleRate = sampleRate
3200
+ config_param.procType = procType
3201
+ config_param.mediaStreamType = 2 // 1:麦克风;2:传stream
3202
+ // console.log(test_controller.GetMediaInfo(document.getElementById('publish_video1').name).audio_)
3203
+ config_param.audio_ = that.test_controller.GetMediaInfo(document.getElementById('publish_video1').name).audio_
3204
+ config_param.idleTime = 6 // 12s没有识别结果返回通知上层
3205
+ config_param.tag = 'asr_tag0'
3206
+ that.asr_sid = that.asr_controller.TurnOnMicrophone(config_param, config_param.audio_)
3207
+ }
3208
+ // 初始化成功
3209
+ this.asr_controller.OnInitOk = function(sid, tag) {
3210
+ console.log('OnInitOk:')
3211
+ media_status = 1
3212
+ }
3213
+
3214
+ // 初始化失败
3215
+ this.asr_controller.OnInitError = function(sid, code, msg, tag) {
3216
+ console.log('OnInitError:' + msg)
3217
+ that.asr_sid = ''
3218
+ }
3219
+
3220
+ // 识别结果
3221
+ this.asr_controller.OnAsrMessage = function(msg, sid, tag, status) {
3222
+ that.asr_controller.trace(`OnAsrMessage sid=${sid},status=${status},tag=${tag}`)
3223
+ const parse = JSON.parse(msg)
3224
+ const resultValue = parse.value
3225
+ const sentence_id = parse.sentence_id
3226
+ // sentence_id相同,取最后一个值
3227
+ let text = resultValue || ''
3228
+ const sensitiveArr = that.props.sensitiveWords
3229
+ // const regex = new RegExp(sensitiveArr.join('|'), 'g') // /\#{(.+?)\}/g;
3230
+ // text = text.replace(regex, function(r) { return '<span style="background: red;">' + r + '</span>' })
3231
+ let matchArr = sensitiveArr.filter(el => text.includes(el));
3232
+ if (matchArr.length>0) {
3233
+ matchArr.forEach(el => {
3234
+ that.messageClick('检测到敏感词:' + matchArr, 'error')
3235
+ that.state.sensitiveTitle = '检测到敏感词:' + matchArr
3236
+ clearTimeout(that.state.sensitiveTitleTimer)
3237
+ that.state.sensitiveTitleTimer = setTimeout(() => {
3238
+ that.state.sensitiveTitle = ''
3239
+ }, 3000);
3240
+ if (!that.state.sensitiveRecordMap[sentence_id] || !that.state.sensitiveRecordMap[sentence_id].includes(el)){
3241
+ API.addSensitiveRecord({
3242
+ tellerId: that.props.tellerAccount,
3243
+ sessionId: that.state.sessionId,
3244
+ sensitiveWord: el
3245
+ });
3246
+ if (!that.state.sensitiveRecordMap[sentence_id]) {
3247
+ that.state.sensitiveRecordMap[sentence_id] = []
3248
+ }
3249
+ that.state.sensitiveRecordMap[sentence_id].push(el)
3250
+ }
3251
+ })
3252
+ }
3253
+ // that.AsrResultText = text
3254
+ }
3255
+
3256
+ // 停止录音回调
3257
+ this.asr_controller.OnTurnOffMicrophoneOK = function(sid, tag) {
3258
+ media_status = 0
3259
+ that.asr_controller.Disconnect()
3260
+ }
3261
+ this.asr_controller.OnAsrMsgIdle = function(sid, tag) {
3262
+ // that.AsrResultText = ''
3263
+ that.asr_controller.trace('OnAsrMsgIdle')
3264
+ }
3265
+ this.asr_controller.OnAsrDisconnectOK = function() {
3266
+ that.asr_controller.trace('Disconnect is success')
3267
+ }
3268
+
3269
+ }
3270
+ startASR() {
3271
+ // const publish_sid = document.getElementById('publish_video1').name
3272
+
3273
+ if (media_status == 1) {
3274
+ return
3275
+ }
3276
+ this.asr_controller.Connect(this.props.asrServerUrl)
3277
+ message.success({
3278
+ content: '敏感词检测已开启',
3279
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
3280
+ className: 'successClassName',
3281
+ top: 200,
3282
+ // duration: 10
3283
+ })
3284
+ this.state.isAsrStart = true
3285
+ this.state.sensitiveRecordMap = {}
3286
+ // this.AsrResultText = ''
3287
+ }
3288
+ stopASR() {
3289
+ this.state.isAsrStart = false
3290
+ // this.AsrResultText = ''
3291
+ // const { publish_sid } = this.getSidsInfo()
3292
+ if (media_status == 0) {
3293
+ return
3294
+ }
3295
+ this.asr_controller.TurnOffMicrophone(this.asr_sid)
3296
+ // clearInterval(this.asrTimer)
3297
+ // if (this.localRecordStatus && this.client_record_id) {
3298
+ // test_controller.StopRecord(this.client_record_id)
3299
+ // }
3300
+ message.success({
3301
+ content: '敏感词检测已关闭',
3302
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
3303
+ className: 'successClassName',
3304
+ top: 200,
3305
+ // duration: 10
3306
+ })
2718
3307
  }
3308
+ // 全局录制
2719
3309
  videoRecordCallback = async (type, status) => {
3310
+ if (status) {
3311
+ // 全局录制且开启成功,通知app
3312
+ this.sendMessage({
3313
+ 'typeId': 1030,
3314
+ 'type': type,
3315
+ 'sessionId': this.state.sessionId,
3316
+ 'recordId': this.state.recordId
3317
+ })
3318
+ }
2720
3319
  try {
2721
3320
  let result = await API.videoRecordCallback({
2722
3321
  activityId: this.props.businessNumber,
2723
3322
  sessionId: this.state.sessionId,
2724
3323
  roomId: this.state.channelId + '',
3324
+ appId: this.state.appId,
3325
+ recordId: this.state.recordId,
3326
+ customerId: this.props.customerId,
2725
3327
  type: type,
2726
3328
  status: status
2727
3329
  });
@@ -2732,6 +3334,52 @@ class Video extends Component {
2732
3334
  }
2733
3335
  }
2734
3336
  }
3337
+ // 业务录制回调
3338
+ businessRecordCallback = async (type, status, businessId) => {
3339
+ if (status) {
3340
+ this.sendMessage({
3341
+ 'typeId': 1031,
3342
+ 'type': type,
3343
+ 'id': businessId,
3344
+ 'sessionId': this.state.sessionId,
3345
+ 'recordId': this.state.recordId,
3346
+ 'businessRecordId': this.state.businessRecordId
3347
+ })
3348
+ }
3349
+ try {
3350
+ let result = await API.videoRecordCallback({
3351
+ activityId: this.props.businessNumber,
3352
+ sessionId: this.state.sessionId,
3353
+ roomId: this.state.channelId + '',
3354
+ id: businessId,
3355
+ appId: this.state.appId,
3356
+ recordId: this.state.businessRecordId,
3357
+ customerId: this.props.customerId,
3358
+ type: type,
3359
+ status: status
3360
+ });
3361
+ console.log(result);
3362
+ } catch (err) {
3363
+ console.error(err);
3364
+ if (err.status == 502 || err.status == 404) {
3365
+ }
3366
+ }
3367
+ }
3368
+ uploadLogCallback = async (url) => {
3369
+ try {
3370
+ let result = await API.uploadLogCallback({
3371
+ activityId: this.props.businessNumber,
3372
+ sessionId: this.state.sessionId,
3373
+ roomId: this.state.channelId + '',
3374
+ tellerAccount: this.props.tellerAccount,
3375
+ fileUrl: url
3376
+ });
3377
+ } catch (err) {
3378
+ // console.error(err);
3379
+ if (err.status == 502 || err.status == 404) {
3380
+ }
3381
+ }
3382
+ }
2735
3383
  // 保存mettingInfo
2736
3384
  updateMeetingInfo = async () => {
2737
3385
  let customers
@@ -2763,10 +3411,9 @@ class Video extends Component {
2763
3411
  type: '2'
2764
3412
  });
2765
3413
  console.log(result);
3414
+ this.queryRecordStatus()
2766
3415
  this.appGetUsername(document.getElementById('publish_video1').name)
2767
- callNimIM('sendCustomCmdMsg', {
2768
- customId: this.state.imRoomId,
2769
- content: JSON.stringify({
3416
+ this.sendMessage({
2770
3417
  'typeId': 1014,
2771
3418
  'sessionId': this.state.sessionId,
2772
3419
  'meetingInfo': {
@@ -2775,9 +3422,6 @@ class Video extends Component {
2775
3422
  'customers': this.props.meetingInfo.customers,
2776
3423
  'otherAttendees': this.props.meetingInfo.otherAttendees
2777
3424
  }
2778
-
2779
- })
2780
- }, function (code, message, data) {
2781
3425
  })
2782
3426
  } catch (err) {
2783
3427
  console.error(err);
@@ -2800,12 +3444,19 @@ class Video extends Component {
2800
3444
  console.error(err)
2801
3445
  }
2802
3446
  }
2803
- if (this.state.imStatus) {
2804
- console.log('disconnect断开连接')
2805
- this.state.manualClose = true
2806
- disconnect();
3447
+ if (this.state.isAsrStart){
3448
+ this.stopASR()
3449
+ this.asr_controller.Disconnect()
3450
+ }
3451
+ if (this.state.isPictureInPicture) {
3452
+ document.exitPictureInPicture()
2807
3453
  }
2808
3454
  message.destroy()
3455
+ clearTimeout(this.loopPlay)
3456
+ clearTimeout(this.recordLoopPlay)
3457
+ clearInterval(this.state.drawCanvasInterval)
3458
+ clearInterval(this.state.faceDetectionTimer);
3459
+ clearInterval(this.state.imageDetectionTimer);
2809
3460
  }
2810
3461
  finishSession = () => {
2811
3462
  // clearInterval(this.state.OnVolumeAnalyserMap.get(sid))
@@ -2862,6 +3513,21 @@ class Video extends Component {
2862
3513
  this.roomCallBack(2, '获取tiken失败', 'SYS-01')
2863
3514
  }
2864
3515
  }
3516
+ queryBranchName = async () => {
3517
+ try {
3518
+ let result = await API.getBranchName({
3519
+ branchCode: this.props.salesBranchCode
3520
+ })
3521
+ this.setState({
3522
+ branchName: result.branchName || ''
3523
+ })
3524
+ console.log('branchName', this.state.branchName)
3525
+ } catch (err) {
3526
+ console.error(err);
3527
+
3528
+ }
3529
+ }
3530
+
2865
3531
  getRoomStatus = async data => {
2866
3532
  try {
2867
3533
  let result = await API.getRoomStatus({
@@ -2909,7 +3575,7 @@ class Video extends Component {
2909
3575
  loading: true,
2910
3576
  })
2911
3577
  const that = this
2912
- axios.get(this.props.resourcePath + "/mcu.js")
3578
+ axios.get(this.props.resourcePath + `/mcu.js?v=${SDK_VERISON}`)
2913
3579
  .then(response => this.addToScriptClick()).catch(function (error) {
2914
3580
  console.log(error);
2915
3581
  that.state.sessionType = false
@@ -2923,36 +3589,50 @@ class Video extends Component {
2923
3589
 
2924
3590
  }
2925
3591
  addToScriptClick = () => {
3592
+ let params = `?v=${SDK_VERISON}`
2926
3593
  const _dependScripts = [
2927
- this.props.resourcePath + "/beauty/beauty_frame_pkg.js",
2928
- this.props.resourcePath + "/adapter.js",
2929
- this.props.resourcePath + "/getMediaInfo.js",
2930
- this.props.resourcePath + "/EBML.js",
2931
- this.props.resourcePath + "/mcu.js",
2932
- this.props.resourcePath + "/meeting_desk_stream.js",
2933
- this.props.resourcePath + "/meeting_html_stream.js",
2934
- this.props.resourcePath + "/meeting_file_stream.js",
2935
- this.props.resourcePath + "/meeting_im.js",
2936
- this.props.resourcePath + "/meeting_vod.js",
2937
- this.props.resourcePath + "/meeting_invite.js",
2938
- this.props.resourcePath + "/client_record.js",
2939
- this.props.resourcePath + "/remote_record.js",
2940
- this.props.resourcePath + "/meeting_camera_stream.js",
2941
- this.props.resourcePath + "/meeting_api.js",
2942
-
2943
- this.props.resourcePath + "/eruda.js",
2944
- this.props.resourcePath + "/iconfont.js",
2945
- this.props.resourcePath + "/html2canvas.js",
2946
- this.props.resourcePath + "/dom-to-image.js",
2947
-
2948
- this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js",
2949
- this.props.resourcePath + "/hs/hs_human_segmentation.js",
2950
- this.props.resourcePath + "/hs/hs_human_segmentation.wasm",
2951
-
2952
- this.props.resourcePath + "/mix/mix_frame.js",
2953
- this.props.resourcePath + "/mix/pageBoard.js"
3594
+ // this.props.resourcePath + "/opencv.js" + params,
3595
+ this.props.resourcePath + "/asr_api.js" + params,
3596
+ this.props.resourcePath + "/reconnecting-websocket.min.js" + params,
3597
+ this.props.resourcePath + "/resampler.js" + params,
3598
+ this.props.resourcePath + "/beauty/beauty_frame_pkg.js" + params,
3599
+ this.props.resourcePath + "/adapter.js" + params,
3600
+ this.props.resourcePath + "/getMediaInfo.js" + params,
3601
+ this.props.resourcePath + "/EBML.js" + params,
3602
+ this.props.resourcePath + "/mcu.js" + params,
3603
+ this.props.resourcePath + "/meeting_desk_stream.js" + params,
3604
+ this.props.resourcePath + "/meeting_html_stream.js" + params,
3605
+ this.props.resourcePath + "/meeting_file_stream.js" + params,
3606
+ this.props.resourcePath + "/meeting_im.js" + params,
3607
+ this.props.resourcePath + "/meeting_vod.js" + params,
3608
+ this.props.resourcePath + "/meeting_invite.js" + params,
3609
+ this.props.resourcePath + "/client_record.js" + params,
3610
+ this.props.resourcePath + "/remote_record.js" + params,
3611
+ this.props.resourcePath + "/meeting_camera_stream.js" + params,
3612
+ this.props.resourcePath + "/meeting_api.js" + params,
3613
+
3614
+ this.props.resourcePath + "/eruda.js" + params,
3615
+ this.props.resourcePath + "/iconfont.js" + params,
3616
+ this.props.resourcePath + "/html2canvas.js" + params,
3617
+ this.props.resourcePath + "/dom-to-image.js" + params,
3618
+
3619
+ this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js" + params,
3620
+ this.props.resourcePath + "/hs/hs_human_segmentation.js" + params,
3621
+ this.props.resourcePath + "/hs/hs_human_segmentation.wasm" + params,
3622
+
3623
+ this.props.resourcePath + "/mix/mix_frame.js" + params,
3624
+ this.props.resourcePath + "/mix/pageBoard.js" + params,
2954
3625
 
2955
3626
  ]
3627
+ try{
3628
+ if (!cv){
3629
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3630
+ }
3631
+ } catch(err) {
3632
+ console.log(err)
3633
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3634
+ }
3635
+
2956
3636
  const that = this
2957
3637
  let i = 0
2958
3638
  scriptAdd()
@@ -2967,13 +3647,15 @@ class Video extends Component {
2967
3647
  if (document.all) { //如果是IE
2968
3648
  script.onreadystatechange = () => {
2969
3649
  if (script.readyState == 'loaded' || script.readyState == 'complete') {
2970
- that.test_controller = new McuController();
3650
+ that.test_controller = new MeetingController();
3651
+ that.asr_controller = new AsrController()
2971
3652
  that.mountClick()
2972
3653
  }
2973
3654
  }
2974
3655
  } else {
2975
3656
  script.onload = () => {
2976
- that.test_controller = new McuController();
3657
+ that.test_controller = new MeetingController();
3658
+ that.asr_controller = new AsrController()
2977
3659
  that.mountClick()
2978
3660
  }
2979
3661
  }
@@ -2996,7 +3678,7 @@ class Video extends Component {
2996
3678
  }
2997
3679
  }
2998
3680
  componentWillMount() {
2999
- console.log('hsbc_teller_sdk', '2.0.1')
3681
+ console.log('hsbc_teller_sdk', SDK_VERISON)
3000
3682
  let arr = []
3001
3683
  for(let i=1;i<=12;i++){
3002
3684
  arr.push({
@@ -3010,6 +3692,18 @@ class Video extends Component {
3010
3692
  }
3011
3693
  this.setState({
3012
3694
  videoList: arr
3695
+ }, () => {
3696
+ // 设置播放回调
3697
+ for(let i=1;i<=12;i++){
3698
+ let dom = document.getElementById('video'+ i)
3699
+ dom.addEventListener("loadedmetadata", (event) => {
3700
+ console.log('video'+ i +' loadedmetadata:' + dom.srcObject.id)
3701
+ this.saveLog('video'+ i +' loadedmetadata, id=' + dom.srcObject.id)
3702
+ // let arrItem = this.state.videoList.find(el => el.idIndex == i) || {}
3703
+ // console.log(arrItem.videoName)
3704
+
3705
+ });
3706
+ }
3013
3707
  })
3014
3708
  if (this.props.sessionId) {
3015
3709
  this.getRoomStatus({
@@ -3018,6 +3712,10 @@ class Video extends Component {
3018
3712
  } else {
3019
3713
  this.addToScript()
3020
3714
  }
3715
+
3716
+ if (this.props.salesBranchCode) {
3717
+ this.queryBranchName()
3718
+ }
3021
3719
  }
3022
3720
 
3023
3721
  voice = () => {
@@ -3035,20 +3733,15 @@ class Video extends Component {
3035
3733
  sid = document.getElementById('publish_streamId1').name
3036
3734
  }
3037
3735
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3038
- callNimIM('sendCustomCmdMsg', {
3039
- customId: this.state.imRoomId,
3040
- content: JSON.stringify({
3736
+ this.saveVideoPoint('mute', 'RM端静音')
3737
+ this.sendMessage({
3041
3738
  'typeId': 1013,
3042
3739
  'muteStatus': 1,
3043
3740
  'data': {
3044
3741
  'sessionId': this.state.sessionId,
3045
3742
  'userId': this.props.tellerAccount
3046
3743
  }
3047
- })
3048
- }, function (code, message, data) {
3049
- console.log(data)
3050
3744
  })
3051
-
3052
3745
  } else if (this.state.voiceStatue) {
3053
3746
  // 打开本地
3054
3747
  this.setState({
@@ -3062,22 +3755,51 @@ class Video extends Component {
3062
3755
  sid = document.getElementById('publish_streamId1').name
3063
3756
  }
3064
3757
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3065
- callNimIM('sendCustomCmdMsg', {
3066
- customId: this.state.imRoomId,
3067
- content: JSON.stringify({
3758
+ this.saveVideoPoint('mute', 'RM端解除静音')
3759
+ this.sendMessage({
3068
3760
  'typeId': 1013,
3069
3761
  'muteStatus': 0,
3070
3762
  'data': {
3071
3763
  'sessionId': this.state.sessionId,
3072
3764
  'userId': this.props.tellerAccount
3073
3765
  }
3074
- })
3075
- }, function (code, message, data) {
3076
- console.log(data)
3077
3766
  })
3078
3767
  }
3768
+ if (this.state.isPictureInPicture) {
3769
+ setTimeout(() => {
3770
+ this.pictureInPicture('Refresh')
3771
+ }, 0);
3772
+ }
3079
3773
  }
3080
3774
  };
3775
+ queryRecordStatus = async()=>{
3776
+ try {
3777
+ let result = await API.getRecordStatus({
3778
+ roomId: this.state.channelId + ''
3779
+ });
3780
+ console.log('RecordStatus', result)
3781
+ if (result.fullRecordStatus == 1) { // 1开启 2未开启
3782
+ // 全局录制
3783
+ this.state.recordId = result.fullRecordId
3784
+ if (result.businessRecordStatus == 1){
3785
+ // 业务录制
3786
+ this.state.businessRecordId = result.businessRecordId;
3787
+ this.state.businessId = result.businessId;
3788
+ third_id_Map.set(result.businessRecordId, result.businessId);
3789
+ console.log(third_id_Map)
3790
+ if (this.props.whetherDetectFace) this.startFaceDetection();
3791
+ if (this.props.whetherDetectLight) this.startImageDetection();
3792
+ }
3793
+ } else {
3794
+ this.state.recordId = ''
3795
+ }
3796
+ } catch (err) {
3797
+ console.error(err);
3798
+ if(err.status == 502 || err.status== 404) {
3799
+ this.roomCallBack(2, '连接服务器失败','SYS-02')
3800
+ }
3801
+ }
3802
+ }
3081
3803
  isFileSuccuse = () => {
3082
3804
  if (!this.state.sessionId || !this.state.sessionType || !this.state.imStatus) {
3083
3805
  this.messageClick('当前程序异常请先退出重开', 'error')
@@ -3100,17 +3822,12 @@ class Video extends Component {
3100
3822
  sid = document.getElementById('publish_streamId1').name
3101
3823
  }
3102
3824
  this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
3103
- callNimIM('sendCustomCmdMsg', {
3104
- customId: this.state.imRoomId,
3105
- content: JSON.stringify({
3825
+ this.sendMessage({
3106
3826
  'typeId': 1012,
3107
3827
  'state': 0,
3108
3828
  'sessionId': this.state.sessionId,
3109
3829
  'userId': this.props.tellerAccount
3110
- })
3111
- }, function (code, message, data) {
3112
- console.log(data)
3113
- })
3830
+ })
3114
3831
  } else if (this.state.audioed) {
3115
3832
  this.state.audioed = false,
3116
3833
  this.setState({
@@ -3122,16 +3839,11 @@ class Video extends Component {
3122
3839
  sid = document.getElementById('publish_streamId1').name
3123
3840
  }
3124
3841
  this.test_controller.SetLocalVideoEnable(1, parseInt(sid, 10));
3125
- callNimIM('sendCustomCmdMsg', {
3126
- customId: this.state.imRoomId,
3127
- content: JSON.stringify({
3128
- 'typeId': 1012,
3129
- 'state': 1,
3130
- 'sessionId': this.state.sessionId,
3131
- 'userId': this.props.tellerAccount
3132
- })
3133
- }, function (code, message, data) {
3134
- console.log(data)
3842
+ this.sendMessage({
3843
+ 'typeId': 1012,
3844
+ 'state': 1,
3845
+ 'sessionId': this.state.sessionId,
3846
+ 'userId': this.props.tellerAccount
3135
3847
  })
3136
3848
  }
3137
3849
  }
@@ -3146,30 +3858,58 @@ class Video extends Component {
3146
3858
  streamShare = ''
3147
3859
  }
3148
3860
  if (this.state.isSharedScreen) {
3149
- const publish_config = {}
3861
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3862
+ setTimeout(() => {
3150
3863
  publish_config.media_type = 1
3151
3864
  publish_config.publish_device = 2
3865
+ publish_config.need_volume_analyser = true
3152
3866
  publish_config.video_profile_type = 1
3153
- // publish_config.video_profile_type=100
3154
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3867
+ publish_config.desktopStreamToCanvas = false
3155
3868
  publish_config.enableDesktopAudio = true
3156
3869
  publish_config.degradationType = 2
3157
- publish_config.desktopStreamToCanvas = false
3158
- publish_config.sid = document.getElementById('video20').name
3159
- this.test_controller.ChangeMediaStream(publish_config)
3160
- this.state.isScreenSwitching = true
3870
+ publish_config.publish_video_id = 'video20'
3871
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3872
+ publish_config.publish_tag = 'projectionWhiteboard'
3873
+ this.test_controller.Publish(publish_config)
3874
+ }, 300);
3875
+ // const publish_config = {}
3876
+ // publish_config.media_type = 1
3877
+ // publish_config.publish_device = 2
3878
+ // publish_config.video_profile_type = 1
3879
+ // // publish_config.video_profile_type=100
3880
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3881
+ // publish_config.enableDesktopAudio = true
3882
+ // publish_config.degradationType = 2
3883
+ // publish_config.desktopStreamToCanvas = false
3884
+ // publish_config.sid = document.getElementById('video20').name
3885
+ // this.test_controller.ChangeMediaStream(publish_config)
3886
+ // this.state.isScreenSwitching = true
3161
3887
  } else {
3162
3888
  if (document.getElementById('video20').name) {
3163
- publish_config.media_type = 1;
3164
- publish_config.publish_device = 2;
3165
- publish_config.video_profile_type = 1
3166
- // publish_config.video_profile_type=100
3167
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3168
- publish_config.enableDesktopAudio = true
3169
- publish_config.desktopStreamToCanvas = false
3170
- publish_config.degradationType = 2
3171
- publish_config.sid = document.getElementById('video20').name;
3172
- this.test_controller.ChangeMediaStream(publish_config);
3889
+ this.test_controller.UnPublish(document.getElementById('video20').name)
3890
+ setTimeout(() => {
3891
+ publish_config.media_type = 1
3892
+ publish_config.publish_device = 2
3893
+ publish_config.need_volume_analyser = true
3894
+ publish_config.video_profile_type = 1
3895
+ publish_config.desktopStreamToCanvas = false
3896
+ publish_config.enableDesktopAudio = true
3897
+ publish_config.degradationType = 2
3898
+ publish_config.publish_video_id = 'video20'
3899
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
3900
+ publish_config.publish_tag = 'projectionWhiteboard'
3901
+ this.test_controller.Publish(publish_config)
3902
+ }, 300);
3903
+ // publish_config.media_type = 1;
3904
+ // publish_config.publish_device = 2;
3905
+ // publish_config.video_profile_type = 1
3906
+ // // publish_config.video_profile_type=100
3907
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3908
+ // publish_config.enableDesktopAudio = true
3909
+ // publish_config.desktopStreamToCanvas = false
3910
+ // publish_config.degradationType = 2
3911
+ // publish_config.sid = document.getElementById('video20').name;
3912
+ // this.test_controller.ChangeMediaStream(publish_config);
3173
3913
  } else {
3174
3914
  publish_config.media_type = 1
3175
3915
  publish_config.publish_device = 2
@@ -3248,23 +3988,21 @@ class Video extends Component {
3248
3988
  sid = document.getElementById('publish_streamId1').name
3249
3989
  }
3250
3990
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10))
3991
+ this.saveVideoPoint('mute', 'RM端静音')
3251
3992
  } else {
3252
3993
  // 当前是
3253
3994
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3995
+ this.saveVideoPoint('mute', 'RM端解除静音')
3254
3996
  this.setState({
3255
3997
  voiceImg: voiceImgOpen,
3256
3998
  voiceName: '静音'
3257
3999
  })
3258
4000
  }
3259
- callNimIM('sendCustomCmdMsg', {
3260
- customId: this.state.imRoomId,
3261
- content: JSON.stringify({
3262
- 'typeId': 1011,
3263
- 'state': 1,
3264
- 'sessionId': this.state.sessionId,
3265
- 'userId': this.props.tellerAccount
3266
- })
3267
- }, function (code, message, data) {
4001
+ this.sendMessage({
4002
+ 'typeId': 1011,
4003
+ 'state': 1,
4004
+ 'sessionId': this.state.sessionId,
4005
+ 'userId': this.props.tellerAccount
3268
4006
  })
3269
4007
  } else {
3270
4008
  this.setState({
@@ -3273,41 +4011,42 @@ class Video extends Component {
3273
4011
  }
3274
4012
 
3275
4013
  };
4014
+ handleOkPictureConfirm = () => {
4015
+ this.pictureInPictureClick('add')
4016
+ this.setState({isPictureConfirmModalVisible: false})
4017
+ }
4018
+ handleOkRecordConfirm = () => {
4019
+ if (!this.state.isPictureInPicture) {
4020
+ this.pictureInPicture()
4021
+ }
4022
+ this.saveLog('Start business recording')
4023
+ this.enableServerRecording(this.state.businessId)
4024
+ }
3276
4025
  handleOk = () => {
3277
4026
  // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
3278
- callNimIM('sendCustomCmdMsg', {
3279
- customId: this.state.imRoomId,
3280
- content: JSON.stringify({
3281
- 'typeId': 1012,
3282
- 'state': 1,
3283
- 'sessionId': this.state.sessionId,
3284
- 'userId': this.props.tellerAccount
3285
- })
3286
- }, function (code, message, data) {
3287
- console.log(data)
3288
- });
4027
+ this.sendMessage({
4028
+ 'typeId': 1012,
4029
+ 'state': 1,
4030
+ 'sessionId': this.state.sessionId,
4031
+ 'userId': this.props.tellerAccount
4032
+ })
3289
4033
  this.setState({
3290
- isSuspend: true,
3291
- suspendName: '恢复'
3292
- });
3293
- callNimIM('sendCustomCmdMsg', {
3294
- customId: this.state.imRoomId,
3295
- content: JSON.stringify({
3296
- 'typeId': 1011,
3297
- 'state': 0,
3298
- 'sessionId': this.state.sessionId,
3299
- 'userId': this.props.tellerAccount
3300
- })
3301
- }, function (code, message, data) {
3302
- console.log(data)
4034
+ isSuspend: true,
4035
+ suspendName: '恢复'
3303
4036
  });
4037
+ this.sendMessage({
4038
+ 'typeId': 1011,
4039
+ 'state': 0,
4040
+ 'sessionId': this.state.sessionId,
4041
+ 'userId': this.props.tellerAccount
4042
+ })
3304
4043
  let sid = document.getElementById('publish_video1').name;
3305
4044
  if (!sid) {
3306
4045
  // 纯音频的时候sid在publish_streamId标签中
3307
4046
  sid = document.getElementById('publish_streamId1').name
3308
4047
  }
3309
4048
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3310
- this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
4049
+ this.saveVideoPoint('mute', 'RM端静音')
3311
4050
  this.setState({
3312
4051
  isModalVisible: false
3313
4052
  })
@@ -3487,6 +4226,9 @@ class Video extends Component {
3487
4226
  // videoList: this.state.videoList
3488
4227
  // })
3489
4228
  this.videoListSort();
4229
+ if (this.state.isPictureInPicture) {
4230
+ this.pictureInPicture('Refresh')
4231
+ }
3490
4232
  } else {
3491
4233
  console.log('1')
3492
4234
  this.messageClick('保持信息失败', 'error')
@@ -3511,15 +4253,12 @@ class Video extends Component {
3511
4253
  console.log('ocrCallback', result.data,val)
3512
4254
  // this.messageClick('姓名:' + result.data.idCardName + ',身份证号:' + result.data.idCardNumber,'success')
3513
4255
  // this.messageClick('识别成功','success')
3514
- callNimIM('sendCustomCmdMsg', {
3515
- customId: this.state.imRoomId,
3516
- content: JSON.stringify({
3517
- 'typeId': 1020,
3518
- 'sessionId': this.state.sessionId,
3519
- 'cameraState': 1,
3520
- "userId": this.state.faceCustomerUid
3521
- })
3522
- });
4256
+ this.sendMessage({
4257
+ 'typeId': 1020,
4258
+ 'sessionId': this.state.sessionId,
4259
+ 'cameraState': 1,
4260
+ "userId": this.state.faceCustomerUid
4261
+ })
3523
4262
  if(this.state.documentType == 'ID_CARD') {
3524
4263
  if (result.data.side == 'front' && val == 1) {
3525
4264
  if(this.state.certificateValidity) {
@@ -3679,6 +4418,7 @@ class Video extends Component {
3679
4418
  })
3680
4419
  // this.messageClick('识别失败', 'error')
3681
4420
  this.errorCodeClick('ocr',result.code)
4421
+ this.saveLog('OCR failed, error code=' + result.code)
3682
4422
  }
3683
4423
  } catch (err) {
3684
4424
  this.setState({
@@ -3777,6 +4517,9 @@ class Video extends Component {
3777
4517
  // videoList: this.state.videoList
3778
4518
  // })
3779
4519
  this.videoListSort();
4520
+ if (this.state.isPictureInPicture) {
4521
+ this.pictureInPicture('Refresh')
4522
+ }
3780
4523
  } else {
3781
4524
  console.log('1')
3782
4525
  this.messageClick('保持信息失败', 'error')
@@ -3787,15 +4530,12 @@ class Video extends Component {
3787
4530
  }
3788
4531
  };
3789
4532
  handleCancelFacial = () => {
3790
- callNimIM('sendCustomCmdMsg', {
3791
- customId: this.state.imRoomId,
3792
- content: JSON.stringify({
3793
- 'typeId': 1020,
3794
- 'sessionId': this.state.sessionId,
3795
- 'cameraState': 1, // 1--打开前置 2--打开后置
3796
- "userId": this.state.faceCustomerUid
3797
- })
3798
- });
4533
+ this.sendMessage({
4534
+ 'typeId': 1020,
4535
+ 'sessionId': this.state.sessionId,
4536
+ 'cameraState': 1, // 1--打开前置 2--打开后置
4537
+ "userId": this.state.faceCustomerUid
4538
+ })
3799
4539
  this.setState({
3800
4540
  isModalVisibleFacial: false
3801
4541
  })
@@ -3820,15 +4560,12 @@ class Video extends Component {
3820
4560
  }
3821
4561
  }
3822
4562
  newFaceClick=()=>{
3823
- callNimIM('sendCustomCmdMsg', {
3824
- customId: this.state.imRoomId,
3825
- content: JSON.stringify({
3826
- 'typeId': 1020,
3827
- 'sessionId': this.state.sessionId,
3828
- 'cameraState': 2, // 1--打开前置 2--打开后置
3829
- "userId": this.state.faceCustomerUid
3830
- })
3831
- });
4563
+ this.sendMessage({
4564
+ 'typeId': 1020,
4565
+ 'sessionId': this.state.sessionId,
4566
+ 'cameraState': 2, // 1--打开前置 2--打开后置
4567
+ "userId": this.state.faceCustomerUid
4568
+ })
3832
4569
  this.setState({
3833
4570
  clickedFacial: false,
3834
4571
  clickedOcr: false,
@@ -3939,15 +4676,12 @@ class Video extends Component {
3939
4676
  } else {
3940
4677
  if (this.state.faceCustomerType == 2) {
3941
4678
  // ocr
3942
- callNimIM('sendCustomCmdMsg', {
3943
- customId: this.state.imRoomId,
3944
- content: JSON.stringify({
3945
- 'typeId': 1020,
3946
- 'sessionId': this.state.sessionId,
3947
- 'cameraState': 2, // 1--打开前置 2--打开后置
3948
- "userId": item.customId
3949
- })
3950
- });
4679
+ this.sendMessage({
4680
+ 'typeId': 1020,
4681
+ 'sessionId': this.state.sessionId,
4682
+ 'cameraState': 2, // 1--打开前置 2--打开后置
4683
+ "userId": item.customId
4684
+ })
3951
4685
  }
3952
4686
  var sid
3953
4687
  if (item.feedId == document.getElementById("feedId1").innerText) {
@@ -4018,19 +4752,25 @@ class Video extends Component {
4018
4752
  }
4019
4753
  }
4020
4754
  sgsinImage = () => {
4021
- if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4022
- this.setState({
4023
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4024
- isFaceImage: true,
4025
- facialImgFront: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4026
- })
4027
- } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4028
- this.setState({
4029
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4030
- isFaceImage: true,
4031
- facialImgBack: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4032
- })
4033
- }
4755
+ const imgBase64 = this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png')
4756
+ // console.log(imgBase64)
4757
+
4758
+ compressImage(imgBase64, (compressedImg)=>{
4759
+ // console.log(compressedImg)
4760
+ if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4761
+ this.setState({
4762
+ facialImg: compressedImg,
4763
+ isFaceImage: true,
4764
+ facialImgFront: compressedImg,
4765
+ })
4766
+ } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4767
+ this.setState({
4768
+ facialImg: compressedImg,
4769
+ isFaceImage: true,
4770
+ facialImgBack: compressedImg,
4771
+ })
4772
+ }
4773
+ })
4034
4774
 
4035
4775
  }
4036
4776
  handleChangeOcr = (val) => {
@@ -4042,10 +4782,10 @@ class Video extends Component {
4042
4782
  })
4043
4783
  }
4044
4784
  componentWillReceiveProps(props) {
4045
- this.state.channelId = props.roomId,
4046
- this.state.rtoken = props.mtoken,
4047
- this.state.sessionId = props.sessionId,
4048
- this.state.imRoomId = props.imRoomId
4785
+ this.state.channelId = props.roomId || this.state.channelId
4786
+ this.state.rtoken = props.mtoken || this.state.rtoken
4787
+ this.state.sessionId = props.sessionId || this.state.sessionId
4788
+ this.state.imRoomId = props.imRoomId || this.state.imRoomId
4049
4789
  }
4050
4790
  appGetUsernameClick = async (userId) => {
4051
4791
  let data = ''
@@ -4193,6 +4933,21 @@ class Video extends Component {
4193
4933
  })
4194
4934
  }
4195
4935
  }
4936
+ changePdfRendering = () => {
4937
+ if (this.props.pdfRendering) {
4938
+ // 暂停绘制
4939
+ clearInterval(this.state.drawCanvasInterval)
4940
+ } else {
4941
+ // 继续绘制
4942
+ if (!this.drawFunction) {
4943
+ console.log('未开始远程签署')
4944
+ return
4945
+ }
4946
+ clearInterval(this.state.drawCanvasInterval)
4947
+ this.state.drawCanvasInterval = setInterval(this.drawFunction, 1000 / 20);
4948
+ }
4949
+
4950
+ }
4196
4951
  navigatorClick = () => {
4197
4952
  const that = this
4198
4953
  const publish_config = {};
@@ -4222,8 +4977,10 @@ class Video extends Component {
4222
4977
  canvas.width = 960;
4223
4978
  canvas.height = 540;
4224
4979
 
4225
-
4226
- videoMedia.addEventListener('play', (event) => {
4980
+ if (this.state.whiteboardPlayEvent) {
4981
+ videoMedia.removeEventListener('play', this.state.whiteboardPlayEvent)
4982
+ }
4983
+ this.state.whiteboardPlayEvent = (event) => {
4227
4984
  var $this = this; //cache
4228
4985
  if ($this.state.operateShow) {
4229
4986
  isGraffiti = false
@@ -4234,20 +4991,21 @@ class Video extends Component {
4234
4991
  canvas.width = this.state.whiteboardWidth
4235
4992
  }
4236
4993
  console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
4237
- loop()
4238
- function loop() {
4239
- if (!$this.paused && !$this.ended) {
4240
- // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4241
- cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4242
- // } else {
4243
- // cobj.fillStyle = 'rgb(0 0 0)'
4244
- // cobj.fillRect(0,0,960,540)
4245
- // }
4246
4994
 
4247
- setTimeout(loop, 1000 / 20); // drawing at 30fps
4248
- }
4995
+ if (this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
4996
+ $this.drawFunction = () => {
4997
+ if (!$this.paused && !$this.ended) {
4998
+ // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4999
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
5000
+ // } else {
5001
+ // cobj.fillStyle = 'rgb(0 0 0)'
5002
+ // cobj.fillRect(0,0,960,540)
5003
+ // }
5004
+ }
4249
5005
  }
4250
5006
 
5007
+ this.state.drawCanvasInterval = setInterval($this.drawFunction , 1000/ 20);
5008
+
4251
5009
  if (document.getElementById('video20').name) {
4252
5010
  // 代表已经有了进行切流
4253
5011
  publish_config.publish_device = 5
@@ -4270,7 +5028,8 @@ class Video extends Component {
4270
5028
  publish_config.publish_tag = 'projectionWhiteboard'
4271
5029
  this.test_controller.Publish(publish_config)
4272
5030
  }
4273
- }, 0);
5031
+ }
5032
+ videoMedia.addEventListener('play', this.state.whiteboardPlayEvent);
4274
5033
  navigator.mediaDevices.getDisplayMedia({
4275
5034
  video: true,
4276
5035
  preferCurrentTab: true,
@@ -4302,6 +5061,104 @@ class Video extends Component {
4302
5061
  that.test_controller.UnPublish(document.getElementById('video20').name)
4303
5062
  }
4304
5063
  }
5064
+
5065
+ // 关闭当前共享屏幕
5066
+ document.getElementById('video20') && document.getElementById('video20').name ? this.test_controller.UnPublish(document.getElementById('video20').name) : ''
5067
+ that.state.isSharedScreen = false
5068
+ that.state.isScreenSwitching = false
5069
+ that.setState({
5070
+ screenName: '共享模式'
5071
+ });
5072
+ that.tabTitlesClick('RMScreen', 'delect')
5073
+
5074
+ }, error => {
5075
+ console.log("Unable to acquire screen capture", error);
5076
+ });
5077
+ }
5078
+ publishRecorderDevice = () => {
5079
+ if (this.state.recorderDevice){
5080
+ let publish_config = {}
5081
+ publish_config.media_type = 3
5082
+ publish_config.publish_device = 1
5083
+ publish_config.videoSource = this.state.recorderDevice.actionid
5084
+ publish_config.video_profile_type = 100
5085
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
5086
+ publish_config.publish_video_id = 'publish_video_record_device'
5087
+ publish_config.publish_streamId_id = 'publish_streamId_record_device'
5088
+ publish_config.publish_tag = 'sharedScreen'
5089
+ this.test_controller.Publish(publish_config)
5090
+ }
5091
+ }
5092
+ publishAllScreen = () => {
5093
+ const that = this
5094
+ const publish_config = {};
5095
+ const canvas = document.createElement('canvas');
5096
+ const videoMedia = document.getElementById('recordvideo');
5097
+ const cobj = canvas.getContext('2d'); // 获取绘图环境
5098
+ const left = document.getElementById("whiteboardDIV").getBoundingClientRect().left;
5099
+ const right = document.getElementById("whiteboardDIV").getBoundingClientRect().right
5100
+ const top = document.getElementById("whiteboardDIV").getBoundingClientRect().top
5101
+ const bottom = document.getElementById("whiteboardDIV").getBoundingClientRect().bottom
5102
+ let width = ((right - left) * window.screen.width / document.body.clientWidth) - 5
5103
+ let height = ((bottom - top) * window.screen.width / document.body.clientWidth) - 30
5104
+ let x = (left * window.screen.width / document.body.clientWidth)
5105
+ let y = (top * window.screen.width / document.body.clientWidth) + 8
5106
+ // console.error(left, right, top, bottom)
5107
+ // console.error(width,height,x,y)
5108
+
5109
+
5110
+ canvas.width = 960;
5111
+ canvas.height = 540;
5112
+
5113
+
5114
+ videoMedia.addEventListener('play', (event) => {
5115
+ var $this = this; //cache
5116
+ console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
5117
+ loop()
5118
+ function loop() {
5119
+ if (!$this.paused && !$this.ended) {
5120
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
5121
+ setTimeout(loop, 1000 / 20); // drawing at 30fps
5122
+ }
5123
+ }
5124
+
5125
+ publish_config.media_type = 3
5126
+ publish_config.publish_device = 5
5127
+ publish_config.need_volume_analyser = false
5128
+ publish_config.video_profile_type = 1
5129
+ publish_config.degradationType = 2
5130
+ publish_config.stream = canvas.captureStream(10)
5131
+ publish_config.publish_video_id = 'record_video'
5132
+ publish_config.publish_streamId_id = 'record_video_streamId'
5133
+ publish_config.publish_tag = 'RM_ALL_SCREEN'
5134
+ this.test_controller.Publish(publish_config)
5135
+ }, 0);
5136
+ navigator.mediaDevices.getDisplayMedia({
5137
+ video: true,
5138
+ preferCurrentTab: true,
5139
+ })
5140
+ .then((stream) => {
5141
+ if (streamRecord) {
5142
+ streamRecord.getTracks().forEach(track => track.stop());
5143
+ streamRecord = ''
5144
+ }
5145
+ videoMedia.srcObject = stream;
5146
+ stream.getVideoTracks()[0].applyConstraints({
5147
+ // width: 1280,
5148
+ // height: 720
5149
+ width: window.screen.width,
5150
+ height: window.screen.height
5151
+ })
5152
+
5153
+ streamRecord = stream
5154
+
5155
+ stream.getVideoTracks()[0].onended = async () => {
5156
+ //单击停止共享按钮后,触发这个事件
5157
+ streamRecord = ''
5158
+ if (document.getElementById('record_video').name) {
5159
+ that.test_controller.UnPublish(document.getElementById('record_video').name)
5160
+ }
5161
+ }
4305
5162
  }, error => {
4306
5163
  console.log("Unable to acquire screen capture", error);
4307
5164
  });
@@ -4477,6 +5334,109 @@ class Video extends Component {
4477
5334
  this.test_controller.GetDevices()
4478
5335
  }
4479
5336
  }
5337
+ toggleAsr = () => {
5338
+ if (this.isFileSuccuse()) {
5339
+ if (!this.state.isAsrStart){
5340
+ this.startASR()
5341
+ } else {
5342
+ this.stopASR()
5343
+ }
5344
+ }
5345
+ }
5346
+ showEnvDetection = () => {
5347
+ this.envDetection()
5348
+ this.setState({
5349
+ isModalVisibleEnvironment: true,
5350
+ })
5351
+ }
5352
+
5353
+ envDetection = () => {
5354
+ let self = this
5355
+ let envInfo = {
5356
+ batteryCharging: '未知', // 电池充电
5357
+ batteryLevel: '未知', // 电池电量
5358
+ networkStatus: '未知', // 网络状态 (已连接/未连接)
5359
+ cameraResult: this.state.cameraList.length>0 ? '合格': '不合格', // 摄像头检测
5360
+ microResult: this.state.microphoneList.length>0 ? '合格': '不合格', // 麦克风检测
5361
+ lightResult: this.state.envInfo? this.state.envInfo.lightResult : '未知'
5362
+ }
5363
+
5364
+ if (navigator) {
5365
+ // 电量检测
5366
+ navigator.getBattery().then(function(battery) {
5367
+ // console.log(battery)
5368
+ // 是否正在充电,yes-充电
5369
+ envInfo.batteryCharging = (battery.charging ? "正在充电" : "不在充电")
5370
+ // 当前剩余电量
5371
+ envInfo.batteryLevel = battery.level * 100 + "%"
5372
+ envInfo.batteryResult = (battery.charging )? '合格': '不合格'
5373
+ self.setState({
5374
+ envInfo: envInfo
5375
+ })
5376
+ battery.removeEventListener("chargingchange", self.envDetection);
5377
+ battery.removeEventListener("levelchange", self.envDetection);
5378
+ battery.addEventListener("chargingchange", self.envDetection);
5379
+ battery.addEventListener("levelchange", self.envDetection);
5380
+ });
5381
+
5382
+ // 网络检测
5383
+ envInfo.networkStatus = window.navigator.onLine? '已连接': '未连接'
5384
+ envInfo.networkResult = window.navigator.onLine? '合格': '不合格'
5385
+ window.removeEventListener("offline", self.envDetection);
5386
+ window.removeEventListener("online", self.envDetection);
5387
+ window.addEventListener("offline", self.envDetection);
5388
+ window.addEventListener("online", self.envDetection);
5389
+ if (navigator.connection){
5390
+ function setNetworkInfo() {
5391
+ const { rtt, downlink, effectiveType, saveData } = navigator.connection;
5392
+ // console.log(`有效网络连接类型: ${effectiveType}`);
5393
+ // console.log(`估算的下行速度/带宽: ${downlink}Mb/s`);
5394
+ // console.log(`估算的往返时间: ${rtt}ms`);
5395
+ if (!window.navigator.onLine) {
5396
+ envInfo.networkInfo = ''}
5397
+ else {
5398
+ envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5399
+ envInfo.networkResult = downlink > 0.2? '合格': '不合格'
5400
+ }
5401
+ }
5402
+ setNetworkInfo()
5403
+ navigator.connection.removeEventListener('change', self.envDetection);
5404
+ navigator.connection.addEventListener('change', self.envDetection);
5405
+ }
5406
+
5407
+ }
5408
+
5409
+ // 背景曝光环境检测
5410
+ this.lightDetect()
5411
+
5412
+ this.setState({
5413
+ // isModalVisibleEnvironment: true,
5414
+ envInfo: envInfo
5415
+ })
5416
+ }
5417
+ handleRetryEnvDetection = () => {
5418
+ this.lightDetect();
5419
+ message.success({
5420
+ content: '已更新检测结果',
5421
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
5422
+ className: 'successClassName',
5423
+ top: 200,
5424
+ duration: 3
5425
+ })
5426
+ }
5427
+ handleOkEnvDetection = () => {
5428
+ this.setState({
5429
+ isModalVisibleEnvironment: false,
5430
+ })
5431
+ if (!this.state.isPictureInPicture) {
5432
+ this.pictureInPicture()
5433
+ }
5434
+ }
5435
+ // handleCancelEnvDetection = () => {
5436
+ // this.setState({
5437
+ // isModalVisibleEnvironment: false
5438
+ // })
5439
+ // }
4480
5440
  handleOkInspection = () => {
4481
5441
  this.setState({
4482
5442
  isModalVisibleInspection: false,
@@ -4522,16 +5482,39 @@ class Video extends Component {
4522
5482
  this.setState({
4523
5483
  beautyName: '开启美颜'
4524
5484
  })
5485
+ beautyMode = 'none'
4525
5486
  beautySetMode('none')
5487
+ beautyStop()
5488
+ if(!isSuccuseHs) {
5489
+ stopHs()
5490
+ }
4526
5491
  } else {
4527
5492
  this.state.beautyType = true
5493
+ beautyMode = 'beauty'
4528
5494
  beautySetMode('beauty')
4529
5495
  this.setState({
4530
5496
  beautyName: '关闭美颜'
4531
5497
  })
4532
5498
  }
5499
+ this.changeMediaStream();
4533
5500
 
4534
5501
  }
5502
+ changeMediaStream = () => {
5503
+ let publish_config = {}
5504
+ publish_config.sid = document.getElementById('publish_video1').name
5505
+ publish_config.media_type = 1
5506
+ publish_config.publish_device = 1
5507
+ // publish_config.videoSource = this.state.cameraValue
5508
+ // publish_config.audioSource = this.state.microphoneValue
5509
+ publish_config.need_volume_analyser = true
5510
+ publish_config.video_profile_type = 100
5511
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
5512
+ // publish_config.publish_video_id = 'publish_video1'
5513
+ // publish_config.publish_streamId_id = 'publish_streamId1'
5514
+ // publish_config.publish_tag = 'tag1'
5515
+ this.test_controller.ChangeMediaStream(publish_config)
5516
+ }
5517
+
4535
5518
  componentDidMount() {
4536
5519
  var box = document.getElementById("whiteboardDIV");
4537
5520
  var box1 = document.getElementById("operate")
@@ -4549,117 +5532,81 @@ class Video extends Component {
4549
5532
  muteOpposite = (value) => {
4550
5533
  console.log(value);
4551
5534
  if (value == 'video1') {
4552
- callNimIM('sendCustomCmdMsg', {
4553
- customId: this.state.imRoomId,
4554
- content: JSON.stringify({
4555
- 'typeId': 1223,
4556
- 'sessionId': this.state.sessionId,
4557
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
4558
- })
4559
- });
5535
+ this.sendMessage({
5536
+ 'typeId': 1223,
5537
+ 'sessionId': this.state.sessionId,
5538
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
5539
+ })
4560
5540
  }
4561
5541
  if (value == 'video2') {
4562
- callNimIM('sendCustomCmdMsg', {
4563
- customId: this.state.imRoomId,
4564
- content: JSON.stringify({
4565
- 'typeId': 1223,
4566
- 'sessionId': this.state.sessionId,
4567
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId2').innerText).uid
4568
- })
4569
- });
5542
+ this.sendMessage({
5543
+ 'typeId': 1223,
5544
+ 'sessionId': this.state.sessionId,
5545
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId2').innerText).uid
5546
+ })
4570
5547
  } if (value == 'video3') {
4571
- callNimIM('sendCustomCmdMsg', {
4572
- customId: this.state.imRoomId,
4573
- content: JSON.stringify({
4574
- 'typeId': 1223,
4575
- 'sessionId': this.state.sessionId,
4576
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId3').innerText).uid
4577
- })
4578
- });
5548
+ this.sendMessage({
5549
+ 'typeId': 1223,
5550
+ 'sessionId': this.state.sessionId,
5551
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId3').innerText).uid
5552
+ })
4579
5553
  } if (value == 'video4') {
4580
- callNimIM('sendCustomCmdMsg', {
4581
- customId: this.state.imRoomId,
4582
- content: JSON.stringify({
4583
- 'typeId': 1223,
4584
- 'sessionId': this.state.sessionId,
4585
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId4').innerText).uid
4586
- })
4587
- });
5554
+ this.sendMessage({
5555
+ 'typeId': 1223,
5556
+ 'sessionId': this.state.sessionId,
5557
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId4').innerText).uid
5558
+ })
4588
5559
  } if (value == 'video5') {
4589
- callNimIM('sendCustomCmdMsg', {
4590
- customId: this.state.imRoomId,
4591
- content: JSON.stringify({
4592
- 'typeId': 1223,
4593
- 'sessionId': this.state.sessionId,
4594
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId5').innerText).uid
4595
- })
4596
- });
5560
+ this.sendMessage({
5561
+ 'typeId': 1223,
5562
+ 'sessionId': this.state.sessionId,
5563
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId5').innerText).uid
5564
+ })
4597
5565
  } if (value == 'video6') {
4598
- callNimIM('sendCustomCmdMsg', {
4599
- customId: this.state.imRoomId,
4600
- content: JSON.stringify({
4601
- 'typeId': 1223,
4602
- 'sessionId': this.state.sessionId,
4603
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId6').innerText).uid
4604
- })
4605
- });
5566
+ this.sendMessage({
5567
+ 'typeId': 1223,
5568
+ 'sessionId': this.state.sessionId,
5569
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId6').innerText).uid
5570
+ })
4606
5571
  } if (value == 'video7') {
4607
- callNimIM('sendCustomCmdMsg', {
4608
- customId: this.state.imRoomId,
4609
- content: JSON.stringify({
4610
- 'typeId': 1223,
4611
- 'sessionId': this.state.sessionId,
4612
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId7').innerText).uid
4613
- })
4614
- });
5572
+ this.sendMessage({
5573
+ 'typeId': 1223,
5574
+ 'sessionId': this.state.sessionId,
5575
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId7').innerText).uid
5576
+ })
4615
5577
  } if (value == 'video8') {
4616
- callNimIM('sendCustomCmdMsg', {
4617
- customId: this.state.imRoomId,
4618
- content: JSON.stringify({
4619
- 'typeId': 1223,
4620
- 'sessionId': this.state.sessionId,
4621
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId8').innerText).uid
4622
- })
4623
- });
5578
+ this.sendMessage({
5579
+ 'typeId': 1223,
5580
+ 'sessionId': this.state.sessionId,
5581
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId8').innerText).uid
5582
+ })
4624
5583
  } if (value == 'video9') {
4625
- callNimIM('sendCustomCmdMsg', {
4626
- customId: this.state.imRoomId,
4627
- content: JSON.stringify({
4628
- 'typeId': 1223,
4629
- 'sessionId': this.state.sessionId,
4630
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId9').innerText).uid
4631
- })
4632
- });
5584
+ this.sendMessage({
5585
+ 'typeId': 1223,
5586
+ 'sessionId': this.state.sessionId,
5587
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId9').innerText).uid
5588
+ })
4633
5589
  }
4634
5590
  if (value == 'video10') {
4635
- callNimIM('sendCustomCmdMsg', {
4636
- customId: this.state.imRoomId,
4637
- content: JSON.stringify({
4638
- 'typeId': 1223,
4639
- 'sessionId': this.state.sessionId,
4640
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId10').innerText).uid
4641
- })
4642
- });
5591
+ this.sendMessage({
5592
+ 'typeId': 1223,
5593
+ 'sessionId': this.state.sessionId,
5594
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId10').innerText).uid
5595
+ })
4643
5596
  }
4644
5597
  if (value == 'video11') {
4645
- callNimIM('sendCustomCmdMsg', {
4646
- customId: this.state.imRoomId,
4647
- content: JSON.stringify({
4648
- 'typeId': 1223,
4649
- 'sessionId': this.state.sessionId,
4650
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId11').innerText).uid
4651
- })
4652
- });
5598
+ this.sendMessage({
5599
+ 'typeId': 1223,
5600
+ 'sessionId': this.state.sessionId,
5601
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId11').innerText).uid
5602
+ })
4653
5603
  }
4654
5604
  if (value == 'video12') {
4655
- callNimIM('sendCustomCmdMsg', {
4656
- customId: this.state.imRoomId,
4657
- content: JSON.stringify({
4658
- 'typeId': 1223,
4659
- 'sessionId': this.state.sessionId,
4660
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId12').innerText).uid
4661
- })
4662
- });
5605
+ this.sendMessage({
5606
+ 'typeId': 1223,
5607
+ 'sessionId': this.state.sessionId,
5608
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId12').innerText).uid
5609
+ })
4663
5610
  }
4664
5611
 
4665
5612
  }
@@ -4668,14 +5615,11 @@ class Video extends Component {
4668
5615
  this.state.shareMaskState = this.props.shareMask
4669
5616
  // 加延迟是因为在关闭的时候可以看到部分rm的操作
4670
5617
  setTimeout(() => {
4671
- callNimIM('sendCustomCmdMsg', {
4672
- customId: this.state.imRoomId,
4673
- content: JSON.stringify({
4674
- 'typeId': 1230,
4675
- 'sessionId': this.state.sessionId,
4676
- 'type': this.state.shareMaskState ? 1 : 2
4677
- })
4678
- });
5618
+ this.sendMessage({
5619
+ 'typeId': 1230,
5620
+ 'sessionId': this.state.sessionId,
5621
+ 'type': this.state.shareMaskState ? 1 : 2
5622
+ })
4679
5623
  }, 100)
4680
5624
 
4681
5625
  }
@@ -4683,11 +5627,18 @@ class Video extends Component {
4683
5627
  if (!isSuccuseHs) {
4684
5628
 
4685
5629
  hsSetMode('blur')
5630
+ hsMode = 'blur'
4686
5631
  isSuccuseHs = true
4687
5632
  } else {
4688
5633
  hsSetMode('none')
5634
+ hsMode = 'none'
4689
5635
  isSuccuseHs = false
5636
+ stopHs()
5637
+ if(!this.state.beautyType) {
5638
+ beautyStop()
5639
+ }
4690
5640
  }
5641
+ this.changeMediaStream();
4691
5642
  }
4692
5643
  virtualization = () => {
4693
5644
  this.virtualizationClick()
@@ -4714,6 +5665,17 @@ class Video extends Component {
4714
5665
  return false;
4715
5666
  }
4716
5667
  }
5668
+ isHKPassValidTime=(value)=>{
5669
+ if (!value.split('.') || value.split('.').length < 3 || value.split('.').some(el => el == '')) return false;
5670
+ let start = new Date('2020.01.01').valueOf();
5671
+ let end = new Date('2023.12.31').valueOf();
5672
+ var time = new Date(value).valueOf();
5673
+ if(start<=time && end >= time ){
5674
+ return true;
5675
+ }else{
5676
+ return false;
5677
+ }
5678
+ }
4717
5679
  handleChangeCertificateValidity = (event) => {
4718
5680
  // 护照只有起始日期,单独处理
4719
5681
  if (this.state.documentType == 'PASSPORT_CARD' && event.target.value.split('.').length >2) {
@@ -4734,6 +5696,12 @@ class Video extends Component {
4734
5696
  certificateValidity: event.target.value,
4735
5697
  certificateValidityType: true
4736
5698
  });
5699
+ } else if (this.state.documentType == 'HK_MO_PASS_CARD' && this.isHKPassValidTime(event.target.value.split('-')[1])){
5700
+ // 疫情政策对港澳来往通行证放宽限制,有效期限从2020.1.1到2023.12.31都算有效
5701
+ this.setState({
5702
+ certificateValidity: event.target.value,
5703
+ certificateValidityType: true
5704
+ });
4737
5705
  } else {
4738
5706
  this.setState({
4739
5707
  certificateValidity: event.target.value,
@@ -4748,6 +5716,9 @@ class Video extends Component {
4748
5716
  if (this.props.shareMask != prevProps.shareMask) {
4749
5717
  this.sendNotification()
4750
5718
  }
5719
+ if (this.props.pdfRendering != prevProps.pdfRendering) {
5720
+ this.changePdfRendering()
5721
+ }
4751
5722
  }
4752
5723
  onChangeOCRCustomer = (e) => {
4753
5724
  console.log(e)
@@ -4848,8 +5819,10 @@ class Video extends Component {
4848
5819
 
4849
5820
  }))
4850
5821
  }
4851
-
4852
-
5822
+ this.setState({
5823
+ documentError: '',
5824
+ isModalVisibleCustomer: false,
5825
+ })
4853
5826
  }
4854
5827
  })
4855
5828
  // this.customerFaceClick(this.state.customerList[this.state.customerSelect])
@@ -5062,6 +6035,13 @@ class Video extends Component {
5062
6035
  </div>
5063
6036
  )
5064
6037
 
6038
+ const isEnvironmentOK = !this.state.loading &&
6039
+ this.state.envInfo.networkResult=='合格' &&
6040
+ this.state.envInfo.batteryResult=='合格' &&
6041
+ this.state.envInfo.cameraResult=='合格' &&
6042
+ this.state.envInfo.microResult=='合格' &&
6043
+ this.state.envInfo.lightResult=='合格'
6044
+
5065
6045
  const sectionStyle = this.state.tabTitles.length > 0 ? {
5066
6046
  zIndex: '-1',
5067
6047
  width: '100%',
@@ -5172,13 +6152,19 @@ class Video extends Component {
5172
6152
 
5173
6153
  </ul>
5174
6154
  </div>
5175
- {!this.state.loading && this.state.sessionId?
5176
- <QRCode
5177
- style={{'position': 'absolute', 'right': '10px', 'top': '-110px'}}
5178
- value={this.state.sessionId} //value参数为生成二维码的链接
5179
- size={100} //二维码的宽高尺寸
6155
+ {!this.state.loading && this.state.sessionType && this.state.sessionId && this.props.recordMode == 2?
6156
+ <div className='QRCode'>
6157
+ <QRCode
6158
+ value={JSON.stringify({
6159
+ sessionId:this.state.sessionId,
6160
+ staffId: this.props.tellerAccount,
6161
+ staffName: this.props.staffName
6162
+ })} //value参数为生成二维码的链接
6163
+ size={110} //二维码的宽高尺寸
5180
6164
  fgColor="#000000" //二维码的颜色
5181
- /> : null}
6165
+ />
6166
+ <div className='sessionDiv'>{this.state.sessionId.slice(0, 4)}-{this.state.sessionId.slice(4-this.state.sessionId.length)}</div>
6167
+ </div> : null}
5182
6168
  </div>
5183
6169
  }
5184
6170
 
@@ -5216,7 +6202,7 @@ class Video extends Component {
5216
6202
  </div>
5217
6203
 
5218
6204
  </div>
5219
- {
6205
+ {/* {
5220
6206
  this.state.cameraList.map((item, index) => {
5221
6207
  if (index > 0)
5222
6208
  return <div
@@ -5249,7 +6235,7 @@ class Video extends Component {
5249
6235
  </div>
5250
6236
  </div>
5251
6237
  })
5252
- }
6238
+ } */}
5253
6239
  {/* <div className={`itemed ${this.state.isVideoList? 'videoMinutuListClass': 'videoMinutuClass'}`}
5254
6240
  style={{ position: "relative", display: (this.state.videoList[0].videoName) ? '' : 'none' }}
5255
6241
  >
@@ -5298,7 +6284,7 @@ class Video extends Component {
5298
6284
  <audio id={'audio'+(item.idIndex)} autoPlay />
5299
6285
  <label style={{ display: 'none' }} id={'feedId'+(item.idIndex)} type="text" />
5300
6286
 
5301
- <div style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
6287
+ <div onClick={this.muteOpposite.bind(this, 'video'+(item.idIndex))} style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
5302
6288
  {
5303
6289
  item.mute && <img
5304
6290
  alt=""
@@ -5348,6 +6334,8 @@ class Video extends Component {
5348
6334
  ocrClick={this.ocrClick}
5349
6335
  switchExternal={this.switchExternal}
5350
6336
  inspection={this.inspection}
6337
+ toggleAsr={this.toggleAsr}
6338
+ envDetection={this.showEnvDetection}
5351
6339
  beautyClick={this.beautyClick}
5352
6340
  graffiti={this.graffiti}
5353
6341
  virtualization={this.virtualization}
@@ -5362,6 +6350,23 @@ class Video extends Component {
5362
6350
  !this.state.isSuspend && <span>确定是否暂停会话?</span>
5363
6351
  }
5364
6352
  </Modal>
6353
+ {/* 画中画重新开启确认 */}
6354
+ <Modal closable={false} centered={true} visible={this.state.isPictureConfirmModalVisible} maskClosable={false} footer={[
6355
+ <div key='end'>
6356
+ {/* <Button className="modelButtonCancel" onClick={()=> {this.setState({isPictureConfirmModalVisible: false})}}>取消</Button> */}
6357
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkPictureConfirm}>确定</Button>
6358
+ </div>
6359
+ ]}>
6360
+ <div className='endModal'>视频浮窗已关闭,请重新开启</div>
6361
+ </Modal>
6362
+ {/* 双录中断重新开启确认 */}
6363
+ <Modal closable={false} centered={true} visible={this.state.isRecordingeErrorModalVisible} maskClosable={false} footer={[
6364
+ <div key='end'>
6365
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkRecordConfirm}>确定</Button>
6366
+ </div>
6367
+ ]}>
6368
+ <div className='endModal'>双录异常中断,请重新开启</div>
6369
+ </Modal>
5365
6370
  {/* 是否退出会议*/}
5366
6371
  <Modal closable={false} centered={true} visible={this.state.isModalVisibleEnd} maskClosable={false} footer={[
5367
6372
  <div key='end'>
@@ -5369,7 +6374,7 @@ class Video extends Component {
5369
6374
  <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnd}>确定</Button>
5370
6375
  </div>
5371
6376
  ]}>
5372
- <div className='endModal'>是否要结束并退出会议?</div>
6377
+ <div className='endModal'>{this.state.businessId? '正在进行业务录制,是否确认结束并退出会议?': '是否要结束并退出会议?'}</div>
5373
6378
  </Modal>
5374
6379
  {/* ocr及人脸 */}
5375
6380
  <Modal title={this.state.titleModal} width={800} closable={true} maskClosable={false} onCancel={this.handleCancelFacial} centered={true} visible={this.state.isModalVisibleFacial} footer={[
@@ -5709,10 +6714,61 @@ class Video extends Component {
5709
6714
 
5710
6715
  </div>
5711
6716
  </Modal>
6717
+ <Modal title="环境检测" maskClosable={false} width={650} closable={false} centered={true} visible={this.state.isModalVisibleEnvironment} footer={[
6718
+ <div key='env'>
6719
+ <Button className="modelButtonCancel" onClick={this.handleRetryEnvDetection}>重新检测</Button>
6720
+ <Button className={isEnvironmentOK ?"modelButtonOk": "modelButtonNo"} type="primary" disabled={!isEnvironmentOK } danger onClick={this.handleOkEnvDetection}>确定</Button>
6721
+ </div>
6722
+ ]}>
6723
+ <Collapse defaultActiveKey={['1', '2', '3', '4', '5', '6']} ghost>
6724
+
6725
+ <Panel header={<span>网络检测 - {this.state.envInfo.networkResult } {this.state.envInfo.networkResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6726
+ key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
6727
+ <p className='envClass'>网络状态:{this.state.envInfo.networkStatus}</p>
6728
+ {this.state.envInfo.networkInfo?<p className='envClass'>{this.state.envInfo.networkInfo}</p>:null}
6729
+ </Panel>
6730
+ <Panel header={<span>设备电量 - {this.state.envInfo.batteryResult} {this.state.envInfo.batteryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />} </span>}
6731
+ key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
6732
+ <p className='envClass'>电量:{this.state.envInfo.batteryLevel}({this.state.envInfo.batteryCharging})</p>
6733
+ </Panel>
6734
+ <Panel header={<span>摄像头设备 - {this.state.envInfo.cameraResult}{this.state.envInfo.cameraResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
6735
+ key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
6736
+ <div >
6737
+ {
6738
+ this.state.cameraList.map((item, index) => {
6739
+ return <div key={index} className="envClass">
6740
+ {/* <input type="radio" name="camere" value={item.actionid} style={{ float: 'left' }} checked={this.state.cameraValue == item.actionid} readOnly disabled /><i></i> */}
6741
+ {item.actionname}{this.state.cameraValue == item.actionid ? '(当前设备)' : ''}
6742
+ </div>
6743
+ })
6744
+ }
6745
+ {this.state.cameraList.length == 0 ? <p className="envClass">获取不到设备,请检查电脑“设置”中的摄像头权限是否开启,并重启浏览器再试</p> : null}
6746
+ </div>
6747
+ </Panel>
6748
+ <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':''}>
6749
+ <div>
6750
+ {
6751
+ this.state.microphoneList.map((item, index) => {
6752
+ return <div key={index} className="envClass">
6753
+ {item.actionname}{this.state.microphoneValue == item.actionid ? '(当前设备)' : ''}
6754
+ </div>
6755
+ })
6756
+ }
6757
+ {this.state.cameraList.length == 0 ? <p className="envClass">获取不到设备,请检查电脑“设置”中的麦克风权限是否开启,并重启浏览器再试</p> : null}
6758
+ </div>
6759
+ </Panel>
6760
+ <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'}>
6761
+ <p className="envClass">{this.state.envInfo.lightResult=='合格'? '无过度背光、曝光':'过度背光、曝光'}</p>
6762
+ </Panel>
6763
+ </Collapse>
6764
+ </Modal>
5712
6765
  <video className="mixedvideo" id="mixedvideo" autoPlay muted={true} width="0" height="0"></video>
5713
6766
  <video className="mixedvideo" id="manedvideo" autoPlay width="0" height="0"></video>
5714
6767
  <video className="mixedvideo" id="video30" autoPlay width="0" height="0"></video>
5715
6768
 
6769
+ <video className="mixedvideo" id="recordvideo" autoPlay width="0" height="0"></video>
6770
+ <video className="mixedvideo" id="record_video" muted autoPlay></video>
6771
+ <video className="mixedvideo" id="publish_video_record_device" muted autoPlay></video>
5716
6772
 
5717
6773
  </Spin>
5718
6774
  </div>);
@@ -5728,7 +6784,7 @@ Video.defaultProps = {
5728
6784
  callbackUrl: 'http://182.92.184.31:8720/hsbc/callback',
5729
6785
  // roomServerUrl: 'wss://app.uat.dsp.hsbcfts.com.cn/mpaas/mrtc/ws',
5730
6786
  roomServerUrl: 'wss://mrtc.mpaas.cn-hangzhou.aliyuncs.com/ws',
5731
-
6787
+ asrServerUrl: 'wss://ismis.alipay.com/ws',
5732
6788
  resourcePath: 'https://counter-web.leimondata.cn:7199',
5733
6789
  // resourcePath: 'https://zuul.uat.dsp.hsbcfts.com.cn/wealth/js/',
5734
6790
  prohbiitPrompt: '当前无客户',
@@ -5738,18 +6794,33 @@ Video.defaultProps = {
5738
6794
  microphoneSize: 25,
5739
6795
  fontSize: '14',
5740
6796
  fontFamily: 'auto',
5741
- menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
6797
+ menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'PAPER_OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
5742
6798
  customLeaveRoom: '客户离开房间',
6799
+ sensitiveWords: ['保本保息', '无风险'],
5743
6800
  meetingInfo: {
5744
6801
  title: '--',
5745
6802
  host: '--',
5746
6803
  customers: ['--'],
5747
6804
  otherAttendees: undefined
5748
6805
  },
6806
+ pdfRendering: false,
5749
6807
  isTranscribing: false,
5750
6808
  shareMask: false,
5751
6809
  isOpenSound: false, // true开启进出音效 false不开启
6810
+ isWeakSound: false,
6811
+ whetherDetectFace: false, // 是否在双录时开启人脸检测
6812
+ whetherDetectLight: false, // 是否在双录时开启背光检测
6813
+ faceDetectInterval: 6, // 人脸检测间隔(秒)
6814
+ lightDetectInterval: 6, // 背光检测间隔(秒)
5752
6815
  userSide: 2,
6816
+ meetingDuration: null, // 会议时长,单位小时
6817
+ recordMode: 1, // 录制模式 1远程录制 2网点录制
6818
+ defaultBranchCode: "",// 员工网点缩写
6819
+ customerId: "", //客户号
6820
+ customerType: "", // 客户类型
6821
+ salesBranchCode: "", //网点编号(分行号)
6822
+ financialOffice: "", // 理财室
6823
+ staffName: '', // 坐席名称
5753
6824
  logUrl: 'http://hsbc.cn-shanghai.log.aliyuncs.com/logstores/hsbc/track?APIVersion=0.6.0&app=meeting-ui',
5754
6825
  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'
5755
6826
  }