@100mslive/hms-virtual-background 1.3.2 → 1.3.3-alpha

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.
@@ -917,8 +917,16 @@ var TAG$1 = 'VBProcessor';
917
917
  var pkg$1 = /*#__PURE__*/require("../package.json");
918
918
 
919
919
  var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
920
- function HMSVirtualBackgroundPlugin(background) {
920
+ function HMSVirtualBackgroundPlugin(background, enableSharpening) {
921
+ if (enableSharpening === void 0) {
922
+ enableSharpening = false;
923
+ }
924
+
925
+ this.backgroundType = "none";
921
926
  this.background = background;
927
+ this.enableSharpening = enableSharpening;
928
+ this.backgroundImage = null;
929
+ this.backgroundVideo = null;
922
930
  this.personMaskWidth = 256;
923
931
  this.personMaskHeight = 144;
924
932
  this.isVirtualBackground = false;
@@ -937,6 +945,7 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
937
945
  this.personMaskCanvas.width = this.personMaskWidth;
938
946
  this.personMaskCanvas.height = this.personMaskHeight;
939
947
  this.personMaskCtx = this.personMaskCanvas.getContext('2d');
948
+ this.filters = {};
940
949
  this.log(TAG$1, "Virtual Background plugin created");
941
950
  this.setBackground(this.background);
942
951
  }
@@ -970,6 +979,11 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
970
979
  return this.tfLitePromise;
971
980
 
972
981
  case 11:
982
+ if (this.enableSharpening) {
983
+ this.initSharpenFilter();
984
+ }
985
+
986
+ case 12:
973
987
  case "end":
974
988
  return _context.stop();
975
989
  }
@@ -998,71 +1012,121 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
998
1012
  };
999
1013
 
1000
1014
  _proto.setBackground = /*#__PURE__*/function () {
1001
- var _setBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(path) {
1015
+ var _setBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(path) {
1016
+ var _this = this;
1017
+
1002
1018
  var img;
1003
- return runtime_1.wrap(function _callee2$(_context2) {
1019
+ return runtime_1.wrap(function _callee3$(_context3) {
1004
1020
  while (1) {
1005
- switch (_context2.prev = _context2.next) {
1021
+ switch (_context3.prev = _context3.next) {
1006
1022
  case 0:
1007
1023
  if (!(path !== "")) {
1008
- _context2.next = 24;
1024
+ _context3.next = 43;
1009
1025
  break;
1010
1026
  }
1011
1027
 
1012
1028
  if (!(path === "none")) {
1013
- _context2.next = 7;
1029
+ _context3.next = 8;
1014
1030
  break;
1015
1031
  }
1016
1032
 
1017
1033
  this.log(TAG$1, 'setting background to :', path);
1018
1034
  this.background = "none";
1035
+ this.backgroundType = "none";
1019
1036
  this.isVirtualBackground = false;
1020
- _context2.next = 22;
1037
+ _context3.next = 41;
1021
1038
  break;
1022
1039
 
1023
- case 7:
1040
+ case 8:
1024
1041
  if (!(path === "blur")) {
1025
- _context2.next = 13;
1042
+ _context3.next = 15;
1026
1043
  break;
1027
1044
  }
1028
1045
 
1029
1046
  this.log(TAG$1, 'setting background to :', path);
1030
1047
  this.background = "blur";
1048
+ this.backgroundType = "blur"; //TODO: check this
1049
+
1031
1050
  this.isVirtualBackground = false;
1032
- _context2.next = 22;
1051
+ _context3.next = 41;
1033
1052
  break;
1034
1053
 
1035
- case 13:
1036
- _context2.next = 15;
1054
+ case 15:
1055
+ if (!(path instanceof HTMLImageElement)) {
1056
+ _context3.next = 29;
1057
+ break;
1058
+ }
1059
+
1060
+ this.log("setting background to image", path);
1061
+ _context3.next = 19;
1037
1062
  return this.setImage(path);
1038
1063
 
1039
- case 15:
1040
- img = _context2.sent;
1064
+ case 19:
1065
+ img = _context3.sent;
1041
1066
 
1042
1067
  if (!(!img || !img.complete || !img.naturalHeight)) {
1043
- _context2.next = 20;
1068
+ _context3.next = 24;
1044
1069
  break;
1045
1070
  }
1046
1071
 
1047
1072
  throw new Error('Invalid image. Provide a valid and successfully loaded HTMLImageElement');
1048
1073
 
1049
- case 20:
1074
+ case 24:
1050
1075
  this.isVirtualBackground = true;
1051
1076
  this.backgroundImage = img;
1077
+ this.backgroundType = "image";
1052
1078
 
1053
- case 22:
1054
- _context2.next = 25;
1079
+ case 27:
1080
+ _context3.next = 41;
1055
1081
  break;
1056
1082
 
1057
- case 24:
1058
- this.log(TAG$1, "Not updating anything using the previous background Settings");
1083
+ case 29:
1084
+ if (!(path instanceof HTMLVideoElement)) {
1085
+ _context3.next = 40;
1086
+ break;
1087
+ }
1088
+
1089
+ this.log("setting background to video", path);
1090
+ this.isVirtualBackground = true;
1091
+ this.backgroundType = "video";
1092
+ this.backgroundVideo = path;
1093
+ this.backgroundVideo.crossOrigin = 'anonymous';
1094
+ this.backgroundVideo.muted = true;
1095
+ this.backgroundVideo.loop = true;
1096
+ this.backgroundVideo.oncanplaythrough = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2() {
1097
+ return runtime_1.wrap(function _callee2$(_context2) {
1098
+ while (1) {
1099
+ switch (_context2.prev = _context2.next) {
1100
+ case 0:
1101
+ _context2.next = 2;
1102
+ return _this.backgroundVideo.play();
1103
+
1104
+ case 2:
1105
+ case "end":
1106
+ return _context2.stop();
1107
+ }
1108
+ }
1109
+ }, _callee2);
1110
+ }));
1111
+ _context3.next = 41;
1112
+ break;
1059
1113
 
1060
- case 25:
1114
+ case 40:
1115
+ throw new Error("Invalid background supplied, see the docs to check supported background type");
1116
+
1117
+ case 41:
1118
+ _context3.next = 44;
1119
+ break;
1120
+
1121
+ case 43:
1122
+ throw new Error("Invalid background supplied, see the docs to check supported background type");
1123
+
1124
+ case 44:
1061
1125
  case "end":
1062
- return _context2.stop();
1126
+ return _context3.stop();
1063
1127
  }
1064
1128
  }
1065
- }, _callee2, this);
1129
+ }, _callee3, this);
1066
1130
  }));
