@besovideo/webrtc-player 0.10.26 → 0.10.28

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.
package/README.md CHANGED
@@ -33,7 +33,8 @@ import {
33
33
  IPuPlayerProps,
34
34
  IPuPlayerInstance,
35
35
  clearAllDialog,
36
- callEndPointUtils
36
+ callEndPointUtils,
37
+ globalConfigHandler
37
38
  } from "@besovideo/webrtc-player";
38
39
  import "@besovideo/webrtc-player/dist/main.es.css";
39
40
 
@@ -98,6 +99,10 @@ const { instance } = PuPlayer({
98
99
  localRecordCfg?: {
99
100
  //多久产生一个录像文件 5 - 60, 默认 20
100
101
  minuteOneFile ?: number;
102
+ },
103
+ // (可选) 播放窗口水印配置,支持 string 或 string[] 多行水印
104
+ watermark?: {
105
+ text: "测试水印",
101
106
  }
102
107
  });
103
108
 
@@ -465,7 +470,11 @@ const { instance } = PlayBack({
465
470
  zIndexMenu?: number,
466
471
 
467
472
  //(可选) 控制是否显示弹幕,默认显示
468
- displayMode?: 'playback'
473
+ displayMode?: 'playback',
474
+ //(可选)播放窗口水印配置,支持全局配置和实例覆盖
475
+ watermark?: {
476
+ text: "测试水印",
477
+ }
469
478
  })
470
479
 
471
480
  // 打开回放
@@ -473,6 +482,104 @@ instance.open()
473
482
 
474
483
  ```
475
484
 
485
+ **水印配置**
486
+
487
+ `PuPlayer` 和 `PlayBack` 支持水印层。水印是播放窗口上的 DOM/CSS 叠层,不会写入本地录像文件。
488
+
489
+ ```typescript
490
+ import { globalConfigHandler, PuPlayer, PlayBack } from "@besovideo/webrtc-player";
491
+
492
+ interface IWatermarkConfig {
493
+ // 是否启用水印
494
+ enable?: boolean;
495
+ // 水印文本;数组会按多行显示
496
+ text?: string | string[];
497
+ // 水印透明度
498
+ opacity?: number;
499
+ // 字号
500
+ fontSize?: number;
501
+ // 字重
502
+ fontWeight?: number | string;
503
+ // 文字颜色
504
+ color?: string;
505
+ // 描边颜色
506
+ strokeColor?: string;
507
+ // 描边宽度
508
+ strokeWidth?: number;
509
+ // 旋转角度
510
+ rotate?: number;
511
+ // 最小横向间距
512
+ gapX?: number;
513
+ // 最小纵向间距
514
+ gapY?: number;
515
+ // 大屏自适应密度:最多显示的列数
516
+ maxColumns?: number;
517
+ // 大屏自适应密度:最多显示的行数
518
+ maxRows?: number;
519
+ // 可选,水印层级;默认不设置
520
+ zIndex?: number;
521
+ }
522
+
523
+ // 全局配置:影响之后创建的 PuPlayer 和 PlayBack 实例
524
+ globalConfigHandler.setDefaultProps({
525
+ watermark: {
526
+ // 支持 string 或 string[],数组会按多行显示
527
+ text: ["测试水印", "仅供内部使用"],
528
+ // 是否启用水印,默认 true;设置为 false 可关闭
529
+ enable: true,
530
+ // 水印透明度,默认 0.28
531
+ opacity: 0.28,
532
+ // 字号,默认 16
533
+ fontSize: 16,
534
+ // 字重,默认 normal
535
+ fontWeight: "normal",
536
+ // 文字颜色,默认 #fff
537
+ color: "#fff",
538
+ // 描边颜色,默认 #000,用于提升浅色/复杂画面上的可读性
539
+ strokeColor: "#000",
540
+ // 描边宽度,默认 2
541
+ strokeWidth: 2,
542
+ // 旋转角度,默认 -20
543
+ rotate: -20,
544
+ // 最小横向间距,默认 180
545
+ gapX: 180,
546
+ // 最小纵向间距,默认 120
547
+ gapY: 120,
548
+ // 大屏自适应密度:最多约 4 列,默认 4
549
+ maxColumns: 4,
550
+ // 大屏自适应密度:最多约 3 行,默认 3
551
+ maxRows: 3,
552
+ // 可选,水印层级;默认不设置,位于视频上方、遮罩和控制层下方
553
+ // zIndex: 1,
554
+ },
555
+ });
556
+
557
+ // 单实例覆盖全局配置
558
+ PuPlayer({
559
+ // ...
560
+ watermark: {
561
+ text: "当前设备水印",
562
+ maxColumns: 3,
563
+ maxRows: 2,
564
+ },
565
+ });
566
+
567
+ // 单实例关闭水印
568
+ PlayBack({
569
+ // ...
570
+ watermark: {
571
+ enable: false,
572
+ },
573
+ });
574
+ ```
575
+
576
+ 水印间距会根据播放窗口大小自动调整。`gapX` / `gapY` 表示最小间距,`maxColumns` / `maxRows` 用于限制大屏下最多显示的水印密度:
577
+
578
+ ```typescript
579
+ 实际横向间距 = Math.max(gapX, 播放窗口宽度 / maxColumns)
580
+ 实际纵向间距 = Math.max(gapY, 播放窗口高度 / maxRows)
581
+ ```
582
+
476
583
  ***媒体流推送***
477
584
  ``` typescript
