react_hsbc_teller 2.0.25 → 2.0.27

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,6 +4,17 @@
4
4
  http://jedwatson.github.io/classnames
5
5
  */
6
6
 
7
+ /*!
8
+ *
9
+ * js-audio-recorder - js audio recorder plugin
10
+ *
11
+ * @version v0.5.7
12
+ * @homepage https://github.com/2fps/recorder
13
+ * @author 2fps <echoweb@126.com> (https://www.zhuyuntao.cn)
14
+ * @license MIT
15
+ *
16
+ */
17
+
7
18
  /*!
8
19
  * Determine if an object is a Buffer
9
20
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react_hsbc_teller",
3
- "version": "2.0.25",
3
+ "version": "2.0.27",
4
4
  "description": "React",
5
5
  "private": false,
6
6
  "main": "lib/hsbc.js",
@@ -89,6 +89,7 @@
89
89
  "axios": "0.19.0",
90
90
  "crypto-js": "^4.1.1",
91
91
  "html2canvas": "^1.4.0",
92
+ "js-audio-recorder": "^0.5.7",
92
93
  "qrcode.react": "^3.1.0",
93
94
  "react": "^17.0.1",
94
95
  "react-canvas-draw": "^1.1.1",
@@ -192,6 +192,10 @@ userExit =(val)=>{
192
192
 
193
193
  })
194
194
  }
195
+ componentDidCatch(error, info) {
196
+ console.log('componentDidCatch')
197
+ console.error(error, info)
198
+ }
195
199
  render() {
196
200
  return (
197
201
  <div className="test">
@@ -7,7 +7,7 @@ import API from '../../api/api';
7
7
  import { BoardOperate } from '../../common/index.esm.js';
8
8
  import './video.less'
9
9
  import { compressImage, isLight } from '../../utils/utils'
10
- import Recorder from "../../utils/recorder";
10
+ import Recorder from "js-audio-recorder";
11
11
  import MyAsrController from '../../utils/asrController'
12
12
  import Header from '../header/header.jsx'
13
13
  import Foot from '../foot/foot.jsx'
@@ -58,7 +58,7 @@ import MultiModule from '../multiModule/multiModule'//签字、抄录
58
58
  import axios from 'axios';
59
59
  import CryptoJS from "crypto-js";
60
60
 
61
- const SDK_VERISON = '2.0.25'
61
+ const SDK_VERISON = '2.0.27'
62
62
  const IDtypeFront = '请客户在其设备后置摄像头下展示证件正面(如:身份证照片页面)'
63
63
  const IDtypeBack = '请在后置摄像头下展示证件反面(如:身份证国徽页)'
64
64
  const { Option } = Select;
@@ -93,6 +93,7 @@ let muteJson = new Map()
93
93
  // let dateTime = 0
94
94
  let messageValue = ''
95
95
  let messageValueMap = new Map()
96
+ let videoMessageMap = new Map() // 画中画消息数据
96
97
  let third_id_Map = new Map()
97
98
  // let beautyType = false
98
99
  // let beautyNum = 0 // 0-关闭 1--弱 2--中 5---高
@@ -138,6 +139,7 @@ function clearStreamRemain() {
138
139
  beautyDiv.beauty_canvas = null;
139
140
  }
140
141
  if (!(beautyDiv.beauty_player == null || beautyDiv.beauty_player == undefined)) {
142
+ console.log('beautyDiv destroy')
141
143
  beautyDiv.beauty_player.destroy();
142
144
  beautyDiv.beauty_player = null;
143
145
  }
@@ -590,6 +592,8 @@ class Video extends Component {
590
592
  this.test_controller.InitRoomConfig(config_param)
591
593
  this.saveLog('mrtc InitRoomConfig start')
592
594
  // 预热摄像头
595
+ config_param.videoSource = this.state.cameraValue
596
+ config_param.audioSource = this.state.microphoneValue
593
597
  this.test_controller.PreOpenLocalMedia(config_param)
594
598
  };
595
599
  rateAll = async () => {
@@ -609,15 +613,16 @@ class Video extends Component {
609
613
  // 开启录制
610
614
  enableServerRecording = (record_business_id) => {
611
615
  const that = this
616
+ const SCALE = 1.5
612
617
  this.rateAll().then((res) => {
613
618
  console.log('退出房间者', res)
614
619
  let list = [
615
620
  {
616
621
  tag: 'projectionWhiteboard',
617
622
  xPosition: 0,
618
- yPosition: 175,
619
- width: 960,
620
- height: 540
623
+ yPosition: 175 * SCALE,
624
+ width: 1280,
625
+ height: 720
621
626
  },
622
627
  // {
623
628
  // tag: 'VIDEO_SOURCE_SCREEN_ONE',
@@ -637,50 +642,50 @@ class Video extends Component {
637
642
  tag: 'tag1',
638
643
  xPosition: 0,
639
644
  yPosition: 0,
640
- width: 213,
641
- height: 175
645
+ width: 213 * SCALE,
646
+ height: 175 * SCALE
642
647
  },
643
648
  {
644
649
  tag: 'customer1',
645
- xPosition: 213,
650
+ xPosition: 213 * SCALE,
646
651
  yPosition: 0,
647
- width: 213,
648
- height: 175
652
+ width: 213 * SCALE,
653
+ height: 175 * SCALE
649
654
  },
650
655
  {
651
656
  tag: 'customer2',
652
- xPosition: 426,
657
+ xPosition: 426 * SCALE,
653
658
  yPosition: 0,
654
- width: 213,
655
- height: 175
659
+ width: 213 * SCALE,
660
+ height: 175 * SCALE
656
661
  },
657
662
  {
658
663
  tag: 'customer3',
659
- xPosition: 639,
664
+ xPosition: 639 * SCALE,
660
665
  yPosition: 0,
661
- width: 213,
662
- height: 175
666
+ width: 213 * SCALE,
667
+ height: 175 * SCALE
663
668
  },
664
669
  {
665
670
  tag: 'customer4',
666
- xPosition: 852,
671
+ xPosition: 852 * SCALE,
667
672
  yPosition: 0,
668
- width: 213,
669
- height: 175
673
+ width: 213 * SCALE,
674
+ height: 175 * SCALE
670
675
  },
671
676
  {
672
677
  tag: 'customer5',
673
- xPosition: 1065,
678
+ xPosition: 1065 * SCALE,
674
679
  yPosition: 0,
675
- width: 213,
676
- height: 175
680
+ width: 213 * SCALE,
681
+ height: 175 * SCALE
677
682
  },
678
683
  {
679
684
  tag: 'customer6',
680
- xPosition: 1278,
685
+ xPosition: 1278 * SCALE,
681
686
  yPosition: 0,
682
- width: 213,
683
- height: 175
687
+ width: 213 * SCALE,
688
+ height: 175 * SCALE
684
689
  },
685
690
  // {
686
691
  // tag: 'sharedScreen', // 一期暂时不需要录制
@@ -694,18 +699,18 @@ class Video extends Component {
694
699
  res.map((item) => {
695
700
  list.push({
696
701
  tag: item.tag,
697
- xPosition: item.xaxis,
698
- yPosition: item.yaxis,
699
- width: item.width,
700
- height: item.height
702
+ xPosition: (item.xaxis * SCALE),
703
+ yPosition: (item.yaxis * SCALE),
704
+ width: (item.width * SCALE),
705
+ height: (item.height * SCALE)
701
706
  })
702
707
  }) :
703
708
  list.push({
704
709
  tag: 'VIDEO_SOURCE_SCREEN',
705
- xPosition: 960,
706
- yPosition: 535,
707
- width: 320,
708
- height: 180
710
+ xPosition: 960 * SCALE,
711
+ yPosition: 535 * SCALE,
712
+ width: 320 * SCALE,
713
+ height: 180 * SCALE
709
714
  })
710
715
  // list.push({
711
716
  // tag: 'VIDEO_SOURCE_SCREEN_19_9',
@@ -716,8 +721,8 @@ class Video extends Component {
716
721
  // })
717
722
  const filePath = 'recordId_' + new Date().valueOf();
718
723
  const recordParam = {};
719
- recordParam.width = 1280;
720
- recordParam.height = 720;
724
+ recordParam.width = 1280 * SCALE;
725
+ recordParam.height = 720 * SCALE;
721
726
  recordParam.recordTotalStream = 0;
722
727
  recordParam.startTimeout = 10;
723
728
  recordParam.splitType = 0;
@@ -729,10 +734,10 @@ class Video extends Component {
729
734
  type: 2, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
730
735
  id: 2, // ⽔印 ID
731
736
  enable: true,
732
- xPosition: 640, // x 轴位置
733
- yPosition: 10, // y 轴位置
737
+ xPosition: 640 * SCALE, // x 轴位置
738
+ yPosition: 10 * SCALE, // y 轴位置
734
739
  text: `${this.props.recordMode ==1 ?'远程录制' :'网点录制'} ${this.props.salesBranchCode || ''} ${this.state.branchName || ''} ${this.props.financialOffice || ''}`,
735
- fontSize: 16, // 字体⼤⼩
740
+ fontSize: 16 * SCALE, // 字体⼤⼩
736
741
  url: '' // ⽔印图⽚ HTTP 地址
737
742
  },
738
743
  {
@@ -740,10 +745,10 @@ class Video extends Component {
740
745
  type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
741
746
  id: 1, // ⽔印 ID
742
747
  enable: true,
743
- xPosition: 1080, // x 轴位置
744
- yPosition: 10, // y 轴位置
748
+ xPosition: 1080 * SCALE, // x 轴位置
749
+ yPosition: 10 * SCALE, // y 轴位置
745
750
  text: '', // ⽔印⽂字
746
- fontSize: 16, // 字体⼤⼩
751
+ fontSize: 16 * SCALE, // 字体⼤⼩
747
752
  url: '' // ⽔印图⽚ HTTP 地址
748
753
  },
749
754
  ];
@@ -1002,13 +1007,17 @@ class Video extends Component {
1002
1007
  this.messageClick('当前暂无客户', 'error')
1003
1008
  }
1004
1009
  }
1005
- messageClick = (value, tipType) => {
1010
+ messageClick = (value, tipType, userId) => {
1006
1011
  console.log('messageClick', value, tipType)
1012
+
1013
+ if (userId) {
1014
+ // 画中画实时消息
1015
+ this.addPictureMessage(value, userId)
1016
+ }
1007
1017
  const intervalSec = 5 // 相同提示触发间隔
1008
1018
  const durationSec = 4.5 // 提示持续时间
1009
1019
  if (messageValueMap.get(value) == undefined) {
1010
1020
  // map中没有相同消息
1011
- messageValue = value
1012
1021
  messageValueMap.set(value, setTimeout(() => {
1013
1022
  messageValueMap.delete(value)
1014
1023
  }, intervalSec * 1000))
@@ -1030,12 +1039,45 @@ class Video extends Component {
1030
1039
  duration: durationSec
1031
1040
  })
1032
1041
  }
1033
- clearTimeout(this.messageClearTimer)
1034
- this.messageClearTimer = setTimeout(() => {
1035
- messageValue = ''
1036
- }, durationSec * 1000);
1042
+ if (!userId) {
1043
+ // 坐席消息
1044
+ messageValue = value
1045
+
1046
+ clearTimeout(this.messageClearTimer)
1047
+ this.messageClearTimer = setTimeout(() => {
1048
+ messageValue = ''
1049
+ }, durationSec * 1000);
1050
+ }
1051
+ }
1052
+ }
1053
+ // 画中画内消息
1054
+ addPictureMessage = (value, userId) => {
1055
+ console.log('addPictureMessage', value, userId)
1056
+
1057
+ const intervalSec = 5 // 相同提示触发间隔
1058
+ const durationSec = 4.5 // 提示持续时间
1059
+ let mapItem = videoMessageMap.get(userId)
1060
+ if (!mapItem) {
1061
+ mapItem = {
1062
+ messageValue: value,
1063
+ clearTimer: null,
1064
+ valueMap: new Map()
1065
+ }
1037
1066
  }
1067
+ const valueMap = mapItem.valueMap
1068
+ if (valueMap.get(value) == undefined) {
1069
+ // map中没有相同消息
1070
+ valueMap.set(value, setTimeout(() => {
1071
+ valueMap.delete(value)
1072
+ }, intervalSec * 1000))
1038
1073
 
1074
+ mapItem.messageValue = value
1075
+ clearTimeout(mapItem.clearTimer)
1076
+ mapItem.clearTimer = setTimeout(() => {
1077
+ mapItem.messageValue = ''
1078
+ }, durationSec * 1000)
1079
+ videoMessageMap.set(userId, mapItem)
1080
+ }
1039
1081
  }
1040
1082
  // 人脸识别
1041
1083
  facialRecognition = () => {
@@ -1201,7 +1243,8 @@ class Video extends Component {
1201
1243
  name: 'video' + sortedlist[i-1].idIndex,
1202
1244
  title: sortedlist[i-1].videoName,
1203
1245
  mute: sortedlist[i-1].mute,
1204
- noVideo: sortedlist[i-1].noVideo
1246
+ noVideo: sortedlist[i-1].noVideo,
1247
+ userId: sortedlist[i-1].userId,
1205
1248
  })
1206
1249
  }
1207
1250
  }
@@ -1243,6 +1286,10 @@ class Video extends Component {
1243
1286
  cobj.clearRect(0, 0, 640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1244
1287
  canvas.width = 640;
1245
1288
  canvas.height = 360 * this.state.listVideoPicture.length + baseStartHeight;
1289
+ if (this.state.listVideoPicture.length == 0) {
1290
+ // 画中画设置最小高度,避免没有人时 宽度被拉得很大
1291
+ canvas.height = 360 + baseStartHeight
1292
+ }
1246
1293
  for (let i = 0; i < this.state.listVideoPicture.length; i++) {
1247
1294
 
1248
1295
  let videoId = this.state.listVideoPicture[i].name;
@@ -1378,6 +1425,23 @@ class Video extends Component {
1378
1425
 
1379
1426
  }
1380
1427
 
1428
+ // 绘制消息
1429
+ if (videoMessageMap.get(this.state.listVideoPicture[i].userId)) {
1430
+ let str = videoMessageMap.get(this.state.listVideoPicture[i].userId).messageValue
1431
+ if (str) {
1432
+ cobj.fillStyle = '#F8F2F3';
1433
+ cobj.font = "normal lighter 30px sans-serif";
1434
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1435
+ const startY = 360 * i + baseStartHeight
1436
+ cobj.fillRect(0, startY, 640, messageBoxHeight)
1437
+ cobj.textAlign = 'center';
1438
+ cobj.strokeStyle = 'black';
1439
+ cobj.lineWidth = 2
1440
+ cobj.strokeText(str, 320, startY + messageBoxHeight - 15);
1441
+ cobj.stroke();
1442
+ }
1443
+ }
1444
+
1381
1445
  }
1382
1446
  cobj.fillStyle = '#333333';
1383
1447
  cobj.fillRect(0, 0, 640, baseStartHeight)
@@ -1570,7 +1634,7 @@ class Video extends Component {
1570
1634
  }, ()=>{
1571
1635
  this.pictureInPicture('Refresh')
1572
1636
  })
1573
- this.messageClick('客户切换其他软件', 'error')
1637
+ this.messageClick('客户切换其他软件', 'error', Mival.data.userId)
1574
1638
  }
1575
1639
  }
1576
1640
  else if (Mival.typeId == 3003) { // app进入前台
@@ -1592,7 +1656,7 @@ class Video extends Component {
1592
1656
  if (Mival.data && Mival.data.userId) {
1593
1657
  TITLE = this.getUserTitle(Mival.data.userId)
1594
1658
  }
1595
- this.messageClick(TITLE+'人脸已离框', 'error')
1659
+ this.messageClick(TITLE+'人脸已离框', 'error', Mival.data.userId)
1596
1660
  // this.saveVideoPoint('ffd', '客户人脸离框');
1597
1661
  }
1598
1662
  else if (Mival.typeId == 5002) { // 客户端背光
@@ -1600,7 +1664,7 @@ class Video extends Component {
1600
1664
  if (Mival.data && Mival.data.userId) {
1601
1665
  TITLE = this.getUserTitle(Mival.data.userId)
1602
1666
  }
1603
- this.messageClick(TITLE+'背光、曝光过度', 'error')
1667
+ this.messageClick(TITLE+'背光、曝光过度', 'error', Mival.data.userId)
1604
1668
  // this.saveVideoPoint('env', '客户端背光、曝光过度');
1605
1669
  }
1606
1670
  else if (Mival.typeId == 5003) { // 客户端弱网
@@ -1608,11 +1672,11 @@ class Video extends Component {
1608
1672
  if (Mival.data && Mival.data.userId) {
1609
1673
  TITLE = this.getUserTitle(Mival.data.userId)
1610
1674
  }
1611
- this.messageClick(TITLE+'当前网络较弱', 'error')
1675
+ this.messageClick(TITLE+'当前网络较弱', 'error', Mival.data.userId)
1612
1676
  // this.saveVideoPoint('wnd', '客户端弱网');
1613
1677
  }
1614
1678
  else if (Mival.typeId == 5004) { // ipad低电量
1615
- this.messageClick('IPAD电量过低', 'error')
1679
+ this.messageClick('IPAD电量过低', 'error', Mival.data.userId)
1616
1680
 
1617
1681
  this.setState({
1618
1682
  ipadLowPowerErrorModalVisible: true,
@@ -1628,6 +1692,13 @@ class Video extends Component {
1628
1692
  }
1629
1693
  setTimeout(this.ipadLowPowerPlay, 0);
1630
1694
  }
1695
+ else if (Mival.typeId == 5005) { // 客户端人脸数量变化
1696
+ let TITLE = '客户'
1697
+ if (Mival.data && Mival.data.userId) {
1698
+ TITLE = this.getUserTitle(Mival.data.userId)
1699
+ }
1700
+ this.messageClick(TITLE+'人脸数量发生变化', 'error', Mival.data.userId)
1701
+ }
1631
1702
  else if (Mival.typeId == 1220) {
1632
1703
  // 一炒多的图片 1214
1633
1704
  if (Mival.sessionId == this.state.sessionId) {
@@ -1912,7 +1983,7 @@ class Video extends Component {
1912
1983
  img.onload = () => {
1913
1984
  const origin = cv.imread(img)
1914
1985
  // let start = new Date().getTime()
1915
- const res = isLight(origin)
1986
+ const res = isLight(origin, this.props.lightSensitivity)
1916
1987
  if (res==1 || res== -1){
1917
1988
  // 背景曝光过度
1918
1989
  this.messageClick('检测到当前背光、曝光过度', 'error')
@@ -1937,7 +2008,7 @@ class Video extends Component {
1937
2008
  img.onload = () => {
1938
2009
  const origin = cv.imread(img)
1939
2010
  // let start = new Date().getTime()
1940
- const res = isLight(origin)
2011
+ const res = isLight(origin, this.props.lightSensitivity)
1941
2012
  if (res==1 || res==-1){
1942
2013
  // 背景曝光过度
1943
2014
  this.state.envInfo.lightResult = '不合格'
@@ -2708,6 +2779,7 @@ class Video extends Component {
2708
2779
 
2709
2780
  }
2710
2781
  if (sid == document.getElementById('publish_streamId1').name || !document.getElementById('publish_streamId1').name) {
2782
+ console.log('OnUnPublishSucc clearStreamRemain!!!')
2711
2783
  clearStreamRemain()
2712
2784
  }
2713
2785
  };
@@ -3496,10 +3568,15 @@ class Video extends Component {
3496
3568
  }
3497
3569
  }
3498
3570
  }
3571
+ componentDidCatch(error, info) {
3572
+ console.log('componentDidCatch')
3573
+ console.error(error, info)
3574
+ }
3575
+
3499
3576
  componentWillUnmount() {
3500
3577
  this.saveLog('Exit meeting')
3501
3578
  if (this.test_controller && this.state.sessionType) {
3502
- clearStreamRemain()
3579
+ // clearStreamRemain() // 谨慎使用,有页面crash问题
3503
3580
  this.test_controller.LeaveRoom()
3504
3581
  this.test_controller.Disconnect()
3505
3582
  try {
@@ -3798,7 +3875,7 @@ class Video extends Component {
3798
3875
  })
3799
3876
  this.asr_controller = new MyAsrController({
3800
3877
  token: this.state.asrToken,
3801
- appkey: this.state.asrAppKey,
3878
+ appKey: this.state.asrAppKey,
3802
3879
  url: this.state.asrServerUrl,
3803
3880
  recorder: this.state.recorder
3804
3881
  })
@@ -5627,7 +5704,7 @@ class Video extends Component {
5627
5704
  this.setState({
5628
5705
  isModalVisibleEnvironment: false,
5629
5706
  })
5630
- if (!this.state.isPictureInPicture && this.props.recordMode != 2) {
5707
+ if (!this.state.isPictureInPicture) {
5631
5708
  this.pictureInPicture()
5632
5709
  }
5633
5710
  }
@@ -7050,6 +7127,7 @@ Video.defaultProps = {
7050
7127
  whetherNeedAsr: false, // 是否在双录时开启违禁词检测
7051
7128
  faceDetectInterval: 6, // 人脸检测间隔(秒)
7052
7129
  lightDetectInterval: 6, // 背光检测间隔(秒)
7130
+ lightSensitivity: 1, // 光线敏感度系数,默认1
7053
7131
  userSide: 2,
7054
7132
  meetingDuration: null, // 会议时长,单位小时
7055
7133
  recordMode: 1, // 录制模式 1远程录制 2网点录制
@@ -2,7 +2,6 @@
2
2
  // import Recorder from "js-audio-recorder";
3
3
  // import Recorder from "./recorder";
4
4
 
5
- import header from "../pages/header/header";
6
5
 
7
6
  // console.log(Recorder)
8
7
  //生成32位随机数UUID
@@ -38,8 +37,9 @@ let websocket_audio2txt_complete_time_end = 100; //websocket 语音转文本
38
37
 
39
38
  export default class MyAsrController {
40
39
  constructor(headers) {
40
+ console.log('MyAsrController', headers, headers.appKey)
41
41
  this.token = headers.token || 'default';
42
- this.appKey = headers.appKey || 'E6DAPlpMun5L2dJ7';
42
+ this.appKey = headers.appKey;
43
43
  this.url = headers.url;
44
44
 
45
45
  //初始化录音实例
@@ -98,7 +98,11 @@ export default class MyAsrController {
98
98
  }
99
99
 
100
100
  Disconnect() {
101
- this.recorderInstance.stop();
101
+ try {
102
+ this.recorderInstance.stop();
103
+ } catch(err){
104
+ console.log(err)
105
+ }
102
106
  clearInterval(this.interval);
103
107
  this.websocketStopTranscription()
104
108
  }
@@ -213,7 +217,7 @@ export default class MyAsrController {
213
217
  getPCMAndSend() {
214
218
  //获取音频信息
215
219
  let NextData = this.recorderInstance.getNextData();
216
- let blob = new Blob([NextData])
220
+ let blob = new Blob(NextData)
217
221
  let blob_size = blob.size;
218
222
  // console.log("获取音频信息,并发送,blob_size:"+blob_size , blob);
219
223
 
@@ -49,7 +49,7 @@ function debounce(fn, delay = 500) {
49
49
  },delay)
50
50
  }
51
51
  }
52
- function isLight(src) {
52
+ function isLight(src, sensitivity = 1) {
53
53
  let gray = new cv.Mat()
54
54
  cv.cvtColor(src, gray, cv.COLOR_BGR2GRAY)
55
55
  let sum = 0;
@@ -84,8 +84,16 @@ function isLight(src) {
84
84
  gray.delete();
85
85
 
86
86
  console.log('亮度值:', cast)
87
+ if (typeof sensitivity == 'number') {
88
+ console.log('灵敏系数:', sensitivity)
89
+ console.log('计算值(<1正常):', cast * sensitivity)
90
+ } else {
91
+ console.error('sensitivity param should be type of number')
92
+ sensitivity = 1
93
+ }
94
+
87
95
  //std::cout << "亮度异常值:" << cast << std::endl;
88
- if (cast > 1)
96
+ if (cast * sensitivity > 1)
89
97
  {
90
98
  if (avg > 0)
91
99
  {