1067
1131
 
1068
1132
  function setBackground(_x) {
@@ -1074,9 +1138,15 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1074
1138
 
1075
1139
  _proto.stop = function stop() {
1076
1140
  if (this.isVirtualBackground) {
1077
- var _this$backgroundImage;
1141
+ var _this$backgroundImage, _this$backgroundVideo;
1078
1142
 
1079
1143
  (_this$backgroundImage = this.backgroundImage) == null ? void 0 : _this$backgroundImage.removeAttribute('src');
1144
+ (_this$backgroundVideo = this.backgroundVideo) == null ? void 0 : _this$backgroundVideo.removeAttribute('src');
1145
+
1146
+ if (this.backgroundType == "video") {
1147
+ this.backgroundVideo.loop = false;
1148
+ this.backgroundVideo = null;
1149
+ }
1080
1150
  }
1081
1151
 
1082
1152
  if (this.outputCtx) {
@@ -1086,18 +1156,32 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1086
1156
  };
1087
1157
 
1088
1158
  _proto.processVideoFrame = function processVideoFrame(input, output, skipProcessing) {
1089
- var _this = this;
1159
+ var _this2 = this;
1090
1160
 
1091
1161
  if (!input || !output) {
1092
1162
  throw new Error('Plugin invalid input/output');
1093
1163
  }
1094
1164
 
1095
1165
  this.input = input;
1096
- this.output = output;
1166
+ this.output = output; // if(!this.t1){
1167
+ // this.output.style.position = "fixed"
1168
+ // this.output.style.top = String(0)
1169
+ // document.body.append(this.output)
1170
+ // this.t1 = true
1171
+ // }
1172
+
1097
1173
  var ctx = output.getContext('2d');
1098
1174
 
1099
1175
  if (ctx.canvas.width !== input.width) {
1100
1176
  ctx.canvas.width = input.width;
1177
+
1178
+ if (this.backgroundType == "video") {
1179
+ this.backgroundVideo.width = input.width;
1180
+ this.backgroundVideo.height = input.height;
1181
+ } // this.backgroundVideo!.style.top = String(0)
1182
+ // this.backgroundVideo!.style.position = "fixed"
1183
+ // document.body.append(this.backgroundVideo!)
1184
+
1101
1185
  }
1102
1186
 
1103
1187
  if (ctx.canvas.height !== input.height) {
@@ -1112,24 +1196,24 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1112
1196
  }
1113
1197
 
1114
1198
  var process = /*#__PURE__*/function () {
1115
- var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3() {
1116
- return runtime_1.wrap(function _callee3$(_context3) {
1199
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4() {
1200
+ return runtime_1.wrap(function _callee4$(_context4) {
1117
1201
  while (1) {
1118
- switch (_context3.prev = _context3.next) {
1202
+ switch (_context4.prev = _context4.next) {
1119
1203
  case 0:
1120
- _context3.next = 2;
1121
- return _this.runSegmentation(skipProcessing);
1204
+ _context4.next = 2;
1205
+ return _this2.runSegmentation(skipProcessing);
1122
1206
 
1123
1207
  case 2:
1124
1208
  case "end":
1125
- return _context3.stop();
1209
+ return _context4.stop();
1126
1210
  }
1127
1211
  }
1128
- }, _callee3);
1212
+ }, _callee4);
1129
1213
  }));
1130
1214
 
1131
1215
  return function process() {
1132
- return _ref.apply(this, arguments);
1216
+ return _ref2.apply(this, arguments);
1133
1217
  };
1134
1218
  }();
1135
1219
 
@@ -1143,13 +1227,13 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1143
1227
  };
1144
1228
 
1145
1229
  _proto.setImage = /*#__PURE__*/function () {
1146
- var _setImage = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4(image) {
1147
- return runtime_1.wrap(function _callee4$(_context4) {
1230
+ var _setImage = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(image) {
1231
+ return runtime_1.wrap(function _callee5$(_context5) {
1148
1232
  while (1) {
1149
- switch (_context4.prev = _context4.next) {
1233
+ switch (_context5.prev = _context5.next) {
1150
1234
  case 0:
1151
1235
  image.crossOrigin = 'anonymous';
1152
- return _context4.abrupt("return", new Promise(function (resolve, reject) {
1236
+ return _context5.abrupt("return", new Promise(function (resolve, reject) {
1153
1237
  image.onload = function () {
1154
1238
  return resolve(image);
1155
1239
  };
@@ -1159,10 +1243,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1159
1243
 
1160
1244
  case 2:
1161
1245
  case "end":
1162
- return _context4.stop();
1246
+ return _context5.stop();
1163
1247
  }
1164
1248
  }
1165
- }, _callee4);
1249
+ }, _callee5);
1166
1250
  }));
1167
1251
 
1168
1252
  function setImage(_x2) {
@@ -1184,7 +1268,8 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1184
1268
 
1185
1269
  _proto.resizeInputData = function resizeInputData() {
1186
1270
  this.personMaskCtx.drawImage(this.input, 0, 0, this.input.width, this.input.height, 0, 0, this.personMaskWidth, this.personMaskHeight);
1187
- var imageData = this.personMaskCtx.getImageData(0, 0, this.personMaskWidth, this.personMaskHeight);
1271
+ var imageData = this.personMaskCtx.getImageData(0, 0, this.personMaskWidth, this.personMaskHeight); //
1272
+
1188
1273
  var inputMemoryOffset = this.tfLite._getInputMemoryOffset() / 4;
1189
1274
 
1190
1275
  for (var i = 0; i < this.personMaskPixelCount; i++) {
@@ -1233,11 +1318,32 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1233
1318
  this.outputCtx.globalCompositeOperation = 'source-in';
1234
1319
  this.outputCtx.filter = 'none'; // //Draw the foreground
1235
1320
 
1236
- this.outputCtx.drawImage(this.input, 0, 0); // //Draw the background
1321
+ this.outputCtx.drawImage(this.input, 0, 0);
1322
+
1323
+ if (this.enableSharpening) {
1324
+ this.sharpenFilter();
1325
+ } // //Draw the background
1326
+
1237
1327
 
1238
1328
  this.drawSegmentedBackground();
1239
1329
  };
1240
1330
 
1331
+ _proto.sharpenFilter = function sharpenFilter() {
1332
+ // adding sharpening filter to each frame to improve edges and brightness
1333
+ // The basic idea is that you take the weighed sum of a rectangle of pixels from the source image and use that as the output value using convolution filter
1334
+ // It is applied intermediate output with black background and only mask data in frame
1335
+ // Filter currently used is 3 x 3 sharpening filter with values as shown:
1336
+ // [ 0, -1, 0,
1337
+ // -1, 5, -1,
1338
+ // 0, -1, 0 ]
1339
+ var outputImageData = this.outputCtx.getImageData(0, 0, this.output.width, this.output.height); // filters you may try
1340
+ // [-1, -1, -1, -1, 9, -1, -1, -1, -1]
1341
+ //[0, -1, 0, -1, 5, -1, 0, -1, 0]
1342
+
1343
+ var output = this.filters.convolute(outputImageData);
1344
+ this.outputCtx.putImageData(output, 0, 0);
1345
+ };
1346
+
1241
1347
  _proto.drawPersonMask = function drawPersonMask() {
1242
1348
  this.outputCtx.drawImage(this.personMaskCanvas, 0, 0, this.personMaskWidth, this.personMaskHeight, 0, 0, this.output.width, this.output.height);
1243
1349
  };
@@ -1248,26 +1354,30 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1248
1354
  this.outputCtx.imageSmoothingQuality = 'high';
1249
1355
 
1250
1356
  if (this.isVirtualBackground) {
1251
- this.fitImageToBackground();
1357
+ if (this.backgroundType === "video") {
1358
+ this.fitVideoToBackground();
1359
+ } else if (this.backgroundType === "image") {
1360
+ this.fitImageToBackground();
1361
+ }
1252
1362
  } else {
1253
1363
  this.addBlurToBackground();
1254
1364
  }
1255
1365
  };
1256
1366
 
1257
1367
  _proto.runSegmentation = /*#__PURE__*/function () {
1258
- var _runSegmentation = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(skipProcessing) {
1259
- return runtime_1.wrap(function _callee5$(_context5) {
1368
+ var _runSegmentation = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee6(skipProcessing) {
1369
+ return runtime_1.wrap(function _callee6$(_context6) {
1260
1370
  while (1) {
1261
- switch (_context5.prev = _context5.next) {
1371
+ switch (_context6.prev = _context6.next) {
1262
1372
  case 0:
1263
1373
  if (!this.tfLite) {
1264
- _context5.next = 5;
1374
+ _context6.next = 5;
1265
1375
  break;
1266
1376
  }
1267
1377
 
1268
1378
  // const start = performance.now();
1269
1379
  this.resizeInputData();
1270
- _context5.next = 4;
1380
+ _context6.next = 4;
1271
1381
  return this.infer(skipProcessing);
1272
1382
 
1273
1383
  case 4:
@@ -1276,10 +1386,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1276
1386
 
1277
1387
  case 5:
1278
1388
  case "end":
1279
- return _context5.stop();
1389
+ return _context6.stop();
1280
1390
  }
1281
1391
  }
1282
- }, _callee5, this);
1392
+ }, _callee6, this);
1283
1393
  }));
1284
1394
 
1285
1395
  function runSegmentation(_x3) {
@@ -1289,6 +1399,23 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1289
1399
  return runSegmentation;
1290
1400
  }();
1291
1401
 
1402
+ _proto.fitVideoToBackground = function fitVideoToBackground() {
1403
+ // let input_width: any, input_height: any, x_off: any, y_off: any
1404
+ // if ((this.backgroundVideo!.width / this.backgroundVideo!.height) < this.imageAspectRatio) {
1405
+ // input_width = this.backgroundVideo!.width;
1406
+ // input_height = this.backgroundVideo!.width/ this.imageAspectRatio;
1407
+ // x_off = 0;
1408
+ // y_off = (this.backgroundVideo!.height - input_height) / 2;
1409
+ // }
1410
+ // else {
1411
+ // input_height = this.backgroundVideo!.height;
1412
+ // input_width = this.backgroundVideo!.height * this.imageAspectRatio;
1413
+ // y_off = 0;
1414
+ // x_off = (this.backgroundVideo!.width - input_width) / 2;
1415
+ // }
1416
+ this.outputCtx.drawImage(this.backgroundVideo, 0, 0, this.output.width, this.output.height);
1417
+ };
1418
+
1292
1419
  _proto.fitImageToBackground = function fitImageToBackground() {
1293
1420
  var input_width, input_height, x_offset, y_offset;
1294
1421
 
@@ -1308,11 +1435,11 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1308
1435
  };
1309
1436
 
1310
1437
  _proto.addBlurToBackground = /*#__PURE__*/function () {
1311
- var _addBlurToBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee6() {
1438
+ var _addBlurToBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee7() {
1312
1439
  var blurValue;
1313
- return runtime_1.wrap(function _callee6$(_context6) {
1440
+ return runtime_1.wrap(function _callee7$(_context7) {
1314
1441
  while (1) {
1315
- switch (_context6.prev = _context6.next) {
1442
+ switch (_context7.prev = _context7.next) {
1316
1443
  case 0:
1317
1444
  blurValue = '15px';
1318
1445
  if (this.input.width <= 160) blurValue = '5px';else if (this.input.width <= 320) blurValue = '10px';else if (this.input.width <= 640) blurValue = '15px';else if (this.input.width <= 960) blurValue = '20px';else if (this.input.width <= 1280) blurValue = '25px';else if (this.input.width <= 1920) blurValue = '30px';
@@ -1321,10 +1448,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1321
1448
 
1322
1449
  case 4:
1323
1450
  case "end":
1324
- return _context6.stop();
1451
+ return _context7.stop();
1325
1452
  }
1326
1453
  }
1327
- }, _callee6, this);
1454
+ }, _callee7, this);
1328
1455
  }));
1329
1456
 
1330
1457
  function addBlurToBackground() {
@@ -1334,6 +1461,80 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1334
1461
  return addBlurToBackground;
1335
1462
  }();
1336
1463
 
1464
+ _proto.initSharpenFilter = function initSharpenFilter() {
1465
+ var _this3 = this;
1466
+
1467
+ this.filters.tmpCanvas = document.createElement('canvas');
1468
+ this.filters.tmpCtx = this.filters.tmpCanvas.getContext('2d');
1469
+
1470
+ this.filters.createImageData = function (w, h) {
1471
+ return _this3.filters.tmpCtx.createImageData(w, h);
1472
+ };
1473
+
1474
+ this.filters.convolute = function (pixels, weights, opaque) {
1475
+ if (weights === void 0) {
1476
+ weights = [0, -1, 0, -1, 5, -1, 0, -1, 0];
1477
+ }
1478
+
1479
+ var side = Math.round(Math.sqrt(weights.length));
1480
+ var halfSide = Math.floor(side / 2);
1481
+ var src = pixels.data;
1482
+ var sw = pixels.width;
1483
+ var sh = pixels.height; // pad output by the convolution matrix
1484
+
1485
+ var w = sw;
1486
+ var h = sh;
1487
+
1488
+ var output = _this3.filters.createImageData(w, h);
1489
+
1490
+ var dst = output.data; // go through the destination image pixels
1491
+
1492
+ var alphaFac = opaque ? 1 : 0;
1493
+
1494
+ for (var y = 0; y < h; y = y + 1) {
1495
+ for (var x = 0; x < w; x = x + 1) {
1496
+ var dstOff = (y * w + x) * 4;
1497
+
1498
+ if (src[dstOff + 3] == 0) {
1499
+ continue;
1500
+ } else if (x < w && y < h) {
1501
+ var sy = y;
1502
+ var sx = x; // calculate the weighed sum of the source image pixels that
1503
+ // fall under the convolution matrix
1504
+
1505
+ var r = 0,
1506
+ g = 0,
1507
+ b = 0,
1508
+ a = 0;
1509
+
1510
+ for (var cy = 0; cy < side; cy++) {
1511
+ for (var cx = 0; cx < side; cx++) {
1512
+ var scy = sy + cy - halfSide;
1513
+ var scx = sx + cx - halfSide;
1514
+
1515
+ if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
1516
+ var srcOff = (scy * sw + scx) * 4;
1517
+ var wt = weights[cy * side + cx];
1518
+ r += src[srcOff] * wt;
1519
+ g += src[srcOff + 1] * wt;
1520
+ b += src[srcOff + 2] * wt;
1521
+ a += src[srcOff + 3] * wt;
1522
+ }
1523
+ }
1524
+ }
1525
+
1526
+ dst[dstOff] = r;
1527
+ dst[dstOff + 1] = g;
1528
+ dst[dstOff + 2] = b;
1529
+ dst[dstOff + 3] = a + alphaFac * (255 - a);
1530
+ }
1531
+ }
1532
+ }
1533
+
1534
+ return output;
1535
+ };
1536
+ };
1537
+
1337
1538
  return HMSVirtualBackgroundPlugin;
1338
1539
  }();
1339
1540