478
585
  const callEndPointUtils: {
@@ -665,8 +772,6 @@ yarn start
665
772
  yarn version
666
773
  yarn build
667
774
  yarn publish
668
- # 版本号按照 Major.Minor.Patch 规范
669
- # 可参考https://www.jianshu.com/p/c675121a8bfd
670
775
 
671
776
 
672
777
  ```
@@ -521,6 +521,18 @@
521
521
  width: 100%;
522
522
  height: 100%;
523
523
  }
524
+ .bvplayer-watermark {
525
+ position: absolute;
526
+ top: 0;
527
+ right: 0;
528
+ bottom: 0;
529
+ left: 0;
530
+ width: 100%;
531
+ height: 100%;
532
+ overflow: hidden;
533
+ pointer-events: none;
534
+ background-repeat: repeat;
535
+ }
524
536
  .bvplayer-controller {
525
537
  position: absolute;
526
538
  bottom: 0;
@@ -124,7 +124,7 @@ var bvPlayerCore = (() => {
124
124
  var define_processenv_default;
125
125
  var init_define_processenv = __esm({
126
126
  "<define:processenv>"() {
127
- define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.10.26", PROJECT_NAMESPACE: "bvplayer" };
127
+ define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.10.28", PROJECT_NAMESPACE: "bvplayer" };
128
128
  }
129
129
  });
130
130
 
@@ -21890,10 +21890,7 @@ padding: 2px 5px;
21890
21890
  return glbConfig;
21891
21891
  },
21892
21892
  setDefaultProps: function(props) {
21893
- Object.keys(props).forEach((itemKey) => {
21894
- const key = itemKey;
21895
- glbConfig[key] = props[key];
21896
- });
21893
+ Object.assign(glbConfig, props);
21897
21894
  }
21898
21895
  };
21899
21896
 
@@ -29083,6 +29080,96 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
29083
29080
  };
29084
29081
  var recordState_default = RecordStatePlugin;
29085
29082
 
29083
+ // src/plugins/watermark.ts
29084
+ init_define_processenv();
29085
+ init_jsx_shim();
29086
+ var PLUGIN_NAME_WATERMARK = "watermark";
29087
+ var defaultWatermarkConfig = {
29088
+ enable: true,
29089
+ opacity: 0.28,
29090
+ fontSize: 16,
29091
+ fontWeight: "normal",
29092
+ color: "#fff",
29093
+ strokeColor: "#000",
29094
+ strokeWidth: 2,
29095
+ rotate: -20,
29096
+ gapX: 180,
29097
+ gapY: 120,
29098
+ maxColumns: 4,
29099
+ maxRows: 3
29100
+ };
29101
+ var escapeXml = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
29102
+ var normalizeText = (text2) => {
29103
+ if (typeof text2 === "string")
29104
+ return text2 ? [text2] : [];
29105
+ return (text2 || []).filter((item) => item);
29106
+ };
29107
+ var createWatermarkSvg = (config) => {
29108
+ const lineHeight = Math.round(config.fontSize * 1.5);
29109
+ const startY = config.gapY / 2 - (config.text.length - 1) * lineHeight / 2;
29110
+ const textNodes = config.text.map((item, index) => {
29111
+ const y2 = startY + index * lineHeight;
29112
+ return `<text x="50%" y="${y2}" text-anchor="middle">${escapeXml(item)}</text>`;
29113
+ }).join("");
29114
+ return `
29115
+ <svg xmlns="http://www.w3.org/2000/svg" width="${config.gapX}" height="${config.gapY}" viewBox="0 0 ${config.gapX} ${config.gapY}">
29116
+ <g transform="rotate(${config.rotate} ${config.gapX / 2} ${config.gapY / 2})" fill="${escapeXml(config.color)}" fill-opacity="${config.opacity}" stroke="${escapeXml(config.strokeColor)}" stroke-opacity="${config.opacity}" stroke-width="${config.strokeWidth}" paint-order="stroke" font-size="${config.fontSize}" font-weight="${escapeXml(`${config.fontWeight}`)}" font-family="Arial, sans-serif">
29117
+ ${textNodes}
29118
+ </g>
29119
+ </svg>`;
29120
+ };
29121
+ var mergeWatermarkConfig = (...configs) => {
29122
+ return configs.reduce((result, config) => {
29123
+ if (!config)
29124
+ return result;
29125
+ return __spreadValues(__spreadValues({}, result), config);
29126
+ }, {});
29127
+ };
29128
+ var WatermarkPlugin = class extends Plugin {
29129
+ constructor(config) {
29130
+ super(PLUGIN_NAME_WATERMARK, "div");
29131
+ this._config = config || {};
29132
+ }
29133
+ init(_container) {
29134
+ this.render();
29135
+ if (this.el && window.ResizeObserver) {
29136
+ this._resizeObserver = new ResizeObserver(() => {
29137
+ this.render();
29138
+ });
29139
+ this._resizeObserver.observe(this.el);
29140
+ }
29141
+ return this.el;
29142
+ }
29143
+ beforeDestroy() {
29144
+ var _a;
29145
+ (_a = this._resizeObserver) == null ? void 0 : _a.disconnect();
29146
+ }
29147
+ render() {
29148
+ if (!this.el)
29149
+ return;
29150
+ const config = __spreadProps(__spreadValues(__spreadValues({}, defaultWatermarkConfig), this._config), {
29151
+ text: normalizeText(this._config.text)
29152
+ });
29153
+ if (!config.enable || !config.text.length) {
29154
+ this.el.style.display = "none";
29155
+ this.el.style.backgroundImage = "";
29156
+ return;
29157
+ }
29158
+ const gapX = config.maxColumns > 0 ? Math.max(config.gapX, this.el.clientWidth / config.maxColumns) : config.gapX;
29159
+ const gapY = config.maxRows > 0 ? Math.max(config.gapY, this.el.clientHeight / config.maxRows) : config.gapY;
29160
+ const renderConfig = __spreadProps(__spreadValues({}, config), {
29161
+ gapX,
29162
+ gapY
29163
+ });
29164
+ const svg = createWatermarkSvg(renderConfig);
29165
+ this.el.style.display = "block";
29166
+ this.el.style.zIndex = typeof config.zIndex === "number" ? `${config.zIndex}` : "";
29167
+ this.el.style.backgroundImage = `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}")`;
29168
+ this.el.style.backgroundSize = `${gapX}px ${gapY}px`;
29169
+ }
29170
+ };
29171
+ var watermark_default = WatermarkPlugin;
29172
+
29086
29173
  // src/plugins/player/index.tsx
29087
29174
  var DIRECT_SUPPORT_TYPES = /* @__PURE__ */ ((DIRECT_SUPPORT_TYPES2) => {
29088
29175
  DIRECT_SUPPORT_TYPES2["MP4"] = "MP4";
@@ -29122,6 +29209,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
29122
29209
  this._spinner = new spinner_default({ spin: false });
29123
29210
  this._toast = new toast_default();
29124
29211
  this._mask = new mask_default({ visible: false });
29212
+ this._watermark = new watermark_default(options == null ? void 0 : options.watermark);
29125
29213
  this._infoModal = new ModalPlugin({
29126
29214
  container: this.el,
29127
29215
  title: t("info"),
@@ -29172,6 +29260,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
29172
29260
  const spinnerEl = this._spinner.init();
29173
29261
  const toastEl = this._toast.init();
29174
29262
  const maskEl = this._mask.init();
29263
+ const watermarkEl = this._watermark.init();
29175
29264
  const panelEls = this._panel ? this._panel.init() : [];
29176
29265
  const infoModalEl = this._infoModal.init();
29177
29266
  const ptzEl = this.ptz.init();
@@ -29179,6 +29268,7 @@ ${event.candidate ? event.candidate.candidate : "(null)"}`
29179
29268
  core_default.dom.append(
29180
29269
  this.el,
29181
29270
  videoEl,
29271
+ watermarkEl,
29182
29272
  spinnerEl,
29183
29273
  maskEl,
29184
29274
  infoModalEl,
@@ -33511,6 +33601,7 @@ registerProcessor('bv-audio-processor', BVAudioProcessor);
33511
33601
  puOption,
33512
33602
  defaultMediaOption = { audio: true, video: true },
33513
33603
  testUrl,
33604
+ watermark,
33514
33605
  videoFit = "fill",
33515
33606
  muted,
33516
33607
  apiPrefix,
@@ -33630,6 +33721,10 @@ registerProcessor('bv-audio-processor', BVAudioProcessor);
33630
33721
  enableController,
33631
33722
  disabledControls
33632
33723
  },
33724
+ watermark: mergeWatermarkConfig(
33725
+ globalConfigHandler.getDefaultProps().watermark,
33726
+ watermark
33727
+ ),
33633
33728
  recorderConfig: localRecordCfg
33634
33729
  });
33635
33730
  player.addEventListener("init", (e) => {
@@ -34816,6 +34911,7 @@ registerProcessor('bv-audio-processor', BVAudioProcessor);
34816
34911
  }
34817
34912
  }
34818
34913
  } catch (e) {
34914
+ console.error(e);
34819
34915
  }
34820
34916
  try {
34821
34917
  if (!mediaStream && !!openParams.beCall) {
@@ -36010,6 +36106,7 @@ a=fmtp:${pt} x-google-start-bitrate=${bitrate}`
36010
36106
  disableAudio: !!!params.audio
36011
36107
  });
36012
36108
  if (resultResult.code != "SUCCESS") {
36109
+ processHandle.invoke();
36013
36110
  return {
36014
36111
  code: resultResult.code,
36015
36112
  message: resultResult.message
@@ -37062,7 +37159,8 @@ a=fmtp:${pt} x-google-start-bitrate=${bitrate}`
37062
37159
  zIndexMenu,
37063
37160
  displayMode,
37064
37161
  playbackUrl,
37065
- cryptkey
37162
+ cryptkey,
37163
+ watermark
37066
37164
  } = __spreadValues(__spreadValues({}, defaultProps3), props);
37067
37165
  i18n_default(locale);
37068
37166
  let hplayer = void 0;
@@ -37106,7 +37204,11 @@ a=fmtp:${pt} x-google-start-bitrate=${bitrate}`
37106
37204
  "mike"
37107
37205
  ],
37108
37206
  enableController: false
37109
- }
37207
+ },
37208
+ watermark: mergeWatermarkConfig(
37209
+ globalConfigHandler.getDefaultProps().watermark,
37210
+ watermark
37211
+ )
37110
37212
  });
37111
37213
  const barHandle = new PlaybackBar();
37112
37214
  this.emitClick = () => {
package/dist/main.es.css CHANGED
@@ -521,6 +521,18 @@
521
521
  width: 100%;
522
522
  height: 100%;
523
523
  }
524
+ .bvplayer-watermark {
525
+ position: absolute;
526
+ top: 0;
527
+ right: 0;
528
+ bottom: 0;
529
+ left: 0;
530
+ width: 100%;
531
+ height: 100%;
532
+ overflow: hidden;
533
+ pointer-events: none;
534
+ background-repeat: repeat;
535
+ }
524
536
  .bvplayer-controller {
525
537
  position: absolute;
526
538
  bottom: 0;
package/dist/main.es.js CHANGED
@@ -118,7 +118,7 @@ var __async = (__this, __arguments, generator) => {
118
118
  var define_processenv_default;
119
119
  var init_define_processenv = __esm({
120
120
  "<define:processenv>"() {
121
- define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.10.26", PROJECT_NAMESPACE: "bvplayer" };
121
+ define_processenv_default = { NODE_ENV: "production", SH_LIB_NAME: "@besovideo/webrtc-player", SH_LIB_VERSION: "0.10.28", PROJECT_NAMESPACE: "bvplayer" };
122
122
  }
123
123
  });
124
124
 
@@ -21872,10 +21872,7 @@ var globalConfigHandler = {
21872
21872
  return glbConfig;
21873
21873
  },
21874
21874
  setDefaultProps: function(props) {
21875
- Object.keys(props).forEach((itemKey) => {
21876
- const key = itemKey;
21877
- glbConfig[key] = props[key];
21878
- });
21875
+ Object.assign(glbConfig, props);
21879
21876
  }
21880
21877
  };
21881
21878
 
@@ -29065,6 +29062,96 @@ var RecordStatePlugin = class extends Plugin {
29065
29062
  };
29066
29063
  var recordState_default = RecordStatePlugin;
29067
29064
 
29065
+ // src/plugins/watermark.ts
29066
+ init_define_processenv();
29067
+ init_jsx_shim();
29068
+ var PLUGIN_NAME_WATERMARK = "watermark";
29069
+ var defaultWatermarkConfig = {
29070
+ enable: true,
29071
+ opacity: 0.28,
29072
+ fontSize: 16,
29073
+ fontWeight: "normal",
29074
+ color: "#fff",
29075
+ strokeColor: "#000",
29076
+ strokeWidth: 2,
29077
+ rotate: -20,
29078
+ gapX: 180,
29079
+ gapY: 120,
29080
+ maxColumns: 4,
29081
+ maxRows: 3
29082
+ };
29083
+ var escapeXml = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
29084
+ var normalizeText = (text2) => {
29085
+ if (typeof text2 === "string")
29086
+ return text2 ? [text2] : [];
29087
+ return (text2 || []).filter((item) => item);
29088
+ };
29089
+ var createWatermarkSvg = (config) => {
29090
+ const lineHeight = Math.round(config.fontSize * 1.5);
29091
+ const startY = config.gapY / 2 - (config.text.length - 1) * lineHeight / 2;
29092
+ const textNodes = config.text.map((item, index) => {
29093
+ const y2 = startY + index * lineHeight;
29094
+ return `<text x="50%" y="${y2}" text-anchor="middle">${escapeXml(item)}</text>`;
29095
+ }).join("");
29096
+ return `
29097
+ <svg xmlns="http://www.w3.org/2000/svg" width="${config.gapX}" height="${config.gapY}" viewBox="0 0 ${config.gapX} ${config.gapY}">
29098
+ <g transform="rotate(${config.rotate} ${config.gapX / 2} ${config.gapY / 2})" fill="${escapeXml(config.color)}" fill-opacity="${config.opacity}" stroke="${escapeXml(config.strokeColor)}" stroke-opacity="${config.opacity}" stroke-width="${config.strokeWidth}" paint-order="stroke" font-size="${config.fontSize}" font-weight="${escapeXml(`${config.fontWeight}`)}" font-family="Arial, sans-serif">
29099
+ ${textNodes}
29100
+ </g>
29101
+ </svg>`;
29102
+ };
29103
+ var mergeWatermarkConfig = (...configs) => {
29104
+ return configs.reduce((result, config) => {
29105
+ if (!config)
29106
+ return result;
29107
+ return __spreadValues(__spreadValues({}, result), config);
29108
+ }, {});
29109
+ };
29110
+ var WatermarkPlugin = class extends Plugin {
29111
+ constructor(config) {
29112
+ super(PLUGIN_NAME_WATERMARK, "div");
29113
+ this._config = config || {};
29114
+ }
29115
+ init(_container) {
29116
+ this.render();
29117
+ if (this.el && window.ResizeObserver) {
29118
+ this._resizeObserver = new ResizeObserver(() => {
29119
+ this.render();
29120
+ });
29121
+ this._resizeObserver.observe(this.el);
29122
+ }
29123
+ return this.el;
29124
+ }
29125
+ beforeDestroy() {
29126
+ var _a;
29127
+ (_a = this._resizeObserver) == null ? void 0 : _a.disconnect();
29128
+ }
29129
+ render() {
29130
+ if (!this.el)
29131
+ return;
29132
+ const config = __spreadProps(__spreadValues(__spreadValues({}, defaultWatermarkConfig), this._config), {
29133
+ text: normalizeText(this._config.text)
29134
+ });
29135
+ if (!config.enable || !config.text.length) {
29136
+ this.el.style.display = "none";
29137
+ this.el.style.backgroundImage = "";
29138
+ return;
29139
+ }
29140
+ const gapX = config.maxColumns > 0 ? Math.max(config.gapX, this.el.clientWidth / config.maxColumns) : config.gapX;
29141
+ const gapY = config.maxRows > 0 ? Math.max(config.gapY, this.el.clientHeight / config.maxRows) : config.gapY;
29142
+ const renderConfig = __spreadProps(__spreadValues({}, config), {
29143
+ gapX,
29144
+ gapY
29145
+ });
29146
+ const svg = createWatermarkSvg(renderConfig);
29147
+ this.el.style.display = "block";
29148
+ this.el.style.zIndex = typeof config.zIndex === "number" ? `${config.zIndex}` : "";
29149
+ this.el.style.backgroundImage = `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}")`;
29150
+ this.el.style.backgroundSize = `${gapX}px ${gapY}px`;
29151
+ }
29152
+ };
29153
+ var watermark_default = WatermarkPlugin;
29154
+
29068
29155
  // src/plugins/player/index.tsx
29069
29156
  var DIRECT_SUPPORT_TYPES = /* @__PURE__ */ ((DIRECT_SUPPORT_TYPES2) => {
29070
29157
  DIRECT_SUPPORT_TYPES2["MP4"] = "MP4";
@@ -29104,6 +29191,7 @@ var PlayerPlugin = class extends Plugin {
29104
29191
  this._spinner = new spinner_default({ spin: false });
29105
29192
  this._toast = new toast_default();
29106
29193
  this._mask = new mask_default({ visible: false });
29194
+ this._watermark = new watermark_default(options == null ? void 0 : options.watermark);
29107
29195
  this._infoModal = new ModalPlugin({
29108
29196
  container: this.el,
29109
29197
  title: t("info"),
@@ -29154,6 +29242,7 @@ var PlayerPlugin = class extends Plugin {
29154
29242
  const spinnerEl = this._spinner.init();
29155
29243
  const toastEl = this._toast.init();
29156
29244
  const maskEl = this._mask.init();
29245
+ const watermarkEl = this._watermark.init();
29157
29246
  const panelEls = this._panel ? this._panel.init() : [];
29158
29247
  const infoModalEl = this._infoModal.init();
29159
29248
  const ptzEl = this.ptz.init();
@@ -29161,6 +29250,7 @@ var PlayerPlugin = class extends Plugin {
29161
29250
  core_default.dom.append(
29162
29251
  this.el,
29163
29252
  videoEl,
29253
+ watermarkEl,
29164
29254
  spinnerEl,
29165
29255
  maskEl,
29166
29256
  infoModalEl,
@@ -33493,6 +33583,7 @@ var PuPlayer = (props) => {
33493
33583
  puOption,
33494
33584
  defaultMediaOption = { audio: true, video: true },
33495
33585
  testUrl,
33586
+ watermark,
33496
33587
  videoFit = "fill",
33497
33588
  muted,
33498
33589
  apiPrefix,
@@ -33612,6 +33703,10 @@ var PuPlayer = (props) => {
33612
33703
  enableController,
33613
33704
  disabledControls
33614
33705
  },
33706
+ watermark: mergeWatermarkConfig(
33707
+ globalConfigHandler.getDefaultProps().watermark,
33708
+ watermark
33709
+ ),
33615
33710
  recorderConfig: localRecordCfg
33616
33711
  });
33617
33712
  player.addEventListener("init", (e) => {
@@ -34798,6 +34893,7 @@ function MediaEndPoint(params) {
34798
34893
  }
34799
34894
  }
34800
34895
  } catch (e) {
34896
+ console.error(e);
34801
34897
  }
34802
34898
  try {
34803
34899
  if (!mediaStream && !!openParams.beCall) {
@@ -35992,6 +36088,7 @@ function pushLocalMedia(params) {
35992
36088
  disableAudio: !!!params.audio
35993
36089
  });
35994
36090
  if (resultResult.code != "SUCCESS") {
36091
+ processHandle.invoke();
35995
36092
  return {
35996
36093
  code: resultResult.code,
35997
36094
  message: resultResult.message
@@ -37044,7 +37141,8 @@ var PlayBack = (props) => {
37044
37141
  zIndexMenu,
37045
37142
  displayMode,
37046
37143
  playbackUrl,
37047
- cryptkey
37144
+ cryptkey,
37145
+ watermark
37048
37146
  } = __spreadValues(__spreadValues({}, defaultProps3), props);
37049
37147
  i18n_default(locale);
37050
37148
  let hplayer = void 0;
@@ -37088,7 +37186,11 @@ var PlayBack = (props) => {
37088
37186
  "mike"
37089
37187
  ],
37090
37188
  enableController: false
37091
- }
37189
+ },
37190
+ watermark: mergeWatermarkConfig(
37191
+ globalConfigHandler.getDefaultProps().watermark,
37192
+ watermark
37193
+ )
37092
37194
  });
37093
37195
  const barHandle = new PlaybackBar();
37094
37196
  this.emitClick = () => {
@@ -1,5 +1,7 @@
1
+ import { IWatermarkConfig } from "../plugins/watermark";
1
2
  export interface IGlobalConfig {
2
3
  bNotSendHost?: boolean;
4
+ watermark?: IWatermarkConfig;
3
5
  }
4
6
  export declare const globalConfigHandler: {
5
7
  getDefaultProps: () => Partial<IGlobalConfig>;
@@ -1,6 +1,7 @@
1
1
  import { SFC, Props, IComponentInstance } from "../core/types";
2
2
  import { IVideoFits } from "../plugins/player";
3
3
  import initI18n from "../locales/i18n";
4
+ import { IWatermarkConfig } from "../plugins/watermark";
4
5
  type Container = HTMLElement | Element | Node | null;
5
6
  interface IPlaybackProps extends Props {
6
7
  fileID: string;
@@ -26,6 +27,7 @@ interface IPlaybackProps extends Props {
26
27
  zIndexMenu?: number;
27
28
  displayMode?: 'playback';
28
29
  cryptkey?: string;
30
+ watermark?: IWatermarkConfig;
29
31
  }
30
32
  type IPlaybackPlayType = "ws-bvrtc" | "web" | "auto";
31
33
  interface IPlaybackInstance extends IComponentInstance {
@@ -4,6 +4,7 @@ import { IPuOption } from "./types";
4
4
  import { IControlPluginMap } from "../plugins/controller";
5
5
  import { MikeButton } from "./subComponent/mikeButton";
6
6
  import { CreatePlayerState } from "./subComponent/playState";
7
+ import { IWatermarkConfig } from "../plugins/watermark";
7
8
  type Container = HTMLElement | Element | Node | null;
8
9
  type helperFunc = {
9
10
  getDefaultProps: () => Partial<IPuPlayerProps>;
@@ -26,6 +27,7 @@ export interface IPuPlayerProps extends Props {
26
27
  videoFit?: keyof IVideoFits;
27
28
  apiPrefix?: string;
28
29
  testUrl?: string;
30
+ watermark?: IWatermarkConfig;
29
31
  fullScreenOnDblclick?: boolean;
30
32
  enableController?: boolean;
31
33
  disabledControls?: (keyof IControlPluginMap)[];
@@ -10,3 +10,4 @@ declare const clearAllDialog: (token: string) => Promise<void>;
10
10
  import "./styles/main.scss";
11
11
  import { globalConfigHandler } from "./components/global.config";
12
12
  export { globalConfigHandler, PlayBack, PuPlayer, Intercom, Conference, IPuPlayerProps, IPuPlayerInstance, IIntercomProps, IIntercomInstance, IConferenceProps, IConferenceInstance, IPuOption, IConfOption, RemoteSdpFetcher, clearAllDialog, CreateCallEndPoint, callEndPointUtils };
13
+ export type { IWatermarkConfig } from "./plugins/watermark";
@@ -12,6 +12,7 @@ import PtzPlugin from "../ptz";
12
12
  import { CreateIntercomUtils, MikeButton } from "../../components/subComponent/mikeButton";
13
13
  import { IPuOption } from "../../main";
14
14
  import { IRecorderConfig } from "src/utils/webmContainerUtils";
15
+ import { IWatermarkConfig } from "../watermark";
15
16
  export declare enum PLAYER_MODES {
16
17
  DIRECT = "direct",
17
18
  PLUGIN = "plugin",
@@ -52,6 +53,7 @@ export interface IPlayerPluginOptions {
52
53
  direct: string;
53
54
  puOptions: IPuOption;
54
55
  recorderConfig?: IRecorderConfig;
56
+ watermark?: IWatermarkConfig;
55
57
  }
56
58
  declare class PlayerPlugin extends Plugin<HTMLDivElement, IPlayerPluginEventMap> {
57
59
  private _mode;
@@ -63,6 +65,7 @@ declare class PlayerPlugin extends Plugin<HTMLDivElement, IPlayerPluginEventMap>
63
65
  private _spinner;
64
66
  private _toast;
65
67
  private _mask;
68
+ private _watermark;
66
69
  private _panel?;
67
70
  private _infoModal;
68
71
  private _recordState;
@@ -0,0 +1,28 @@
1
+ import { RenderTarget } from "../core/types";
2
+ import { Plugin } from "./types";
3
+ export interface IWatermarkConfig {
4
+ enable?: boolean;
5
+ text?: string | string[];
6
+ opacity?: number;
7
+ fontSize?: number;
8
+ fontWeight?: number | string;
9
+ color?: string;
10
+ strokeColor?: string;
11
+ strokeWidth?: number;
12
+ rotate?: number;
13
+ gapX?: number;
14
+ gapY?: number;
15
+ maxColumns?: number;
16
+ maxRows?: number;
17
+ zIndex?: number;
18
+ }
19
+ export declare const mergeWatermarkConfig: (...configs: Array<IWatermarkConfig | undefined>) => IWatermarkConfig;
20
+ declare class WatermarkPlugin extends Plugin<HTMLDivElement> {
21
+ private _config;
22
+ private _resizeObserver?;
23
+ constructor(config?: IWatermarkConfig);
24
+ init(_container?: RenderTarget): RenderTarget;
25
+ protected beforeDestroy(): void;
26
+ render(): void;
27
+ }
28
+ export default WatermarkPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@besovideo/webrtc-player",
3
- "version": "0.10.26",
3
+ "version": "0.10.28",
4
4
  "description": "@besovideo/webrtc-player desc",
5
5
  "type": "module",
6
6
  "types": "./dist/types/main.d.ts",