@ezuikit/player-theme 3.1.6-beta.1 → 3.1.7-beta.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.
package/dist/index.umd.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.6-beta.1
3
- * Copyright (c) 2026-09-16 19:24:27 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.7-beta.1
3
+ * Copyright (c) 2026-09-23 13:45:09 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  (function (global, factory) {
@@ -365,6 +365,16 @@
365
365
  var eventemitter3Exports = requireEventemitter3();
366
366
  var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
367
367
 
368
+ function _extends$C() {
369
+ _extends$C = Object.assign || function assign(target) {
370
+ for(var i = 1; i < arguments.length; i++){
371
+ var source = arguments[i];
372
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
373
+ }
374
+ return target;
375
+ };
376
+ return _extends$C.apply(this, arguments);
377
+ }
368
378
  /**
369
379
  * 播放器的类名前缀
370
380
  */ var PREFIX_CLASS$1 = 'ezplayer';
@@ -444,6 +454,54 @@
444
454
  'date',
445
455
  'segmentProgress'
446
456
  ];
457
+ /**
458
+ * 全部播放类型:直播 + 三种回放
459
+ *
460
+ * 控件用静态属性 `supportedPlayTypes` 声明支持范围,默认取本数组(即全支持)。
461
+ * 与 {@link REC_GROUP} 的区别:REC_GROUP 是「回放类型切换控件的 iconId 分组」,
462
+ * 这里是「播放地址实际解析出的播放类型」,两者取值恰好在回放侧重合。
463
+ */ var PLAY_TYPES = [
464
+ 'live',
465
+ 'rec',
466
+ 'cloudRec',
467
+ 'cloudRecord'
468
+ ];
469
+ /**
470
+ * 控件初始化完成事件名
471
+ *
472
+ * 键与 `Controls`(`src/Controls/index.ts`)的键一一对应,值为 `Control.<键>ControlInit`,
473
+ * 在控件实例创建成功后由 `_renderTheme` 派发一次,无载荷。
474
+ *
475
+ * 这些成员会被展开进 {@link EVENTS}.control,因此既可以 `EVENTS.control.playControlInit`
476
+ * 这样按名取用,也可以在只拿到 `iconId` 的场合用 `CONTROL_INIT_EVENTS[iconId]` 查表。
477
+ *
478
+ * @remarks `changeTheme` 会先卸载旧控件并重置 `theme.controls`,因此切换主题时这些事件会再次派发;
479
+ * 同一次渲染内则由 `!theme.controls.xxxControl` 守卫保证只派发一次。
480
+ */ var CONTROL_INIT_EVENTS = {
481
+ /** 播放/暂停控件初始化完成 */ playControlInit: 'Control.playControlInit',
482
+ /** 音量控件初始化完成 */ volumeControlInit: 'Control.volumeControlInit',
483
+ /** 设备信息控件初始化完成 */ deviceControlInit: 'Control.deviceControlInit',
484
+ /** 截图控件初始化完成 */ capturePictureControlInit: 'Control.capturePictureControlInit',
485
+ /** 云台控件初始化完成 */ ptzControlInit: 'Control.ptzControlInit',
486
+ /** 录制控件初始化完成 */ recordControlInit: 'Control.recordControlInit',
487
+ /** 对讲控件初始化完成 */ talkControlInit: 'Control.talkControlInit',
488
+ /** 语音广播控件初始化完成 */ broadcastControlInit: 'Control.broadcastControlInit',
489
+ /** AI 对话控件初始化完成 */ aiChatControlInit: 'Control.aiChatControlInit',
490
+ /** 直播按钮控件初始化完成 */ liveControlInit: 'Control.liveControlInit',
491
+ /** 回放下拉控件初始化完成 */ recDropdownControlInit: 'Control.recDropdownControlInit',
492
+ /** 录像列表控件初始化完成 */ recListControlInit: 'Control.recListControlInit',
493
+ /** 告警消息控件初始化完成 */ alarmMessageControlInit: 'Control.alarmMessageControlInit',
494
+ /** 电子放大控件初始化完成 */ zoomControlInit: 'Control.zoomControlInit',
495
+ /** 清晰度控件初始化完成 */ definitionControlInit: 'Control.definitionControlInit',
496
+ /** web 全屏控件初始化完成 */ fullscreenControlInit: 'Control.fullscreenControlInit',
497
+ /** 全局全屏控件初始化完成 */ globalFullscreenControlInit: 'Control.globalFullscreenControlInit',
498
+ /** 回放类型控件初始化完成 */ recControlInit: 'Control.recControlInit',
499
+ /** 倍速控件初始化完成 */ speedControlInit: 'Control.speedControlInit',
500
+ /** 日历控件初始化完成 */ dateControlInit: 'Control.dateControlInit',
501
+ /** 时间选择控件初始化完成 */ timeControlInit: 'Control.timeControlInit',
502
+ /** 时间轴控件初始化完成 */ timeLineControlInit: 'Control.timeLineControlInit',
503
+ /** 回放片段进度条控件初始化完成 */ segmentProgressControlInit: 'Control.segmentProgressControlInit'
504
+ };
447
505
  /**
448
506
  *
449
507
  * 事件名
@@ -510,7 +568,7 @@
510
568
  /** 播放区间播放结束(SDK 层 playbackRange 特性) */ playbackEnd: 'playbackEnd',
511
569
  /**
512
570
  * 控件相关
513
- */ control: {
571
+ */ control: _extends$C({}, CONTROL_INIT_EVENTS, {
514
572
  /** 点击播放播放/暂停按钮 */ play: 'Control.play',
515
573
  /** 播放控件销毁 */ playDestroy: 'Control.playDestroy',
516
574
  /** 截图 */ capturePicture: 'Control.capturePicture',
@@ -566,12 +624,13 @@
566
624
  /** 日期改变 */ dateMonthChange: 'Control.dateMonthChange',
567
625
  /** 日期面板展示的月份变化 */ datePanelMonthChange: 'Control.datePanelMonthChange',
568
626
  /** 日期面板展示的年份变化 */ datePanelYearChange: 'Control.datePanelYearChange',
569
- /** 日期销毁 */ dateDestroy: 'Control.datePanelDestroy',
627
+ /** 日期销毁 */ dateDestroy: 'Control.dateDestroy',
570
628
  /** 时间面板展示隐藏变换 */ timePanelOpenChange: 'Control.timePanelOpenChange',
571
629
  /** 时间改变 */ timeChange: 'Control.timeChange',
572
630
  /** 时间轴拖动结束 */ timeLineChange: 'Control.timeLineChange',
573
631
  /** 时间轴图片列表面板 */ timeLinePanelOpenChange: 'Control.timeLinePanelOpenChange',
574
632
  /** 时间轴控件销毁 */ timeLineDestroy: 'Control.timeLineDestroy',
633
+ /** 控件不支持当前播放类型(仅提示,控件仍会渲染) */ unsupportedPlayType: 'Control.unsupportedPlayType',
575
634
  /** 主题控件挂载前 切换新的主题也会触发,如果想首次获取需要在 onInitializing 回调中进行监听 */ beforeMountControls: 'Control.beforeMountControls',
576
635
  /** 主题控件挂载完成, 切换新的主题也会触发,如果想首次获取需要在 onInitializing 回调中进行监听 */ mountedControls: 'Control.mountedControls',
577
636
  /** 主题控件卸载前, 已有控件卸载时才可触发 */ beforeUnmountControls: 'Control.beforeUnmountControls',
@@ -581,7 +640,7 @@
581
640
  /** 消息控件销毁 */ messageDestroy: 'Control.messageDestroy',
582
641
  /** 播放器内容区域销毁 */ contentDestroy: 'Control.contentDestroy',
583
642
  /** 播放器内容区域重新渲染 */ contentRerender: 'Control.contentRerender'
584
- },
643
+ }),
585
644
  /**
586
645
  * 主题控件相关
587
646
  */ theme: {
@@ -631,17 +690,17 @@
631
690
  };
632
691
  return _set_prototype_of$D(o, p);
633
692
  }
634
- /**
635
- * 控件基类
636
- * @category Control
637
- * @example
638
- * ```ts
639
- * // 创建控件
640
- * class MyControl extends Control {}
641
- *
642
- * // 使用控件
643
- * const myControl = new MyControl({})
644
- * ```
693
+ /**
694
+ * 控件基类
695
+ * @category Control
696
+ * @example
697
+ * ```ts
698
+ * // 创建控件
699
+ * class MyControl extends Control {}
700
+ *
701
+ * // 使用控件
702
+ * const myControl = new MyControl({})
703
+ * ```
645
704
  */ var Control = /*#__PURE__*/ function(EventEmitter) {
646
705
  _inherits$z(Control, EventEmitter);
647
706
  function Control(options) {
@@ -683,22 +742,22 @@
683
742
  return _this;
684
743
  }
685
744
  var _proto = Control.prototype;
686
- /**
687
- * 重置整个控件
745
+ /**
746
+ * 重置整个控件
688
747
  */ _proto.reset = function reset(hide) {
689
748
  if (this._camelCaseName) {
690
749
  this.emit("Control." + this._camelCaseName + "Reset", hide);
691
750
  }
692
751
  };
693
- /**
694
- * 重置控件挂载节点
695
- * @param popupContainer 重新挂载的节点
696
- * @param append 添加的方式, 默认 append
697
- * @param element 当 append = before 时 需要 element, 插入 element 前
698
- *
699
- * | prepend | append |
700
- * |:-------------:|:---------------:|
701
- * | 插入第一个位置 | 追加在末尾 |
752
+ /**
753
+ * 重置控件挂载节点
754
+ * @param popupContainer 重新挂载的节点
755
+ * @param append 添加的方式, 默认 append
756
+ * @param element 当 append = before 时 需要 element, 插入 element 前
757
+ *
758
+ * | prepend | append |
759
+ * |:-------------:|:---------------:|
760
+ * | 插入第一个位置 | 追加在末尾 |
702
761
  */ _proto.resetPopupContainer = function resetPopupContainer(popupContainer, append, element) {
703
762
  if (popupContainer !== this.$popupContainer) {
704
763
  if (this.$popupContainer.contains(this.$container)) {
@@ -720,16 +779,16 @@
720
779
  }
721
780
  }
722
781
  };
723
- /**
724
- * 隐藏整个控件
782
+ /**
783
+ * 隐藏整个控件
725
784
  */ _proto.hide = function hide() {
726
785
  if (this.$container) {
727
786
  this.$container.style.display = 'none';
728
787
  this.$container.classList.add("" + PREFIX_CLASS$1 + "-hide");
729
788
  }
730
789
  };
731
- /**
732
- * 销毁控件
790
+ /**
791
+ * 销毁控件
733
792
  */ _proto.destroy = function destroy() {
734
793
  var _this___options, _this_$container_remove, _this_$container;
735
794
  if (this._camelCaseName) {
@@ -766,8 +825,8 @@
766
825
  (_this_$container1 = this.$container) == null ? void 0 : _this_$container1.classList.remove("" + PREFIX_CLASS$1 + "-active");
767
826
  }
768
827
  };
769
- /**
770
- * 当点击 Control 时 触发子类的 _onControlClick
828
+ /**
829
+ * 当点击 Control 时 触发子类的 _onControlClick
771
830
  */ _proto._onClick = function _onClick() {
772
831
  var _this = this;
773
832
  // 使用具名 handler 便于在 destroy 时精确移除,避免匿名监听残留
@@ -785,19 +844,29 @@
785
844
  e.stopPropagation();
786
845
  e.preventDefault();
787
846
  };
788
- /**
789
- * 点击 Control 控件触发
790
- * @param {Event} e
791
- * @returns {void}
847
+ /**
848
+ * 点击 Control 控件触发
849
+ * @param {Event} e
850
+ * @returns {void}
792
851
  */ _proto._onControlClick = function _onControlClick(e) {
793
852
  // 这是一个空函数, 子类可以实现重新改方法
794
853
  this.__options.onClick == null ? void 0 : this.__options.onClick.call(this.__options, e);
795
854
  };
855
+ /**
856
+ * 判断某个播放类型是否被本控件支持
857
+ *
858
+ * @param playType 播放类型;传空串(无法从地址判定)时一律返回 `true`,避免误报
859
+ * @returns 是否支持
860
+ * @since 3.1.7
861
+ */ Control.supportsPlayType = function supportsPlayType(playType) {
862
+ if (!playType) return true;
863
+ return this.supportedPlayTypes.includes(playType);
864
+ };
796
865
  _create_class$k(Control, [
797
866
  {
798
867
  key: "active",
799
- get: /**
800
- * 是否激活
868
+ get: /**
869
+ * 是否激活
801
870
  */ function get() {
802
871
  return this._active;
803
872
  },
@@ -812,8 +881,8 @@
812
881
  },
813
882
  {
814
883
  key: "disabled",
815
- get: /**
816
- * 是否禁用
884
+ get: /**
885
+ * 是否禁用
817
886
  */ function get() {
818
887
  return this._disabled;
819
888
  },
@@ -825,6 +894,24 @@
825
894
  ]);
826
895
  return Control;
827
896
  }(EventEmitter);
897
+ /**
898
+ * 该控件支持的播放类型,默认全支持
899
+ *
900
+ * 子类用 `static supportedPlayTypes = [...]` 覆盖来收窄范围。声明是**静态**的,
901
+ * 因为渲染层需要在不实例化控件的前提下就能读到(`Controls[iconId].supportedPlayTypes`)。
902
+ *
903
+ * 渲染时会拿 `theme.playType` 与此比对,不匹配只发警告与 `Control.unsupportedPlayType`
904
+ * 事件,**不阻止渲染**,控件照常创建、照常可交互,行为是否生效由 SDK 层与设备能力决定。
905
+ *
906
+ * @since 3.1.7
907
+ * @example
908
+ * ```ts
909
+ * class MyControl extends Control {
910
+ * // 只在云存储回放下有意义
911
+ * static supportedPlayTypes: ThemePlayType[] = ['cloudRec'];
912
+ * }
913
+ * ```
914
+ */ Control.supportedPlayTypes = [].concat(PLAY_TYPES);
828
915
 
829
916
  function _extends$B() {
830
917
  _extends$B = Object.assign || function assign(target) {
@@ -857,9 +944,9 @@
857
944
  return _set_prototype_of$C(o, p);
858
945
  }
859
946
  var LOADING_DEFAULT_OPTIONS = {};
860
- /**
861
- * 加载动画控件
862
- * @category Control
947
+ /**
948
+ * 加载动画控件
949
+ * @category Control
863
950
  */ var Loading = /*#__PURE__*/ function(Control) {
864
951
  _inherits$y(Loading, Control);
865
952
  function Loading(options) {
@@ -884,9 +971,9 @@
884
971
  this.$container.innerHTML = '\n <span class="' + PREFIX_CLASS$1 + "-loading-dot " + PREFIX_CLASS$1 + '-loading-dot-load">\n <i class="' + PREFIX_CLASS$1 + '-loading-dot-item"></i>\n <i class="' + PREFIX_CLASS$1 + '-loading-dot-item"></i>\n <i class="' + PREFIX_CLASS$1 + '-loading-dot-item"></i>\n <i class="' + PREFIX_CLASS$1 + '-loading-dot-item"></i>\n </span>\n <div class="' + PREFIX_CLASS$1 + '-loading-text">' + (((_this_locale = this.locale) == null ? void 0 : _this_locale.LOADING) || 'loading...') + "</div>\n ";
885
972
  }
886
973
  };
887
- /**
888
- * 动画展示
889
- * @param html 自定义动画内容, 如果不存在则使用默认动画
974
+ /**
975
+ * 动画展示
976
+ * @param html 自定义动画内容, 如果不存在则使用默认动画
890
977
  */ _proto.show = function show(html) {
891
978
  if (html) this.$container.innerHTML = html;
892
979
  // 初始化, 出流再等待中(回放出流结束不包括)
@@ -894,8 +981,8 @@
894
981
  this.$container.classList.remove("" + PREFIX_CLASS$1 + "-hide");
895
982
  this.$popupContainer.classList.add("" + PREFIX_CLASS$1 + "-has-loading");
896
983
  };
897
- /**
898
- * 隐藏动画
984
+ /**
985
+ * 隐藏动画
899
986
  */ _proto.hide = function hide() {
900
987
  Control.prototype.hide.call(this);
901
988
  this.$popupContainer.classList.remove("" + PREFIX_CLASS$1 + "-has-loading");
@@ -939,9 +1026,9 @@
939
1026
  var POSTER_OPTIONS = {
940
1027
  poster: DEFAULT_POSTER
941
1028
  };
942
- /**
943
- * 封面控件
944
- * @category Control
1029
+ /**
1030
+ * 封面控件
1031
+ * @category Control
945
1032
  */ var Poster = /*#__PURE__*/ function(Control) {
946
1033
  _inherits$x(Poster, Control);
947
1034
  function Poster(options) {
@@ -961,18 +1048,18 @@
961
1048
  return _this;
962
1049
  }
963
1050
  var _proto = Poster.prototype;
964
- /**
965
- * 封面图片加载失败
966
- * @param error
1051
+ /**
1052
+ * 封面图片加载失败
1053
+ * @param error
967
1054
  */ _proto._imgLoadErrorEvent = function _imgLoadErrorEvent(error) {
968
1055
  var _error_target;
969
1056
  // 封面加载失败, 一般只有自定义封面会出现这种情况
970
1057
  // 这里不做img src重置处理 防止无限循环
971
1058
  this._options.onLoadImgError == null ? void 0 : this._options.onLoadImgError.call(this._options, ((_error_target = error.target) == null ? void 0 : _error_target.getAttribute('src')) || '');
972
1059
  };
973
- /**
974
- * 设置封面 这里不对 poster 进行缓存,如果有值优先使用,如果没有值优先使用 初始化传入的值
975
- * @param {string} poster 封面地址或 base64 数据
1060
+ /**
1061
+ * 设置封面 这里不对 poster 进行缓存,如果有值优先使用,如果没有值优先使用 初始化传入的值
1062
+ * @param {string} poster 封面地址或 base64 数据
976
1063
  */ _proto.setPoster = function setPoster(poster) {
977
1064
  var // eslint-disable-next-line @typescript-eslint/unbound-method
978
1065
  // prettier-ignore
@@ -985,24 +1072,24 @@
985
1072
  this.$container.innerHTML = '<img class="' + PREFIX_CLASS$1 + '-poster-img" src="' + poster + '" />';
986
1073
  (_this_$container_querySelector = this.$container.querySelector("." + PREFIX_CLASS$1 + "-poster-img")) == null ? void 0 : _this_$container_querySelector.addEventListener("error", this._imgLoadErrorEvent);
987
1074
  };
988
- /**
989
- * 展示封面 这里不对 poster 进行缓存, 如果有值优先使用, 如果没有值优先使用 初始化传入的值
1075
+ /**
1076
+ * 展示封面 这里不对 poster 进行缓存, 如果有值优先使用, 如果没有值优先使用 初始化传入的值
990
1077
  */ _proto.show = function show() {
991
1078
  if (this.$container) {
992
1079
  this.$container.style.display = 'flex';
993
1080
  this.$container.classList.remove("" + PREFIX_CLASS$1 + "-hide");
994
1081
  }
995
1082
  };
996
- /**
997
- * 隐藏封面
1083
+ /**
1084
+ * 隐藏封面
998
1085
  */ _proto.hide = function hide() {
999
1086
  var // eslint-disable-next-line @typescript-eslint/unbound-method
1000
1087
  _this_$container_querySelector, _this_$container;
1001
1088
  Control.prototype.hide.call(this);
1002
1089
  (_this_$container = this.$container) == null ? void 0 : (_this_$container_querySelector = _this_$container.querySelector("." + PREFIX_CLASS$1 + "-poster-img")) == null ? void 0 : _this_$container_querySelector.removeEventListener('error', this._imgLoadErrorEvent);
1003
1090
  };
1004
- /**
1005
- * 销毁
1091
+ /**
1092
+ * 销毁
1006
1093
  */ _proto.destroy = function destroy() {
1007
1094
  this.hide();
1008
1095
  Control.prototype.destroy.call(this);
@@ -1061,15 +1148,15 @@
1061
1148
  list: '<svg stroke="currentColor" fill="none" width="1em" height="1em" viewBox="0 0 24 24" focusable="false" aria-hidden="true" data-icon="list">\n <path d="M10.9995 5H21.0005" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path d="M10.9995 12H21.0005" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path d="M10.9995 19H21.0005" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M6.99951 5C6.99951 3.896 6.10351 3 4.99951 3C3.89551 3 2.99951 3.896 2.99951 5C2.99951 6.105 3.89551 7 4.99951 7C6.10351 7 6.99951 6.105 6.99951 5V5Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M6.99951 12C6.99951 10.896 6.10351 10 4.99951 10C3.89551 10 2.99951 10.896 2.99951 12C2.99951 13.105 3.89551 14 4.99951 14C6.10351 14 6.99951 13.105 6.99951 12V12Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M6.99951 12C6.99951 10.896 6.10351 10 4.99951 10C3.89551 10 2.99951 10.896 2.99951 12C2.99951 13.105 3.89551 14 4.99951 14C6.10351 14 6.99951 13.105 6.99951 12V12Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n <path fill-rule="evenodd" clip-rule="evenodd" d="M6.99951 19C6.99951 17.896 6.10351 17 4.99951 17C3.89551 17 2.99951 17.896 2.99951 19C2.99951 20.105 3.89551 21 4.99951 21C6.10351 21 6.99951 20.105 6.99951 19V19Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>'
1062
1149
  };
1063
1150
 
1064
- /**
1065
- * 创建 icon 组件
1066
- * @param svg - svg 字符串
1067
- * @param type - icon 类型
1068
- * @returns icon 组件
1069
- * @example
1070
- * ```ts
1071
- * createIcon('<svg>....</svg>', 'logo') // <span class="ezplayer-icon ezplayer-icon-logo"><svg>....</svg></span>
1072
- * ```
1151
+ /**
1152
+ * 创建 icon 组件
1153
+ * @param svg - svg 字符串
1154
+ * @param type - icon 类型
1155
+ * @returns icon 组件
1156
+ * @example
1157
+ * ```ts
1158
+ * createIcon('<svg>....</svg>', 'logo') // <span class="ezplayer-icon ezplayer-icon-logo"><svg>....</svg></span>
1159
+ * ```
1073
1160
  */ function createIcon(svg, type, attr) {
1074
1161
  if (attr === void 0) attr = {};
1075
1162
  var attrStr = '';
@@ -1270,9 +1357,9 @@
1270
1357
  return _set_prototype_of$A(o, p);
1271
1358
  }
1272
1359
  var MESSAGE_DEFAULT_OPTIONS = {};
1273
- /**
1274
- * 消息控件
1275
- * @category Control
1360
+ /**
1361
+ * 消息控件
1362
+ * @category Control
1276
1363
  */ var Message = /*#__PURE__*/ function(Control) {
1277
1364
  _inherits$w(Message, Control);
1278
1365
  function Message(options) {
@@ -1287,34 +1374,34 @@
1287
1374
  return _this;
1288
1375
  }
1289
1376
  var _proto = Message.prototype;
1290
- /**
1291
- * info 普通消息, 内容默认字体白色
1292
- * @param {string} msg 消息内容
1293
- * @param {number} duration 认自动关闭延时,单位秒, 默认 2s后 关闭, 需手动 调用 hide()
1377
+ /**
1378
+ * info 普通消息, 内容默认字体白色
1379
+ * @param {string} msg 消息内容
1380
+ * @param {number} duration 认自动关闭延时,单位秒, 默认 2s后 关闭, 需手动 调用 hide()
1294
1381
  */ _proto.info = function info(msg, duration) {
1295
1382
  if (duration === void 0) duration = 2;
1296
1383
  this._toast(msg, 'info', duration);
1297
1384
  };
1298
- /**
1299
- * warn 警告消息, 内容默认字体黄色
1300
- * @param {string} msg 消息内容
1301
- * @param {number} duration 认自动关闭延时,单位秒, 默认 2s后 关闭, 需手动 调用 hide()
1385
+ /**
1386
+ * warn 警告消息, 内容默认字体黄色
1387
+ * @param {string} msg 消息内容
1388
+ * @param {number} duration 认自动关闭延时,单位秒, 默认 2s后 关闭, 需手动 调用 hide()
1302
1389
  */ _proto.warn = function warn(msg, duration) {
1303
1390
  if (duration === void 0) duration = 2;
1304
1391
  this._toast(msg, 'warn', duration);
1305
1392
  };
1306
- /**
1307
- * toast 错误消息(渲染在 rootContainer 上的浮层)
1308
- * @param {string} msg 消息内容
1309
- * @param {number} duration 自动关闭延时,单位秒, 默认 2s 后关闭
1393
+ /**
1394
+ * toast 错误消息(渲染在 rootContainer 上的浮层)
1395
+ * @param {string} msg 消息内容
1396
+ * @param {number} duration 自动关闭延时,单位秒, 默认 2s 后关闭
1310
1397
  */ _proto.toastError = function toastError(msg, duration) {
1311
1398
  if (duration === void 0) duration = 2;
1312
1399
  this._toast(msg, 'error', duration);
1313
1400
  };
1314
- /**
1315
- * error 错误消息, 内容默认字体红色
1316
- * @param {string} msg 消息内容
1317
- * @param {number=} duration 认自动关闭延时,单位秒, 默认 0 不关闭, 需手动 调用 hide()
1401
+ /**
1402
+ * error 错误消息, 内容默认字体红色
1403
+ * @param {string} msg 消息内容
1404
+ * @param {number=} duration 认自动关闭延时,单位秒, 默认 0 不关闭, 需手动 调用 hide()
1318
1405
  */ _proto.error = function error(msg, duration) {
1319
1406
  if (duration === void 0) duration = 0;
1320
1407
  this._show(this._getIcon('error') + '<div class="' + PREFIX_CLASS$1 + '-message-msg">' + (msg || '') + "</div>", duration, 'error');
@@ -1343,11 +1430,11 @@
1343
1430
  }
1344
1431
  }
1345
1432
  };
1346
- /**
1347
- * 展示消息,如果同时调用多次只展示最后一次的消息
1348
- * @param {string} msg 消息内容, 支持 html dom 字符串
1349
- * @param {number} duration 认自动关闭延时,单位秒, 默认 0 不关闭 需手动 调用 hide()
1350
- * @param {MessageType} type 消息类型
1433
+ /**
1434
+ * 展示消息,如果同时调用多次只展示最后一次的消息
1435
+ * @param {string} msg 消息内容, 支持 html dom 字符串
1436
+ * @param {number} duration 认自动关闭延时,单位秒, 默认 0 不关闭 需手动 调用 hide()
1437
+ * @param {MessageType} type 消息类型
1351
1438
  */ _proto._show = function _show(msg, duration, type) {
1352
1439
  var _this = this;
1353
1440
  if (duration === void 0) duration = 0;
@@ -1375,8 +1462,8 @@
1375
1462
  }, duration * 1000);
1376
1463
  }
1377
1464
  };
1378
- /**
1379
- * 销毁
1465
+ /**
1466
+ * 销毁
1380
1467
  */ _proto.destroy = function destroy() {
1381
1468
  var _this__$toast;
1382
1469
  if (this._timer) {
@@ -1391,8 +1478,8 @@
1391
1478
  this.hide();
1392
1479
  Control.prototype.destroy.call(this);
1393
1480
  };
1394
- /**
1395
- * 隐藏消息, 并清空消息内容
1481
+ /**
1482
+ * 隐藏消息, 并清空消息内容
1396
1483
  */ _proto.hide = function hide() {
1397
1484
  var _this = this;
1398
1485
  // 每次隐藏都清空内 消息内容
@@ -1465,9 +1552,9 @@
1465
1552
  };
1466
1553
  return _set_prototype_of$z(o, p);
1467
1554
  }
1468
- /**
1469
- * 播放/暂停控件
1470
- * @category Control
1555
+ /**
1556
+ * 播放/暂停控件
1557
+ * @category Control
1471
1558
  */ var Play = /*#__PURE__*/ function(Control) {
1472
1559
  _inherits$v(Play, Control);
1473
1560
  function Play(options) {
@@ -1489,8 +1576,8 @@
1489
1576
  return _this;
1490
1577
  }
1491
1578
  var _proto = Play.prototype;
1492
- /**
1493
- * 点击 Control 会触发
1579
+ /**
1580
+ * 点击 Control 会触发
1494
1581
  */ _proto._onControlClick = function _onControlClick(e) {
1495
1582
  this._playing = !this._playing;
1496
1583
  this.emit(EVENTS$2.control.play, this._playing);
@@ -1513,8 +1600,8 @@
1513
1600
  _create_class$j(Play, [
1514
1601
  {
1515
1602
  key: "playing",
1516
- get: /**
1517
- * 播放状态
1603
+ get: /**
1604
+ * 播放状态
1518
1605
  */ function get() {
1519
1606
  return this._playing;
1520
1607
  }
@@ -2425,12 +2512,12 @@
2425
2512
 
2426
2513
  var distExports$3 = requireDist$3();
2427
2514
 
2428
- /**
2429
- * 节流函数
2430
- * @param {Function} func
2431
- * @param {number} wait
2432
- * @typeParam T - 函数类型
2433
- * @returns {Function}
2515
+ /**
2516
+ * 节流函数
2517
+ * @param {Function} func
2518
+ * @param {number} wait
2519
+ * @typeParam T - 函数类型
2520
+ * @returns {Function}
2434
2521
  */ // eslint-disable-next-line @typescript-eslint/ban-types
2435
2522
  function throttle(func, wait) {
2436
2523
  var timeout = null;
@@ -2486,28 +2573,28 @@
2486
2573
  if (n === "Map" || n === "Set") return Array.from(n);
2487
2574
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$3(o, minLen);
2488
2575
  }
2489
- /**
2490
- * 工具类
2491
- * @category Util
2576
+ /**
2577
+ * 工具类
2578
+ * @category Util
2492
2579
  */ var Utils = /*#__PURE__*/ function() {
2493
2580
  function Utils() {}
2494
2581
  // /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Opera Mini)/i.test(navigator?.userAgent) ||
2495
2582
  // (/Macintosh/i.test(navigator?.userAgent) && navigator?.maxTouchPoints > 1); // iPad 支持多点触控;
2496
- /**
2497
- * 监听手机旋转, 参考 {@link https://developer.mozilla.org/zh-CN/docs/Web/API/Screen/orientation}
2498
- * @param {OrientationChangeCallback} change 手机旋转回调
2499
- * @returns {[ScreenOrientation, CleanUpScreenOrientationFun]} [第一次的结果, 事件移除]
2500
- *
2501
- * @example
2502
- * ```ts
2503
- * const [orientation, cleanUp] = Utils.orientationEventListener((orientation) => {
2504
- * console.log("orientation", orientation)
2505
- * })
2506
- *
2507
- * console.log("orientation", orientation)
2508
- * // 清除监听
2509
- * cleanUp()
2510
- * ```
2583
+ /**
2584
+ * 监听手机旋转, 参考 {@link https://developer.mozilla.org/zh-CN/docs/Web/API/Screen/orientation}
2585
+ * @param {OrientationChangeCallback} change 手机旋转回调
2586
+ * @returns {[ScreenOrientation, CleanUpScreenOrientationFun]} [第一次的结果, 事件移除]
2587
+ *
2588
+ * @example
2589
+ * ```ts
2590
+ * const [orientation, cleanUp] = Utils.orientationEventListener((orientation) => {
2591
+ * console.log("orientation", orientation)
2592
+ * })
2593
+ *
2594
+ * console.log("orientation", orientation)
2595
+ * // 清除监听
2596
+ * cleanUp()
2597
+ * ```
2511
2598
  */ // prettier-ignore
2512
2599
  Utils.orientationEventListener = function orientationEventListener(change) {
2513
2600
  var _orientationTimer = null;
@@ -2597,18 +2684,18 @@
2597
2684
  }
2598
2685
  ];
2599
2686
  };
2600
- /**
2601
- * 监听节点尺寸变化, 参考 {@link https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver}
2602
- * @param {Element} node
2603
- * @param callback
2604
- * @returns {CleanUpResizeObserver}
2605
- * @example
2606
- * ```ts
2607
- * const [unobserve, disconnect] = Utils.resizeObserver(node, (entries, observer) => {});
2608
- *
2609
- * // 移除监听
2610
- * unobserve()
2611
- * ```
2687
+ /**
2688
+ * 监听节点尺寸变化, 参考 {@link https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver}
2689
+ * @param {Element} node
2690
+ * @param callback
2691
+ * @returns {CleanUpResizeObserver}
2692
+ * @example
2693
+ * ```ts
2694
+ * const [unobserve, disconnect] = Utils.resizeObserver(node, (entries, observer) => {});
2695
+ *
2696
+ * // 移除监听
2697
+ * unobserve()
2698
+ * ```
2612
2699
  */ // prettier-ignore
2613
2700
  Utils.resizeObserver = function resizeObserver(node, callback) {
2614
2701
  // prettier-ignore
@@ -2643,12 +2730,12 @@
2643
2730
  return Utils;
2644
2731
  }();
2645
2732
  // 不要使用 window, 如果在 worker 中会报错
2646
- /**
2647
- * 判断是否是移动端, (iPadOS 13+ 移除了 "iPad" 标识)
2648
- * @example
2649
- * ```ts
2650
- * Utils.isMobile // true | false
2651
- * ```
2733
+ /**
2734
+ * 判断是否是移动端, (iPadOS 13+ 移除了 "iPad" 标识)
2735
+ * @example
2736
+ * ```ts
2737
+ * Utils.isMobile // true | false
2738
+ * ```
2652
2739
  */ Utils.isMobile = distExports$3.isMobile();
2653
2740
 
2654
2741
  function _defineProperties$7(target, props) {
@@ -2682,23 +2769,23 @@
2682
2769
  return (percent * 100).toFixed(0);
2683
2770
  }
2684
2771
  };
2685
- /**
2686
- * 进度条
2687
- *
2688
- * @category Control
2689
- * @example
2690
- * ```ts
2691
- * const progress = new Progress({
2692
- * container: document.getElementById('progress-container'),
2693
- * step: 0.01,
2694
- * range: [0, 1],
2695
- * onChange: (value, range) => {
2696
- * console.log(`Progress changed: ${value}, Range: ${range}`);
2697
- * },
2698
- * defaultValue: 0.5,
2699
- * draggable: true,
2700
- * disabled: false,
2701
- * })
2772
+ /**
2773
+ * 进度条
2774
+ *
2775
+ * @category Control
2776
+ * @example
2777
+ * ```ts
2778
+ * const progress = new Progress({
2779
+ * container: document.getElementById('progress-container'),
2780
+ * step: 0.01,
2781
+ * range: [0, 1],
2782
+ * onChange: (value, range) => {
2783
+ * console.log(`Progress changed: ${value}, Range: ${range}`);
2784
+ * },
2785
+ * defaultValue: 0.5,
2786
+ * draggable: true,
2787
+ * disabled: false,
2788
+ * })
2702
2789
  */ var Progress = /*#__PURE__*/ function() {
2703
2790
  function Progress(options) {
2704
2791
  var _this_options_defaultValue;
@@ -2731,20 +2818,20 @@
2731
2818
  this.disabled = this.options.disabled;
2732
2819
  }
2733
2820
  var _proto = Progress.prototype;
2734
- /**
2735
- * 是否旋转了
2736
- * @param rotated
2821
+ /**
2822
+ * 是否旋转了
2823
+ * @param rotated
2737
2824
  */ _proto.isRotate = function isRotate(rotated) {
2738
2825
  this._isRotated = rotated;
2739
2826
  };
2740
- /**
2741
- * 销毁 Progress 实例,移除事件监听器
2742
- * @returns {void}
2743
- * @memberof Progress
2744
- * @example
2745
- * ```ts
2746
- * progress.destroy();
2747
- * ```
2827
+ /**
2828
+ * 销毁 Progress 实例,移除事件监听器
2829
+ * @returns {void}
2830
+ * @memberof Progress
2831
+ * @example
2832
+ * ```ts
2833
+ * progress.destroy();
2834
+ * ```
2748
2835
  */ _proto.destroy = function destroy() {
2749
2836
  var _this__delegateSliderMouseDown_destroy, _this__delegateSliderMouseDown, _this__delegateSliderHandleMouseDown_destroy, _this__delegateSliderHandleMouseDown, _this__delegateProgressMouseDown_destroy, _this__delegateProgressMouseDown, _this__delegatePlusClick_destroy, _this__delegatePlusClick, _this__delegateMinusClick_destroy, _this__delegateMinusClick;
2750
2837
  (_this__delegateSliderMouseDown = this._delegateSliderMouseDown) == null ? void 0 : (_this__delegateSliderMouseDown_destroy = _this__delegateSliderMouseDown.destroy) == null ? void 0 : _this__delegateSliderMouseDown_destroy.call(_this__delegateSliderMouseDown);
@@ -2939,14 +3026,14 @@
2939
3026
  },
2940
3027
  {
2941
3028
  key: "value",
2942
- get: /**
2943
- * 获取进度条值
2944
- * @returns {number} 当前进度条值
2945
- * @example
2946
- * ```ts
2947
- * const value = progress.value; // 获取当前进度条值
2948
- * console.log(value); // 输出值
2949
- * ```
3029
+ get: /**
3030
+ * 获取进度条值
3031
+ * @returns {number} 当前进度条值
3032
+ * @example
3033
+ * ```ts
3034
+ * const value = progress.value; // 获取当前进度条值
3035
+ * console.log(value); // 输出值
3036
+ * ```
2950
3037
  */ function get() {
2951
3038
  return this._value; //
2952
3039
  },
@@ -2956,14 +3043,14 @@
2956
3043
  },
2957
3044
  {
2958
3045
  key: "percent",
2959
- get: /**
2960
- * 获取进度百分比
2961
- * @returns {number} 当前进度条百分比
2962
- * @example
2963
- * ```ts
2964
- * const percent = progress.percent; // 获取当前进度条百分比
2965
- * console.log(percent); // 输出百分比
2966
- * ```
3046
+ get: /**
3047
+ * 获取进度百分比
3048
+ * @returns {number} 当前进度条百分比
3049
+ * @example
3050
+ * ```ts
3051
+ * const percent = progress.percent; // 获取当前进度条百分比
3052
+ * console.log(percent); // 输出百分比
3053
+ * ```
2967
3054
  */ function get() {
2968
3055
  return this._percent;
2969
3056
  },
@@ -3026,9 +3113,9 @@
3026
3113
  onOpenChange: function onOpenChange() {},
3027
3114
  onChange: function onChange() {}
3028
3115
  };
3029
- /**
3030
- * 音量调节控件
3031
- * @category Control
3116
+ /**
3117
+ * 音量调节控件
3118
+ * @category Control
3032
3119
  */ var Volume = /*#__PURE__*/ function(Control) {
3033
3120
  _inherits$u(Volume, Control);
3034
3121
  function Volume(options) {
@@ -3102,8 +3189,8 @@
3102
3189
  return _this;
3103
3190
  }
3104
3191
  var _proto = Volume.prototype;
3105
- /**
3106
- * 销毁
3192
+ /**
3193
+ * 销毁
3107
3194
  */ _proto.destroy = function destroy() {
3108
3195
  var _this__progress_destroy, _this__progress, _this_picker;
3109
3196
  (_this__progress = this._progress) == null ? void 0 : (_this__progress_destroy = _this__progress.destroy) == null ? void 0 : _this__progress_destroy.call(_this__progress);
@@ -3161,8 +3248,8 @@
3161
3248
  title: (_this_locale = this.locale) == null ? void 0 : _this_locale.BTN_VOLUME
3162
3249
  });
3163
3250
  };
3164
- /**
3165
- * 点击 Control 会触发
3251
+ /**
3252
+ * 点击 Control 会触发
3166
3253
  */ _proto._onControlClick = function _onControlClick() {
3167
3254
  // this._options.onClick?.(e);
3168
3255
  };
@@ -3179,8 +3266,8 @@
3179
3266
  _create_class$h(Volume, [
3180
3267
  {
3181
3268
  key: "muted",
3182
- get: /**
3183
- * 是否静音
3269
+ get: /**
3270
+ * 是否静音
3184
3271
  */ function get() {
3185
3272
  return this._muted;
3186
3273
  },
@@ -3204,8 +3291,8 @@
3204
3291
  },
3205
3292
  {
3206
3293
  key: "volume",
3207
- get: /**
3208
- * 当前音量值(真实值 即使静音)
3294
+ get: /**
3295
+ * 当前音量值(真实值 即使静音)
3209
3296
  */ function get() {
3210
3297
  return this._lastVolume;
3211
3298
  },
@@ -3228,8 +3315,8 @@
3228
3315
  },
3229
3316
  {
3230
3317
  key: "disabled",
3231
- get: /**
3232
- * 是否禁用
3318
+ get: /**
3319
+ * 是否禁用
3233
3320
  */ function get() {
3234
3321
  return this._disabled;
3235
3322
  },
@@ -3928,9 +4015,9 @@
3928
4015
  };
3929
4016
  return _set_prototype_of$x(o, p);
3930
4017
  }
3931
- /**
3932
- * 全屏控件
3933
- * @category Control
4018
+ /**
4019
+ * 全屏控件
4020
+ * @category Control
3934
4021
  */ var Fullscreen = /*#__PURE__*/ function(Control) {
3935
4022
  _inherits$t(Fullscreen, Control);
3936
4023
  function Fullscreen(options) {
@@ -3957,8 +4044,8 @@
3957
4044
  return _this;
3958
4045
  }
3959
4046
  var _proto = Fullscreen.prototype;
3960
- /**
3961
- * 销毁
4047
+ /**
4048
+ * 销毁
3962
4049
  */ _proto.destroy = function destroy() {
3963
4050
  var _this__fullscreenUtil;
3964
4051
  this.$container.innerHTML = '';
@@ -3986,8 +4073,8 @@
3986
4073
  this._render();
3987
4074
  this.options.onChange == null ? void 0 : this.options.onChange.call(this.options, info);
3988
4075
  };
3989
- /**
3990
- * 点击 Control 会触发
4076
+ /**
4077
+ * 点击 Control 会触发
3991
4078
  */ _proto._onControlClick = function _onControlClick() {
3992
4079
  if (this.isCurrentFullscreen) {
3993
4080
  var _this__fullscreenUtil;
@@ -4031,9 +4118,9 @@
4031
4118
  };
4032
4119
  return _set_prototype_of$w(o, p);
4033
4120
  }
4034
- /**
4035
- * 回放类型切换(本地回放(sdk 卡), 云存储回放, 云录制回放)控件
4036
- * @category Control
4121
+ /**
4122
+ * 回放类型切换(本地回放(sdk 卡), 云存储回放, 云录制回放)控件
4123
+ * @category Control
4037
4124
  */ var Rec = /*#__PURE__*/ function(Control) {
4038
4125
  _inherits$s(Rec, Control);
4039
4126
  function Rec(options) {
@@ -4052,8 +4139,8 @@
4052
4139
  return _this;
4053
4140
  }
4054
4141
  var _proto = Rec.prototype;
4055
- /**
4056
- * 销毁
4142
+ /**
4143
+ * 销毁
4057
4144
  */ _proto.destroy = function destroy() {
4058
4145
  var _this__delegation;
4059
4146
  this.$container.removeEventListener('dblclick', this._onDBlClick);
@@ -4061,9 +4148,9 @@
4061
4148
  this._delegation = null;
4062
4149
  Control.prototype.destroy.call(this);
4063
4150
  };
4064
- /**
4065
- * 添加回放类型图标
4066
- * @param {string} id 回放类型 'rec' | 'cloudRec' | 'cloudRecord'
4151
+ /**
4152
+ * 添加回放类型图标
4153
+ * @param {string} id 回放类型 'rec' | 'cloudRec' | 'cloudRecord'
4067
4154
  */ _proto.addRecType = function addRecType(id) {
4068
4155
  var spanIcon = '';
4069
4156
  switch(id){
@@ -4130,11 +4217,16 @@
4130
4217
  }
4131
4218
  });
4132
4219
  };
4133
- /**
4134
- * 点击 Control 会触发
4220
+ /**
4221
+ * 点击 Control 会触发
4135
4222
  */ _proto._onControlClick = function _onControlClick(e) {};
4136
4223
  return Rec;
4137
4224
  }(Control);
4225
+ /** 回放类型切换组,本身就是三种回放之间的切换入口,直播下无意义 */ Rec.supportedPlayTypes = [
4226
+ 'rec',
4227
+ 'cloudRec',
4228
+ 'cloudRecord'
4229
+ ];
4138
4230
 
4139
4231
  var dist$2 = {exports: {}};
4140
4232
 
@@ -4455,7 +4547,8 @@
4455
4547
  cancel: '取消',
4456
4548
  ok: '确定',
4457
4549
  close: '关闭',
4458
- BTN_REC_LIST_TITLE: '录像片段'
4550
+ BTN_REC_LIST_TITLE: '录像片段',
4551
+ UNKOWN_ISSUE: '未知问题 【{{scope}}】'
4459
4552
  };
4460
4553
 
4461
4554
  // 不要出现多层的的数据, 数据铺平
@@ -4739,7 +4832,8 @@
4739
4832
  cancel: 'Cancel',
4740
4833
  ok: 'Ok',
4741
4834
  close: 'Close',
4742
- BTN_REC_LIST_TITLE: 'Records'
4835
+ BTN_REC_LIST_TITLE: 'Records',
4836
+ UNKOWN_ISSUE: 'Unknown issue [{{scope}}]'
4743
4837
  };
4744
4838
 
4745
4839
  /**
@@ -4856,8 +4950,8 @@
4856
4950
  }
4857
4951
  };
4858
4952
 
4859
- /**
4860
- * flv 预览
4953
+ /**
4954
+ * flv 预览
4861
4955
  */ var hlsLiveTemplate = {
4862
4956
  autoFocus: 3,
4863
4957
  // poster:
@@ -4909,8 +5003,8 @@
4909
5003
  }
4910
5004
  };
4911
5005
 
4912
- /**
4913
- * flv 预览
5006
+ /**
5007
+ * flv 预览
4914
5008
  */ var hlsRecTemplate = {
4915
5009
  autoFocus: 3,
4916
5010
  // poster:
@@ -4968,8 +5062,8 @@
4968
5062
  }
4969
5063
  };
4970
5064
 
4971
- /**
4972
- * pc 预览
5065
+ /**
5066
+ * pc 预览
4973
5067
  */ var pcLive = {
4974
5068
  autoFocus: 3,
4975
5069
  header: {
@@ -5068,8 +5162,8 @@
5068
5162
  }
5069
5163
  };
5070
5164
 
5071
- /**
5072
- * pc 回放
5165
+ /**
5166
+ * pc 回放
5073
5167
  */ var pcRec = {
5074
5168
  header: {
5075
5169
  // color: DEFAULT_COLOR,
@@ -5180,8 +5274,8 @@
5180
5274
  }
5181
5275
  };
5182
5276
 
5183
- /**
5184
- * mobile 预览
5277
+ /**
5278
+ * mobile 预览
5185
5279
  */ var mobileLive = {
5186
5280
  header: {
5187
5281
  // color: DEFAULT_COLOR,
@@ -5269,8 +5363,8 @@
5269
5363
  }
5270
5364
  };
5271
5365
 
5272
- /**
5273
- * mobile 回放
5366
+ /**
5367
+ * mobile 回放
5274
5368
  */ var mobileRec = {
5275
5369
  header: {
5276
5370
  // color: DEFAULT_COLOR,
@@ -5364,8 +5458,8 @@
5364
5458
  }
5365
5459
  };
5366
5460
 
5367
- /**
5368
- * 安防版(预览/回放)
5461
+ /**
5462
+ * 安防版(预览/回放)
5369
5463
  */ var security = {
5370
5464
  header: {
5371
5465
  // color: DEFAULT_COLOR,
@@ -5441,8 +5535,8 @@
5441
5535
  }
5442
5536
  };
5443
5537
 
5444
- /**
5445
- * 语音版(预览)
5538
+ /**
5539
+ * 语音版(预览)
5446
5540
  */ var voice = {
5447
5541
  header: {
5448
5542
  // color: DEFAULT_COLOR,
@@ -5494,11 +5588,11 @@
5494
5588
  }
5495
5589
  };
5496
5590
 
5497
- /**
5498
- * standard 做特殊处理
5499
- *
5500
- * WARN: 除了 'deviceID', 'deviceName', 'rec', 'cloudRec', 'cloudRecord' 做特殊处理, 只能放置在顶部, 其它不做处理,如果配置渲染的有问题需要开发者自行修改
5501
- * FIXME: 暂时不去重, 让开发者自己去修改
5591
+ /**
5592
+ * standard 做特殊处理
5593
+ *
5594
+ * WARN: 除了 'deviceID', 'deviceName', 'rec', 'cloudRec', 'cloudRecord' 做特殊处理, 只能放置在顶部, 其它不做处理,如果配置渲染的有问题需要开发者自行修改
5595
+ * FIXME: 暂时不去重, 让开发者自己去修改
5502
5596
  */ var TEMPLATES = {
5503
5597
  pcLive: pcLive,
5504
5598
  pcRec: pcRec,
@@ -5528,9 +5622,9 @@
5528
5622
  };
5529
5623
  return _set_prototype_of$v(o, p);
5530
5624
  }
5531
- /**
5532
- * 截图控件
5533
- * @category Content
5625
+ /**
5626
+ * 截图控件
5627
+ * @category Content
5534
5628
  */ var Content = /*#__PURE__*/ function(EventEmitter) {
5535
5629
  _inherits$r(Content, EventEmitter);
5536
5630
  function Content(options) {
@@ -5560,11 +5654,11 @@
5560
5654
  return _this;
5561
5655
  }
5562
5656
  var _proto = Content.prototype;
5563
- /**
5564
- * 重新画面区域
5565
- * @param {number} originWidth 画面宽度
5566
- * @param {number} originHeight 画面高度
5567
- * @returns {void}
5657
+ /**
5658
+ * 重新画面区域
5659
+ * @param {number} originWidth 画面宽度
5660
+ * @param {number} originHeight 画面高度
5661
+ * @returns {void}
5568
5662
  */ _proto.rerender = function rerender(originWidth, originHeight) {
5569
5663
  if (originWidth === void 0) originWidth = 0;
5570
5664
  if (originHeight === void 0) originHeight = 0;
@@ -5677,9 +5771,9 @@
5677
5771
  };
5678
5772
  return _set_prototype_of$u(o, p);
5679
5773
  }
5680
- /**
5681
- * 更多控件
5682
- * @category Control
5774
+ /**
5775
+ * 更多控件
5776
+ * @category Control
5683
5777
  */ var More = /*#__PURE__*/ function(Control) {
5684
5778
  _inherits$q(More, Control);
5685
5779
  function More(options) {
@@ -5725,9 +5819,9 @@
5725
5819
  }
5726
5820
  // debug
5727
5821
  };
5728
- /**
5729
- * 添加
5730
- * @param control
5822
+ /**
5823
+ * 添加
5824
+ * @param control
5731
5825
  */ _proto.add = function add(key, part, control, props) {
5732
5826
  this.list.unshift({
5733
5827
  part: part,
@@ -5737,9 +5831,9 @@
5737
5831
  height: props.height
5738
5832
  });
5739
5833
  };
5740
- /**
5741
- * 移除
5742
- * @param control
5834
+ /**
5835
+ * 移除
5836
+ * @param control
5743
5837
  */ _proto.remove = function remove(control) {
5744
5838
  var index = this.list.findIndex(function(item) {
5745
5839
  return item.control === control;
@@ -5759,20 +5853,20 @@
5759
5853
  }
5760
5854
  Control.prototype.destroy.call(this);
5761
5855
  };
5762
- /**
5763
- * 点击 Control 会触发
5856
+ /**
5857
+ * 点击 Control 会触发
5764
5858
  */ _proto._onControlClick = function _onControlClick(e) {
5765
5859
  // this._options.onClick?.(e);
5766
5860
  };
5767
5861
  return More;
5768
5862
  }(Control);
5769
5863
 
5770
- /**
5771
- * 函数防抖
5772
- * @param {Function} func
5773
- * @param {number} wait
5774
- * @typeParam T - 函数类型
5775
- * @returns {Function}
5864
+ /**
5865
+ * 函数防抖
5866
+ * @param {Function} func
5867
+ * @param {number} wait
5868
+ * @typeParam T - 函数类型
5869
+ * @returns {Function}
5776
5870
  */ // eslint-disable-next-line @typescript-eslint/ban-types
5777
5871
  function debounce(func, wait) {
5778
5872
  var timeout;
@@ -6402,23 +6496,23 @@
6402
6496
  });
6403
6497
  }
6404
6498
 
6405
- /**
6406
- * 重新调整播放器窗口大小
6407
- *
6408
- * Adjust the player window size
6409
- * @param {number | string} width 宽度(number 类型默认px, 支持字符串大小 "100%" | "50vw")
6410
- * @param {number | string} height 高度(number 类型默认px, 支持字符串大小 "100%" | "50vh")
6411
- * @since 0.0.1
6412
- * @example
6413
- * ```ts
6414
- * theme.resize(600, 400) // 600px * 400px
6415
- * theme.resize("600px", "400px") // 600px * 400px
6416
- * theme.resize("50%", "1vh")
6417
- * theme.resize("2em", "2rem")
6418
- * // 事件监听 event, 这里是具体的宽高(单位px)
6419
- * theme.on(Theme.EVENTS.resize, (width: number, height: number) => {})
6420
- * ```
6421
- * @returns {void}
6499
+ /**
6500
+ * 重新调整播放器窗口大小
6501
+ *
6502
+ * Adjust the player window size
6503
+ * @param {number | string} width 宽度(number 类型默认px, 支持字符串大小 "100%" | "50vw")
6504
+ * @param {number | string} height 高度(number 类型默认px, 支持字符串大小 "100%" | "50vh")
6505
+ * @since 0.0.1
6506
+ * @example
6507
+ * ```ts
6508
+ * theme.resize(600, 400) // 600px * 400px
6509
+ * theme.resize("600px", "400px") // 600px * 400px
6510
+ * theme.resize("50%", "1vh")
6511
+ * theme.resize("2em", "2rem")
6512
+ * // 事件监听 event, 这里是具体的宽高(单位px)
6513
+ * theme.on(Theme.EVENTS.resize, (width: number, height: number) => {})
6514
+ * ```
6515
+ * @returns {void}
6422
6516
  */ function _resize(theme, width, height) {
6423
6517
  var cssText = '';
6424
6518
  if (/^\d+(\.\d+)?$/.test(width + '')) {
@@ -6481,9 +6575,9 @@
6481
6575
  open: false,
6482
6576
  max: 8
6483
6577
  };
6484
- /**
6485
- * 电子放大控件
6486
- * @category Control
6578
+ /**
6579
+ * 电子放大控件
6580
+ * @category Control
6487
6581
  */ var Zoom$1 = /*#__PURE__*/ function(Control) {
6488
6582
  _inherits$p(Zoom, Control);
6489
6583
  function Zoom(options) {
@@ -6560,8 +6654,8 @@
6560
6654
  }
6561
6655
  Control.prototype.destroy.call(this);
6562
6656
  };
6563
- /**
6564
- * 点击 Control 会触发
6657
+ /**
6658
+ * 点击 Control 会触发
6565
6659
  */ _proto._onControlClick = function _onControlClick(e) {
6566
6660
  this.active = !this.active;
6567
6661
  Control.prototype._onControlClick.call(this, e);
@@ -6581,8 +6675,8 @@
6581
6675
  },
6582
6676
  {
6583
6677
  key: "active",
6584
- get: /**
6585
- * 是否激活
6678
+ get: /**
6679
+ * 是否激活
6586
6680
  */ function get() {
6587
6681
  return this._active;
6588
6682
  },
@@ -7238,8 +7332,8 @@
7238
7332
  return '';
7239
7333
  }
7240
7334
 
7241
- /**
7242
- * Header
7335
+ /**
7336
+ * Header
7243
7337
  */ var Component = /*#__PURE__*/ function() {
7244
7338
  function Component(options) {
7245
7339
  if (options === void 0) options = {};
@@ -7291,8 +7385,8 @@
7291
7385
  this.$popupContainer.appendChild(this.$container);
7292
7386
  }
7293
7387
  var _proto = Component.prototype;
7294
- /**
7295
- * 销毁 header
7388
+ /**
7389
+ * 销毁 header
7296
7390
  */ _proto.destroy = function destroy() {
7297
7391
  var _this_$popupContainer;
7298
7392
  (_this_$popupContainer = this.$popupContainer) == null ? void 0 : _this_$popupContainer.removeChild(this.$container);
@@ -7568,10 +7662,10 @@
7568
7662
  };
7569
7663
  return _set_prototype_of$q(o, p);
7570
7664
  }
7571
- /**
7572
- * 全局全屏
7573
- * 主题和播放器不提供全局全屏的api, 如果开发者想要可以参考这个组件自己实现
7574
- * @category Control
7665
+ /**
7666
+ * 全局全屏
7667
+ * 主题和播放器不提供全局全屏的api, 如果开发者想要可以参考这个组件自己实现
7668
+ * @category Control
7575
7669
  */ var GlobalFullscreen = /*#__PURE__*/ function(Fullscreen) {
7576
7670
  _inherits$m(GlobalFullscreen, Fullscreen);
7577
7671
  function GlobalFullscreen(options) {
@@ -7589,8 +7683,8 @@
7589
7683
  title: (_this_locale1 = this.locale) == null ? void 0 : _this_locale1.BTN_GLOBAL_FULLSCREEN
7590
7684
  });
7591
7685
  };
7592
- /**
7593
- * 点击 Control 会触发
7686
+ /**
7687
+ * 点击 Control 会触发
7594
7688
  */ _proto._onControlClick = function _onControlClick() {
7595
7689
  // 网页全屏的情况下 还可以执行全局全屏
7596
7690
  if (this.isCurrentFullscreen && this._$rootContainer.classList.contains("" + PREFIX_CLASS$1 + "-global-fullscreen")) {
@@ -7636,9 +7730,9 @@
7636
7730
  };
7637
7731
  return _set_prototype_of$p(o, p);
7638
7732
  }
7639
- /**
7640
- * 截图控件,点击后会触发截图事件, 截图数据会通过 onCapture 回调函数返回
7641
- * @category Control
7733
+ /**
7734
+ * 截图控件,点击后会触发截图事件, 截图数据会通过 onCapture 回调函数返回
7735
+ * @category Control
7642
7736
  */ var CapturePicture = /*#__PURE__*/ function(Control) {
7643
7737
  _inherits$l(CapturePicture, Control);
7644
7738
  function CapturePicture(options) {
@@ -7669,8 +7763,8 @@
7669
7763
  title: (_this_locale = this.locale) == null ? void 0 : _this_locale.BTN_CAPTURE
7670
7764
  });
7671
7765
  };
7672
- /**
7673
- * 点击 Control 会触发
7766
+ /**
7767
+ * 点击 Control 会触发
7674
7768
  */ _proto._onControlClick = function _onControlClick(e) {
7675
7769
  var _this = this;
7676
7770
  var _this_options_type, _this_options_cloudRecUpload;
@@ -7746,9 +7840,9 @@
7746
7840
  };
7747
7841
  return _set_prototype_of$n(o, p);
7748
7842
  }
7749
- /**
7750
- * 云台控件
7751
- * @category Control
7843
+ /**
7844
+ * 云台控件
7845
+ * @category Control
7752
7846
  */ var Ptz = /*#__PURE__*/ function(Control) {
7753
7847
  _inherits$k(Ptz, Control);
7754
7848
  function Ptz(options) {
@@ -7837,8 +7931,8 @@
7837
7931
  }
7838
7932
  };
7839
7933
  };
7840
- /**
7841
- * 点击 Control 会触发
7934
+ /**
7935
+ * 点击 Control 会触发
7842
7936
  */ _proto._onControlClick = function _onControlClick(e) {
7843
7937
  Control.prototype._onControlClick.call(this, e);
7844
7938
  this.active = !this.active;
@@ -7883,6 +7977,14 @@
7883
7977
  ]);
7884
7978
  return Ptz;
7885
7979
  }(Control);
7980
+ /**
7981
+ * 云台是对设备的实时控制,回放场景下转动云台不影响已录制的画面。
7982
+ *
7983
+ * 依据是语义与 mobileRec 模板(不含云台)。`pcRec` 模板的配置里虽然还留着 `pantile`,
7984
+ * 但实测在回放地址下它不会被渲染出来,因此这里声明为 live-only 不会对内置模板误报。
7985
+ */ Ptz.supportedPlayTypes = [
7986
+ 'live'
7987
+ ];
7886
7988
 
7887
7989
  function formatTime(seconds, format) {
7888
7990
  if (format === void 0) format = 'MM:SS';
@@ -7941,14 +8043,14 @@
7941
8043
  var RECORD_DEFAULT_OPTIONS = {
7942
8044
  maxDuration: 3600
7943
8045
  };
7944
- /**
7945
- * 录制控件,点击开始录制,再次点击停止录制,
7946
- * 录制开始到结束会依次触发 `startRecord` 和 `stopRecord` 事件
7947
- *
7948
- * 注意:
7949
- * 1. 录制过程中会占用浏览器内存, 请根据实际情况进行配置
7950
- * 2. 录制时间很短可能会因为浏览器的限制或没有I帧而无法生成有效的视频文件
7951
- * @category Control
8046
+ /**
8047
+ * 录制控件,点击开始录制,再次点击停止录制,
8048
+ * 录制开始到结束会依次触发 `startRecord` 和 `stopRecord` 事件
8049
+ *
8050
+ * 注意:
8051
+ * 1. 录制过程中会占用浏览器内存, 请根据实际情况进行配置
8052
+ * 2. 录制时间很短可能会因为浏览器的限制或没有I帧而无法生成有效的视频文件
8053
+ * @category Control
7952
8054
  */ var Record = /*#__PURE__*/ function(Control) {
7953
8055
  _inherits$j(Record, Control);
7954
8056
  function Record(options) {
@@ -7963,16 +8065,16 @@
7963
8065
  return _this;
7964
8066
  }
7965
8067
  var _proto = Record.prototype;
7966
- /**
7967
- * 渲染图标
8068
+ /**
8069
+ * 渲染图标
7968
8070
  */ _proto._render = function _render() {
7969
8071
  var _this_locale;
7970
8072
  this.$container.innerHTML = IconComponents.record({
7971
8073
  title: (_this_locale = this.locale) == null ? void 0 : _this_locale.BTN_RECORDVIDEO
7972
8074
  });
7973
8075
  };
7974
- /**
7975
- * 渲染计时器
8076
+ /**
8077
+ * 渲染计时器
7976
8078
  */ _proto._renderTimer = function _renderTimer() {
7977
8079
  var _this = this;
7978
8080
  var _this__options_rootContainer, _this__options;
@@ -8001,8 +8103,8 @@
8001
8103
  this._destroyTimer();
8002
8104
  Control.prototype.destroy.call(this);
8003
8105
  };
8004
- /**
8005
- * 销毁定时器和销毁节点
8106
+ /**
8107
+ * 销毁定时器和销毁节点
8006
8108
  */ _proto._destroyTimer = function _destroyTimer() {
8007
8109
  this._seconds = 0;
8008
8110
  if (this._timer) {
@@ -8017,8 +8119,8 @@
8017
8119
  }
8018
8120
  this._active = false;
8019
8121
  };
8020
- /**
8021
- * 点击 Control 会触发
8122
+ /**
8123
+ * 点击 Control 会触发
8022
8124
  */ _proto._onControlClick = function _onControlClick(e) {
8023
8125
  this.active = !this.active;
8024
8126
  Control.prototype._onControlClick.call(this, e);
@@ -8026,8 +8128,8 @@
8026
8128
  _create_class$c(Record, [
8027
8129
  {
8028
8130
  key: "active",
8029
- get: /**
8030
- * 是否激活
8131
+ get: /**
8132
+ * 是否激活
8031
8133
  */ function get() {
8032
8134
  return this._active;
8033
8135
  },
@@ -8220,14 +8322,14 @@
8220
8322
  };
8221
8323
  }
8222
8324
  }
8223
- /**
8224
- * 对讲控件
8225
- *
8226
- * navigator.mediaDevices.getUserMedia {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia} 返回一个 Promise 对象,
8227
- * 成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,
8228
- * promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。
8229
- *
8230
- * @category Control
8325
+ /**
8326
+ * 对讲控件
8327
+ *
8328
+ * navigator.mediaDevices.getUserMedia {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia} 返回一个 Promise 对象,
8329
+ * 成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,
8330
+ * promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。
8331
+ *
8332
+ * @category Control
8231
8333
  */ var Talk = /*#__PURE__*/ function(Control) {
8232
8334
  _inherits$i(Talk, Control);
8233
8335
  function Talk(options) {
@@ -8270,16 +8372,16 @@
8270
8372
  Control.prototype.reset.call(this, hide);
8271
8373
  }
8272
8374
  };
8273
- /**
8274
- * 销毁对讲
8375
+ /**
8376
+ * 销毁对讲
8275
8377
  */ _proto.destroy = function destroy() {
8276
8378
  if (this.active) {
8277
8379
  this.reset();
8278
8380
  }
8279
8381
  Control.prototype.destroy.call(this);
8280
8382
  };
8281
- /**
8282
- * 点击 Control 会触发
8383
+ /**
8384
+ * 点击 Control 会触发
8283
8385
  */ _proto._onControlClick = function _onControlClick(e) {
8284
8386
  var _this = this, _superprop_get__onControlClick = function _superprop_get__onControlClick() {
8285
8387
  return Control.prototype._onControlClick;
@@ -8299,13 +8401,13 @@
8299
8401
  _create_class$b(Talk, [
8300
8402
  {
8301
8403
  key: "value",
8302
- get: /**
8303
- * 获取当前值
8404
+ get: /**
8405
+ * 获取当前值
8304
8406
  */ function get() {
8305
8407
  return this._value;
8306
8408
  },
8307
- set: /**
8308
- * 设置当前值 [0-1]
8409
+ set: /**
8410
+ * 设置当前值 [0-1]
8309
8411
  */ function set(value) {
8310
8412
  // 没有激活状态,则不处理
8311
8413
  if (!this.active) {
@@ -8335,6 +8437,9 @@
8335
8437
  ]);
8336
8438
  return Talk;
8337
8439
  }(Control);
8440
+ /** 对讲是实时上行通道,只有直播场景有意义 */ Talk.supportedPlayTypes = [
8441
+ 'live'
8442
+ ];
8338
8443
 
8339
8444
  function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
8340
8445
  try {
@@ -8491,12 +8596,12 @@
8491
8596
  };
8492
8597
  }
8493
8598
  }
8494
- /**
8495
- * 语音广播控件
8496
- *
8497
- * 用于触发语音广播功能的按钮控件
8498
- *
8499
- * @category Control
8599
+ /**
8600
+ * 语音广播控件
8601
+ *
8602
+ * 用于触发语音广播功能的按钮控件
8603
+ *
8604
+ * @category Control
8500
8605
  */ var Broadcast = /*#__PURE__*/ function(Control) {
8501
8606
  _inherits$h(Broadcast, Control);
8502
8607
  function Broadcast(options) {
@@ -8536,16 +8641,16 @@
8536
8641
  Control.prototype.reset.call(this, hide);
8537
8642
  }
8538
8643
  };
8539
- /**
8540
- * 销毁语音广播控件
8644
+ /**
8645
+ * 销毁语音广播控件
8541
8646
  */ _proto.destroy = function destroy() {
8542
8647
  if (this.active) {
8543
8648
  this.reset();
8544
8649
  }
8545
8650
  Control.prototype.destroy.call(this);
8546
8651
  };
8547
- /**
8548
- * 点击 Control 会触发
8652
+ /**
8653
+ * 点击 Control 会触发
8549
8654
  */ _proto._onControlClick = function _onControlClick(e) {
8550
8655
  var _this = this, _superprop_get__onControlClick = function _superprop_get__onControlClick() {
8551
8656
  return Control.prototype._onControlClick;
@@ -8566,6 +8671,9 @@
8566
8671
  };
8567
8672
  return Broadcast;
8568
8673
  }(Control);
8674
+ /** 语音广播是实时上行通道,只有直播场景有意义(另需 `sdkType === 'base'`,见构造函数) */ Broadcast.supportedPlayTypes = [
8675
+ 'live'
8676
+ ];
8569
8677
 
8570
8678
  function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
8571
8679
  try {
@@ -8722,12 +8830,12 @@
8722
8830
  };
8723
8831
  }
8724
8832
  }
8725
- /**
8726
- * AI对话框控件
8727
- *
8728
- * 用于触发AI对话框功能的按钮控件
8729
- *
8730
- * @category Control
8833
+ /**
8834
+ * AI对话框控件
8835
+ *
8836
+ * 用于触发AI对话框功能的按钮控件
8837
+ *
8838
+ * @category Control
8731
8839
  */ var AIChat = /*#__PURE__*/ function(Control) {
8732
8840
  _inherits$g(AIChat, Control);
8733
8841
  function AIChat(options) {
@@ -8768,16 +8876,16 @@
8768
8876
  Control.prototype.reset.call(this, hide);
8769
8877
  }
8770
8878
  };
8771
- /**
8772
- * 销毁AI对话框控件
8879
+ /**
8880
+ * 销毁AI对话框控件
8773
8881
  */ _proto.destroy = function destroy() {
8774
8882
  if (this.active) {
8775
8883
  this.reset();
8776
8884
  }
8777
8885
  Control.prototype.destroy.call(this);
8778
8886
  };
8779
- /**
8780
- * 点击 Control 会触发
8887
+ /**
8888
+ * 点击 Control 会触发
8781
8889
  */ _proto._onControlClick = function _onControlClick(e) {
8782
8890
  var _this = this, _superprop_get__onControlClick = function _superprop_get__onControlClick() {
8783
8891
  return Control.prototype._onControlClick;
@@ -8798,6 +8906,14 @@
8798
8906
  };
8799
8907
  return AIChat;
8800
8908
  }(Control);
8909
+ /**
8910
+ * 只在云存储回放下可用。
8911
+ *
8912
+ * 这是全部控件里证据最强的一条:构造函数里已显式要求 `recType === 'cloud'`
8913
+ * 且排除 `busType === '7'`(云录制),不满足时直接 `display: none`。
8914
+ */ AIChat.supportedPlayTypes = [
8915
+ 'cloudRec'
8916
+ ];
8801
8917
 
8802
8918
  function _extends$h() {
8803
8919
  _extends$h = Object.assign || function assign(target) {
@@ -8829,12 +8945,12 @@
8829
8945
  };
8830
8946
  return _set_prototype_of$i(o, p);
8831
8947
  }
8832
- /**
8833
- * 直播按钮控件
8834
- *
8835
- * 点击切换到直播模式
8836
- *
8837
- * @category Control
8948
+ /**
8949
+ * 直播按钮控件
8950
+ *
8951
+ * 点击切换到直播模式
8952
+ *
8953
+ * @category Control
8838
8954
  */ var Live = /*#__PURE__*/ function(Control) {
8839
8955
  _inherits$f(Live, Control);
8840
8956
  function Live(options) {
@@ -8856,9 +8972,9 @@
8856
8972
  return _this;
8857
8973
  }
8858
8974
  var _proto = Live.prototype;
8859
- /**
8860
- * 根据 urlInfo 同步激活状态
8861
- * 在初始化和播放地址切换后调用
8975
+ /**
8976
+ * 根据 urlInfo 同步激活状态
8977
+ * 在初始化和播放地址切换后调用
8862
8978
  */ _proto._syncActiveByUrlInfo = function _syncActiveByUrlInfo(urlInfo) {
8863
8979
  var shouldBeActive = !!(urlInfo && urlInfo.type === 'live');
8864
8980
  this.active = shouldBeActive;
@@ -8869,13 +8985,13 @@
8869
8985
  title: ((_this_locale = this.locale) == null ? void 0 : _this_locale.BTN_LIVE) || '直播'
8870
8986
  });
8871
8987
  };
8872
- /**
8873
- * 销毁
8988
+ /**
8989
+ * 销毁
8874
8990
  */ _proto.destroy = function destroy() {
8875
8991
  Control.prototype.destroy.call(this);
8876
8992
  };
8877
- /**
8878
- * 点击 Control 会触发
8993
+ /**
8994
+ * 点击 Control 会触发
8879
8995
  */ _proto._onControlClick = function _onControlClick(e) {
8880
8996
  var _this__options_onChange, _this__options;
8881
8997
  Control.prototype._onControlClick.call(this, e);
@@ -8920,12 +9036,12 @@
8920
9036
  };
8921
9037
  return _set_prototype_of$h(o, p);
8922
9038
  }
8923
- /**
8924
- * 回放下拉控件
8925
- *
8926
- * 鼠标移入弹出气泡,展示云存储、云录制、本地回放三个选项
8927
- *
8928
- * @category Control
9039
+ /**
9040
+ * 回放下拉控件
9041
+ *
9042
+ * 鼠标移入弹出气泡,展示云存储、云录制、本地回放三个选项
9043
+ *
9044
+ * @category Control
8929
9045
  */ var RecDropdown = /*#__PURE__*/ function(Control) {
8930
9046
  _inherits$e(RecDropdown, Control);
8931
9047
  function RecDropdown(options) {
@@ -8942,16 +9058,16 @@
8942
9058
  _this.$container.style.display = 'none';
8943
9059
  }
8944
9060
  // 初始化时根据 urlInfo 确定当前回放类型和激活状态
8945
- _this._recType = options.recType || ((_options_props = options.props) == null ? void 0 : _options_props.recType) || 'cloudRec';
9061
+ _this._recType = options.recType || ((_options_props = options.props) == null ? void 0 : _options_props.recType) || '';
8946
9062
  _this._syncActiveByUrlInfo((_this___options_props1 = _this.__options.props) == null ? void 0 : _this___options_props1.urlInfo);
8947
9063
  _this._render();
8948
9064
  _this._initPicker();
8949
9065
  return _this;
8950
9066
  }
8951
9067
  var _proto = RecDropdown.prototype;
8952
- /**
8953
- * 根据 urlInfo 同步激活状态和回放类型
8954
- * 在初始化和播放地址切换后调用
9068
+ /**
9069
+ * 根据 urlInfo 同步激活状态和回放类型
9070
+ * 在初始化和播放地址切换后调用
8955
9071
  */ _proto._syncActiveByUrlInfo = function _syncActiveByUrlInfo(urlInfo) {
8956
9072
  if (urlInfo && urlInfo.type === 'rec') {
8957
9073
  var _urlInfo_searchParams1;
@@ -9028,8 +9144,8 @@
9028
9144
  target == null ? void 0 : target.classList.add("" + PREFIX_CLASS$1 + "-active");
9029
9145
  }
9030
9146
  };
9031
- /**
9032
- * 销毁
9147
+ /**
9148
+ * 销毁
9033
9149
  */ _proto.destroy = function destroy() {
9034
9150
  var _this__delegation_destroy, _this__delegation;
9035
9151
  (_this__delegation = this._delegation) == null ? void 0 : (_this__delegation_destroy = _this__delegation.destroy) == null ? void 0 : _this__delegation_destroy.call(_this__delegation);
@@ -9041,8 +9157,8 @@
9041
9157
  }
9042
9158
  Control.prototype.destroy.call(this);
9043
9159
  };
9044
- /**
9045
- * 点击 Control 会触发(移动端 click 触发 picker)
9160
+ /**
9161
+ * 点击 Control 会触发(移动端 click 触发 picker)
9046
9162
  */ // eslint-disable-next-line @typescript-eslint/no-unused-vars
9047
9163
  _proto._onControlClick = function _onControlClick(_e) {
9048
9164
  // picker 自行处理 click/hover,这里不额外处理
@@ -9195,7 +9311,6 @@
9195
9311
  if (this._panelOpen) {
9196
9312
  this.emit(EVENTS$2.control.recListChange, false);
9197
9313
  }
9198
- this.emit(EVENTS$2.control.recListDestroy);
9199
9314
  if (this._modal) {
9200
9315
  this._modal.destroy();
9201
9316
  this._modal = null;
@@ -9227,6 +9342,16 @@
9227
9342
  };
9228
9343
  return RecList;
9229
9344
  }(Control);
9345
+ /**
9346
+ * 录像片段列表,只对回放有意义。
9347
+ *
9348
+ * 依据是内置模板分布(仅 pcRec 含 `recList`)与语义。若后续确认本地卡回放
9349
+ * 没有片段列表接口,把 `'rec'` 去掉即可。
9350
+ */ RecList.supportedPlayTypes = [
9351
+ 'rec',
9352
+ 'cloudRec',
9353
+ 'cloudRecord'
9354
+ ];
9230
9355
 
9231
9356
  function _extends$d() {
9232
9357
  _extends$d = Object.assign || function assign(target) {
@@ -9258,12 +9383,12 @@
9258
9383
  };
9259
9384
  return _set_prototype_of$e(o, p);
9260
9385
  }
9261
- /**
9262
- * 告警消息按钮控件
9263
- *
9264
- * 点击弹出告警消息列表弹窗(纯触发按钮,无激活状态)
9265
- *
9266
- * @category Control
9386
+ /**
9387
+ * 告警消息按钮控件
9388
+ *
9389
+ * 点击弹出告警消息列表弹窗(纯触发按钮,无激活状态)
9390
+ *
9391
+ * @category Control
9267
9392
  */ var AlarmMessage = /*#__PURE__*/ function(Control) {
9268
9393
  _inherits$c(AlarmMessage, Control);
9269
9394
  function AlarmMessage(options) {
@@ -9287,16 +9412,16 @@
9287
9412
  title: ((_this_locale = this.locale) == null ? void 0 : _this_locale.BTN_ALARM_MESSAGE) || '消息'
9288
9413
  });
9289
9414
  };
9290
- /**
9291
- * 销毁
9415
+ /**
9416
+ * 销毁
9292
9417
  */ _proto.destroy = function destroy() {
9293
9418
  if (this._panelOpen) {
9294
9419
  this.emit(EVENTS$2.control.alarmMessageChange, false);
9295
9420
  }
9296
9421
  Control.prototype.destroy.call(this);
9297
9422
  };
9298
- /**
9299
- * 点击 Control 会触发
9423
+ /**
9424
+ * 点击 Control 会触发
9300
9425
  */ _proto._onControlClick = function _onControlClick(e) {
9301
9426
  var _this__options_onChange, _this__options;
9302
9427
  Control.prototype._onControlClick.call(this, e);
@@ -9361,54 +9486,54 @@
9361
9486
  onChange: function onChange() {},
9362
9487
  onOpenChange: function onOpenChange() {}
9363
9488
  };
9364
- /**
9365
- * 选择器切换 (支持PC/Mobile)
9366
- * @category Control
9367
- * @example
9368
- * ```ts
9369
- * new Select({
9370
- * title: '清晰度',
9371
- * list: [
9372
- * {
9373
- * label: '高清',
9374
- * value: 'hd',
9375
- * streamTypeIn: 1,
9376
- * },
9377
- * {
9378
- * label: '超清',
9379
- * value: 'super',
9380
- * streamTypeIn: 2,
9381
- * }
9382
- * ],
9383
- * value: 'hd',
9384
- * onChange: (value, item) => {
9385
- * console.log('选择了', value, item);
9386
- * }
9387
- * })
9388
- *
9389
- * // 如果想扩展 Select 组件,可以继承 Select 组件
9390
- * // 例如清晰度切换组件
9391
- * class Definition extends Select {
9392
- * options: DefinitionOptions;
9393
- * constructor(options: DefinitionOptions) {
9394
- * super({
9395
- * ...options,
9396
- * fieldNames: { label: 'name', value: 'level',},
9397
- * title: options?.locale?.definition,
9398
- * controlType: 'button',
9399
- * classNameSuffix: 'definition',
9400
- * onChange: (value: SelectItem['value'], item) => {
9401
- * options?.onChange?.(value, item);
9402
- * this.emit(EVENTS.control.definitionChange, value, item);
9403
- * },
9404
- * onOpenChange: (open: boolean, value: SelectItem['value'], item) => {
9405
- * options?.onOpenChange?.(open, value, item);
9406
- * this.emit(EVENTS.control.definitionPanelOpenChange, open, value, item);
9407
- * }
9408
- * });
9409
- * }
9410
- * }
9411
- * ```
9489
+ /**
9490
+ * 选择器切换 (支持PC/Mobile)
9491
+ * @category Control
9492
+ * @example
9493
+ * ```ts
9494
+ * new Select({
9495
+ * title: '清晰度',
9496
+ * list: [
9497
+ * {
9498
+ * label: '高清',
9499
+ * value: 'hd',
9500
+ * streamTypeIn: 1,
9501
+ * },
9502
+ * {
9503
+ * label: '超清',
9504
+ * value: 'super',
9505
+ * streamTypeIn: 2,
9506
+ * }
9507
+ * ],
9508
+ * value: 'hd',
9509
+ * onChange: (value, item) => {
9510
+ * console.log('选择了', value, item);
9511
+ * }
9512
+ * })
9513
+ *
9514
+ * // 如果想扩展 Select 组件,可以继承 Select 组件
9515
+ * // 例如清晰度切换组件
9516
+ * class Definition extends Select {
9517
+ * options: DefinitionOptions;
9518
+ * constructor(options: DefinitionOptions) {
9519
+ * super({
9520
+ * ...options,
9521
+ * fieldNames: { label: 'name', value: 'level',},
9522
+ * title: options?.locale?.definition,
9523
+ * controlType: 'button',
9524
+ * classNameSuffix: 'definition',
9525
+ * onChange: (value: SelectItem['value'], item) => {
9526
+ * options?.onChange?.(value, item);
9527
+ * this.emit(EVENTS.control.definitionChange, value, item);
9528
+ * },
9529
+ * onOpenChange: (open: boolean, value: SelectItem['value'], item) => {
9530
+ * options?.onOpenChange?.(open, value, item);
9531
+ * this.emit(EVENTS.control.definitionPanelOpenChange, open, value, item);
9532
+ * }
9533
+ * });
9534
+ * }
9535
+ * }
9536
+ * ```
9412
9537
  */ var Select = /*#__PURE__*/ function(Control) {
9413
9538
  _inherits$b(Select, Control);
9414
9539
  function Select(options) {
@@ -9460,9 +9585,9 @@
9460
9585
  return _this;
9461
9586
  }
9462
9587
  var _proto = Select.prototype;
9463
- /**
9464
- * 更新选项列表
9465
- * @param list - 选项列表
9588
+ /**
9589
+ * 更新选项列表
9590
+ * @param list - 选项列表
9466
9591
  */ _proto.updateOptions = function updateOptions(list) {
9467
9592
  var _this = this;
9468
9593
  if (list === void 0) list = [];
@@ -9547,8 +9672,8 @@
9547
9672
  });
9548
9673
  }
9549
9674
  };
9550
- /**
9551
- * 销毁
9675
+ /**
9676
+ * 销毁
9552
9677
  */ _proto.destroy = function destroy() {
9553
9678
  var _this__delegationOption_destroy, _this__delegationOption, _this__delegationClose_destroy, _this__delegationClose, _this__delegationCancel_destroy, _this__delegationCancel;
9554
9679
  (_this__delegationOption = this._delegationOption) == null ? void 0 : (_this__delegationOption_destroy = _this__delegationOption.destroy) == null ? void 0 : _this__delegationOption_destroy.call(_this__delegationOption);
@@ -9570,8 +9695,8 @@
9570
9695
  e.stopPropagation();
9571
9696
  e.preventDefault();
9572
9697
  };
9573
- /**
9574
- * 点击 Control 会触发
9698
+ /**
9699
+ * 点击 Control 会触发
9575
9700
  */ _proto._onControlClick = function _onControlClick(e) {
9576
9701
  this._options.onClick == null ? void 0 : this._options.onClick.call(this._options, e);
9577
9702
  };
@@ -9590,8 +9715,8 @@
9590
9715
  },
9591
9716
  {
9592
9717
  key: "disabled",
9593
- get: /**
9594
- * 是否禁用
9718
+ get: /**
9719
+ * 是否禁用
9595
9720
  */ function get() {
9596
9721
  return this._disabled;
9597
9722
  },
@@ -9677,15 +9802,15 @@
9677
9802
  };
9678
9803
  });
9679
9804
  }
9680
- /**
9681
- * 清晰度切换控件
9682
- *
9683
- * 清晰度切换控件有三套UI
9684
- * 1. PC 端默认UI,hover 展示清晰度切换面板
9685
- * 2. 移动端 picker选择器清晰度切换面板 + 取消按钮
9686
- * 3. 移动端全屏模式右侧菜单清晰度切换面板
9687
- *
9688
- * @category Control
9805
+ /**
9806
+ * 清晰度切换控件
9807
+ *
9808
+ * 清晰度切换控件有三套UI
9809
+ * 1. PC 端默认UI,hover 展示清晰度切换面板
9810
+ * 2. 移动端 picker选择器清晰度切换面板 + 取消按钮
9811
+ * 3. 移动端全屏模式右侧菜单清晰度切换面板
9812
+ *
9813
+ * @category Control
9689
9814
  */ var Definition = /*#__PURE__*/ function(Select) {
9690
9815
  _inherits$a(Definition, Select);
9691
9816
  function Definition(options) {
@@ -9751,14 +9876,22 @@
9751
9876
  return _this;
9752
9877
  }
9753
9878
  var _proto = Definition.prototype;
9754
- /**
9755
- * 重置,恢复默认值
9756
- * @param hide 默认不隐藏
9879
+ /**
9880
+ * 重置,恢复默认值
9881
+ * @param hide 默认不隐藏
9757
9882
  */ _proto.reset = function reset(hide) {
9758
9883
  Select.prototype.reset.call(this, hide);
9759
9884
  };
9760
9885
  return Definition;
9761
9886
  }(Select);
9887
+ /**
9888
+ * 清晰度切换只在直播下有意义:回放播的是已落盘的码流,清晰度由录制时决定。
9889
+ *
9890
+ * 依据是内置模板分布(`hd` 只出现在 pcLive / mobileLive / security),控件本身无硬约束。
9891
+ * 若后续确认本地卡回放支持主/子码流切换,把 `'rec'` 加进来即可。
9892
+ */ Definition.supportedPlayTypes = [
9893
+ 'live'
9894
+ ];
9762
9895
 
9763
9896
  function _assert_this_initialized(self) {
9764
9897
  if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
@@ -9804,13 +9937,13 @@
9804
9937
  16
9805
9938
  ]; // 8, 16
9806
9939
  var SPEED_DEFAULT_OPTIONS = {
9807
- /**
9808
- * 默认倍速 1, 如果传入的值不在列表中会使用 1 倍速,可能会没有选中
9809
- * 暂时不支持初始化时设置倍速
9940
+ /**
9941
+ * 默认倍速 1, 如果传入的值不在列表中会使用 1 倍速,可能会没有选中
9942
+ * 暂时不支持初始化时设置倍速
9810
9943
  */ // value: 1, // 对应list 中的 value
9811
9944
  // 这里不要设置多语言, 比较麻烦
9812
- /**
9813
- * 倍速列表, 需要是 2 的指数,不能小于 0.5, 最大 16 倍
9945
+ /**
9946
+ * 倍速列表, 需要是 2 的指数,不能小于 0.5, 最大 16 倍
9814
9947
  */ list: SUPPORT_SPEED.reverse().map(function(speed) {
9815
9948
  return {
9816
9949
  label: "" + speed + "x",
@@ -9818,13 +9951,13 @@
9818
9951
  };
9819
9952
  })
9820
9953
  };
9821
- /**
9822
- * 倍速切换控件, 不支持动态切换倍速列表
9823
- *
9824
- * 注意:
9825
- * 1. 本地回放倍速需要设备本身支持才可以, 如果不支持切换后的倍数不会生效, 云端回放(云存储,云录制)倍速都是支持, 需要是 2 的指数,不能小于 0.5, 最大 16 倍;
9826
- * 2. 标准流不支持;
9827
- * @category Control
9954
+ /**
9955
+ * 倍速切换控件, 不支持动态切换倍速列表
9956
+ *
9957
+ * 注意:
9958
+ * 1. 本地回放倍速需要设备本身支持才可以, 如果不支持切换后的倍数不会生效, 云端回放(云存储,云录制)倍速都是支持, 需要是 2 的指数,不能小于 0.5, 最大 16 倍;
9959
+ * 2. 标准流不支持;
9960
+ * @category Control
9828
9961
  */ var Speed = /*#__PURE__*/ function(Select) {
9829
9962
  _inherits$9(Speed, Select);
9830
9963
  function Speed(options) {
@@ -9858,10 +9991,10 @@
9858
9991
  return _this;
9859
9992
  }
9860
9993
  var _proto = Speed.prototype;
9861
- /**
9862
- * 滤掉本地回放不支持的倍速
9863
- * @param optionsList 初始化配置倍速列表
9864
- * @param type 回放类型
9994
+ /**
9995
+ * 滤掉本地回放不支持的倍速
9996
+ * @param optionsList 初始化配置倍速列表
9997
+ * @param type 回放类型
9865
9998
  */ _proto._filterSpeedList = function _filterSpeedList(optionsList, type, url) {
9866
9999
  if (!optionsList) {
9867
10000
  // 非用户自定义 /openpb/ 是标准流回放路径
@@ -9889,6 +10022,16 @@
9889
10022
  };
9890
10023
  return Speed;
9891
10024
  }(Select);
10025
+ /**
10026
+ * 倍速只对回放有意义;直播是实时流,没有倍速语义。
10027
+ *
10028
+ * 三类回放都支持,但档位上限不同(见 `_filterSpeedList`):
10029
+ * 本地卡回放与标准流 ≤ 4x,云存储 / 云录制 ≤ 16x。
10030
+ */ Speed.supportedPlayTypes = [
10031
+ 'rec',
10032
+ 'cloudRec',
10033
+ 'cloudRecord'
10034
+ ];
9892
10035
 
9893
10036
  /*
9894
10037
  * @ezuikit/control-date-picker v2.1.2-beta.1
@@ -10103,6 +10246,11 @@
10103
10246
  };
10104
10247
  return DatePickerControl;
10105
10248
  }(Control);
10249
+ /** 选日期是为了定位录像,只对回放有意义(初值取自 `urlInfo.searchParams.begin`) */ DatePickerControl.supportedPlayTypes = [
10250
+ 'rec',
10251
+ 'cloudRec',
10252
+ 'cloudRecord'
10253
+ ];
10106
10254
 
10107
10255
  function _extends$7() {
10108
10256
  _extends$7 = Object.assign || function assign(target) {
@@ -10135,9 +10283,9 @@
10135
10283
  return _set_prototype_of$8(o, p);
10136
10284
  }
10137
10285
  /** 时间格式 HH:mm:ss */ var TIME_FORMAT = 'HH:mm:ss';
10138
- /**
10139
- * 时间选择器控件
10140
- * @category Control
10286
+ /**
10287
+ * 时间选择器控件
10288
+ * @category Control
10141
10289
  */ var TimePickerControl = /*#__PURE__*/ function(Control) {
10142
10290
  _inherits$7(TimePickerControl, Control);
10143
10291
  function TimePickerControl(options) {
@@ -10198,9 +10346,9 @@
10198
10346
  }
10199
10347
  }));
10200
10348
  };
10201
- /**
10202
- * 设置时间
10203
- * @param time 设置的时间 HH:mm:ss
10349
+ /**
10350
+ * 设置时间
10351
+ * @param time 设置的时间 HH:mm:ss
10204
10352
  */ _proto.setTime = function setTime(time) {
10205
10353
  var _this_timePicker;
10206
10354
  (_this_timePicker = this.timePicker) == null ? void 0 : _this_timePicker.setCurrent(time);
@@ -10216,9 +10364,9 @@
10216
10364
  if (this.timePicker) this.timePicker.open = false;
10217
10365
  Control.prototype.reset.call(this);
10218
10366
  };
10219
- /**
10220
- * 销毁控件
10221
- * @override
10367
+ /**
10368
+ * 销毁控件
10369
+ * @override
10222
10370
  */ _proto.destroy = function destroy() {
10223
10371
  if (this.timePicker) {
10224
10372
  this.timePicker.destroy();
@@ -10230,14 +10378,19 @@
10230
10378
  _proto._getTimeStr = function _getTimeStr() {
10231
10379
  return this._value;
10232
10380
  };
10233
- /**
10234
- * 点击 Control 会触发
10235
- * @overload super._onControlClick(e: Event)
10381
+ /**
10382
+ * 点击 Control 会触发
10383
+ * @overload super._onControlClick(e: Event)
10236
10384
  */ _proto._onControlClick = function _onControlClick(e) {
10237
10385
  Control.prototype._onControlClick.call(this, e);
10238
10386
  };
10239
10387
  return TimePickerControl;
10240
10388
  }(Control);
10389
+ /** 选时间是为了定位录像,只对回放有意义(初值取自 `urlInfo.searchParams.begin`) */ TimePickerControl.supportedPlayTypes = [
10390
+ 'rec',
10391
+ 'cloudRec',
10392
+ 'cloudRecord'
10393
+ ];
10241
10394
 
10242
10395
  /**
10243
10396
  * drag scroll support move and touch
@@ -10733,8 +10886,8 @@
10733
10886
  };
10734
10887
  return _set_prototype_of$6(o, p);
10735
10888
  }
10736
- /**
10737
- * 回放时间轴控件
10889
+ /**
10890
+ * 回放时间轴控件
10738
10891
  */ var TimeLineControl = /*#__PURE__*/ function(Control) {
10739
10892
  _inherits$6(TimeLineControl, Control);
10740
10893
  function TimeLineControl(options) {
@@ -10894,13 +11047,18 @@
10894
11047
  }
10895
11048
  Control.prototype.destroy.call(this);
10896
11049
  };
10897
- /**
10898
- * 点击 Control 会触发
11050
+ /**
11051
+ * 点击 Control 会触发
10899
11052
  */ _proto._onControlClick = function _onControlClick(e) {
10900
11053
  this._options.onClick == null ? void 0 : this._options.onClick.call(this._options, e);
10901
11054
  };
10902
11055
  return TimeLineControl;
10903
11056
  }(Control);
11057
+ /** 时间轴展示的是录像片段,只对回放有意义(渲染层的 `_needTimeLine` 也要求 `urlInfo.type === 'rec'`) */ TimeLineControl.supportedPlayTypes = [
11058
+ 'rec',
11059
+ 'cloudRec',
11060
+ 'cloudRecord'
11061
+ ];
10904
11062
 
10905
11063
  /*
10906
11064
  * @ezuikit/control-segment-progress v0.0.1
@@ -10938,24 +11096,24 @@
10938
11096
  };
10939
11097
  return _set_prototype_of$5(o, p);
10940
11098
  }
10941
- /**
10942
- * 播放结束后忽略 OSD 回写的静默期(毫秒)
10943
- *
10944
- * 断流结束时 SDK 不会立刻停掉 OSD 轮询(要让时间轴光标跟到画面最后一帧,见
10945
- * api/_playbackRange.ts 的 OSD_SETTLE_MS = 2500),这些回写的时间早于区间末端,
10946
- * 会把刚补满的进度拉回去。取值需覆盖该窗口。
10947
- *
10948
- * 用静默期而不是永久忽略:用户可能从时间轴点回区间内继续看,那条 seek 不经过
10949
- * 进度条的 onChange,永久忽略会让进度条卡死不再更新。
11099
+ /**
11100
+ * 播放结束后忽略 OSD 回写的静默期(毫秒)
11101
+ *
11102
+ * 断流结束时 SDK 不会立刻停掉 OSD 轮询(要让时间轴光标跟到画面最后一帧,见
11103
+ * api/_playbackRange.ts 的 OSD_SETTLE_MS = 2500),这些回写的时间早于区间末端,
11104
+ * 会把刚补满的进度拉回去。取值需覆盖该窗口。
11105
+ *
11106
+ * 用静默期而不是永久忽略:用户可能从时间轴点回区间内继续看,那条 seek 不经过
11107
+ * 进度条的 onChange,永久忽略会让进度条卡死不再更新。
10950
11108
  */ var PLAYBACK_END_SILENCE_MS = 3000;
10951
- /**
10952
- * 读取录像片段的起止时间(毫秒)
10953
- *
10954
- * 录像列表是服务端原始返回、未做字段归一化,`begin/end` 与 `startTime/endTime`
10955
- * 两套字段名在不同回放类型下都出现过,这里统一兼容。
10956
- *
10957
- * @param seg 录像片段
10958
- * @param which 取起点还是终点
11109
+ /**
11110
+ * 读取录像片段的起止时间(毫秒)
11111
+ *
11112
+ * 录像列表是服务端原始返回、未做字段归一化,`begin/end` 与 `startTime/endTime`
11113
+ * 两套字段名在不同回放类型下都出现过,这里统一兼容。
11114
+ *
11115
+ * @param seg 录像片段
11116
+ * @param which 取起点还是终点
10959
11117
  */ function segMs(seg, which) {
10960
11118
  var _ref, _ref1;
10961
11119
  var value = which === 'start' ? (_ref = seg == null ? void 0 : seg.startTime) != null ? _ref : seg == null ? void 0 : seg.begin : (_ref1 = seg == null ? void 0 : seg.endTime) != null ? _ref1 : seg == null ? void 0 : seg.end;
@@ -10963,12 +11121,12 @@
10963
11121
  if (typeof value === 'number') return value < 1e12 ? value * 1000 : value;
10964
11122
  return distExports$3.DateTime.toDate(value).getTime();
10965
11123
  }
10966
- /**
10967
- * 回放片段进度条控件(移动端)
10968
- *
10969
- * 只在设置了播放区间时渲染,范围是「当前录像片段 ∩ 播放区间」。
10970
- * 区间内跨片段的定位由时间轴承担,这里只负责当前片段的精细拖动。
10971
- * @category Control
11124
+ /**
11125
+ * 回放片段进度条控件(移动端)
11126
+ *
11127
+ * 只在设置了播放区间时渲染,范围是「当前录像片段 ∩ 播放区间」。
11128
+ * 区间内跨片段的定位由时间轴承担,这里只负责当前片段的精细拖动。
11129
+ * @category Control
10972
11130
  */ var SegmentProgressControl = /*#__PURE__*/ function(Control) {
10973
11131
  _inherits$5(SegmentProgressControl, Control);
10974
11132
  function SegmentProgressControl(options) {
@@ -11035,9 +11193,9 @@
11035
11193
  });
11036
11194
  this._updateVisible();
11037
11195
  };
11038
- /**
11039
- * 设置播放区间
11040
- * @param range 区间;null 表示解除约束
11196
+ /**
11197
+ * 设置播放区间
11198
+ * @param range 区间;null 表示解除约束
11041
11199
  */ _proto._setRange = function _setRange(range) {
11042
11200
  if ((range == null ? void 0 : range.begin) && (range == null ? void 0 : range.end)) {
11043
11201
  this._rangeBeginMs = distExports$3.DateTime.toDate(range.begin).getTime();
@@ -11048,9 +11206,9 @@
11048
11206
  }
11049
11207
  this._updateVisible();
11050
11208
  };
11051
- /**
11052
- * 用区间裁剪录像片段
11053
- * @param records 全天录像片段
11209
+ /**
11210
+ * 用区间裁剪录像片段
11211
+ * @param records 全天录像片段
11054
11212
  */ _proto._setSegments = function _setSegments(records) {
11055
11213
  var _this = this;
11056
11214
  if (!this._hasRange() || !Array.isArray(records)) {
@@ -11078,9 +11236,9 @@
11078
11236
  if (force) this._currentIndex = -1;
11079
11237
  this._updateVisible();
11080
11238
  };
11081
- /**
11082
- * 按播放进度更新片段与进度
11083
- * @param currentMs 当前播放时间(毫秒)
11239
+ /**
11240
+ * 按播放进度更新片段与进度
11241
+ * @param currentMs 当前播放时间(毫秒)
11084
11242
  */ _proto._syncCurrent = function _syncCurrent(currentMs) {
11085
11243
  if (!this._hasRange()) return;
11086
11244
  var index = this._segments.findIndex(function(seg) {
@@ -11120,6 +11278,11 @@
11120
11278
  };
11121
11279
  return SegmentProgressControl;
11122
11280
  }(Control);
11281
+ /** 片段进度条拖动的是录像片段内的位置,只对回放有意义(另需移动端 + 已设置播放区间) */ SegmentProgressControl.supportedPlayTypes = [
11282
+ 'rec',
11283
+ 'cloudRec',
11284
+ 'cloudRecord'
11285
+ ];
11123
11286
 
11124
11287
  function _extends$3() {
11125
11288
  _extends$3 = Object.assign || function assign(target) {
@@ -11151,9 +11314,9 @@
11151
11314
  };
11152
11315
  return _set_prototype_of$4(o, p);
11153
11316
  }
11154
- /**
11155
- * 展示设备序列号控件
11156
- * @category Control
11317
+ /**
11318
+ * 展示设备序列号控件
11319
+ * @category Control
11157
11320
  */ var Device = /*#__PURE__*/ function(Control) {
11158
11321
  _inherits$4(Device, Control);
11159
11322
  function Device(options) {
@@ -11171,10 +11334,10 @@
11171
11334
  var _this___options_props_urlInfo, _this___options_props;
11172
11335
  this.$container.innerHTML = '<span class="' + PREFIX_CLASS$1 + "-text " + PREFIX_CLASS$1 + '-text-device">' + this._splicingString(this.__options.deviceName, (_this___options_props = this.__options.props) == null ? void 0 : (_this___options_props_urlInfo = _this___options_props.urlInfo) == null ? void 0 : _this___options_props_urlInfo.deviceSerial) + "</span>";
11173
11336
  };
11174
- /**
11175
- * 更新设备序列号
11176
- * @param deviceSerial - 设备序列号
11177
- * @param deviceName - 设备名称
11337
+ /**
11338
+ * 更新设备序列号
11339
+ * @param deviceSerial - 设备序列号
11340
+ * @param deviceName - 设备名称
11178
11341
  */ _proto.update = function update(deviceName, deviceSerial) {
11179
11342
  if (this.$container.querySelector("." + PREFIX_CLASS$1 + "-text-device")) {
11180
11343
  var $span = this.$container.querySelector("." + PREFIX_CLASS$1 + "-text-device");
@@ -11332,8 +11495,8 @@
11332
11495
  // const MobileExtend_DEFAULT_Options = {
11333
11496
  // controls: MOBILE_EXTENDS,
11334
11497
  // };
11335
- /**
11336
- * 移动端扩展
11498
+ /**
11499
+ * 移动端扩展
11337
11500
  */ var MobileExtend = /*#__PURE__*/ function(EventEmitter) {
11338
11501
  _inherits$2(MobileExtend, EventEmitter);
11339
11502
  function MobileExtend($siblingContainer) {
@@ -11410,9 +11573,9 @@
11410
11573
  return _set_prototype_of$1(o, p);
11411
11574
  }
11412
11575
  var PAUSE_DEFAULT_OPTIONS = {};
11413
- /**
11414
- * 暂停控件(仅在第一次非自动播放时可以点击播放), 防止和放大有冲突
11415
- * @category Control
11576
+ /**
11577
+ * 暂停控件(仅在第一次非自动播放时可以点击播放), 防止和放大有冲突
11578
+ * @category Control
11416
11579
  */ var Pause = /*#__PURE__*/ function(Control) {
11417
11580
  _inherits$1(Pause, Control);
11418
11581
  function Pause(options) {
@@ -11428,8 +11591,8 @@
11428
11591
  return _this;
11429
11592
  }
11430
11593
  var _proto = Pause.prototype;
11431
- /**
11432
- * 展示封面 这里不对 poster 进行缓存, 如果有值优先使用, 如果没有值优先使用 初始化传入的值
11594
+ /**
11595
+ * 展示封面 这里不对 poster 进行缓存, 如果有值优先使用, 如果没有值优先使用 初始化传入的值
11433
11596
  */ _proto.show = function show(playing, always) {
11434
11597
  var _this = this;
11435
11598
  var _this_$container_classList, _this_$container;
@@ -11474,8 +11637,8 @@
11474
11637
  }, 300);
11475
11638
  }, 10);
11476
11639
  };
11477
- /**
11478
- * 销毁
11640
+ /**
11641
+ * 销毁
11479
11642
  */ _proto.destroy = function destroy() {
11480
11643
  if (this._timer) {
11481
11644
  clearTimeout(this._timer);
@@ -11763,10 +11926,30 @@
11763
11926
  'recDropdown',
11764
11927
  'alarmMessage'
11765
11928
  ];
11766
- /**
11767
- * 渲染控件
11768
- * @param $container - 控件渲染节点
11769
- * @param btnList - 控件按钮列表
11929
+ /**
11930
+ * 校验控件是否支持当前播放类型,不支持只提示、**不阻止渲染**
11931
+ *
11932
+ * 之所以只提示:控件能否真正工作还取决于设备能力与 SDK 层实现,主题层没有足够信息
11933
+ * 直接判死;而模板可能来自开放平台配置(`getThemeData` 远程拉取)或开发者自定义的
11934
+ * `themeData`,直接隐藏会让人无从排查。
11935
+ *
11936
+ * `theme.playType` 为空串(地址判不出类型,如 rtmp / webrtc / 地址未设置)时整体跳过校验。
11937
+ *
11938
+ * @param theme - Theme
11939
+ * @param iconId - 控件 iconId
11940
+ * @param ControlClass - 控件类,读其静态 `supportedPlayTypes`
11941
+ */ function _checkPlayTypeSupport(theme, iconId, ControlClass) {
11942
+ var playType = theme.playType;
11943
+ if (!playType || ControlClass.supportsPlayType(playType)) return;
11944
+ var supported = ControlClass.supportedPlayTypes;
11945
+ // prettier-ignore
11946
+ theme.logger.warn("[" + iconId + '] control does not support playType "' + playType + '" (supported: ' + supported.join(', ') + "). It is still rendered, but may not work as expected.");
11947
+ theme.emit(EVENTS$2.control.unsupportedPlayType, iconId, playType, supported);
11948
+ }
11949
+ /**
11950
+ * 渲染控件
11951
+ * @param $container - 控件渲染节点
11952
+ * @param btnList - 控件按钮列表
11770
11953
  */ // prettier-ignore
11771
11954
  function _renderControls(theme, $container, btnList, props) {
11772
11955
  if (props === void 0) props = {};
@@ -11805,6 +11988,8 @@
11805
11988
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options["deviceOptions"]) || {}, {
11806
11989
  props: props
11807
11990
  }));
11991
+ theme.emit(EVENTS$2.control.deviceControlInit);
11992
+ _checkPlayTypeSupport(theme, item.iconId, Controls["device"]);
11808
11993
  }
11809
11994
  }
11810
11995
  continue;
@@ -11834,6 +12019,9 @@
11834
12019
  }, ((_theme_options1 = theme.options) == null ? void 0 : _theme_options1["" + item.iconId + "Options"]) || {}, {
11835
12020
  props: props
11836
12021
  }));
12022
+ // iconId 已由 Controls 查表校验过,这里必然能取到对应的初始化事件名
12023
+ theme.emit(CONTROL_INIT_EVENTS["" + item.iconId + "ControlInit"]);
12024
+ _checkPlayTypeSupport(theme, item.iconId, Controls[item.iconId]);
11837
12025
  }
11838
12026
  } else {
11839
12027
  theme.logger.warn("[" + item.iconId + "] control does not exist");
@@ -12042,7 +12230,7 @@
12042
12230
  });
12043
12231
  }
12044
12232
  // 移动端:在 rec 控件旁渲染 alarmMessage 按钮
12045
- if (theme.options.alarmMessageOptions !== null && !((_theme_controls2 = theme.controls) == null ? void 0 : _theme_controls2['alarmMessageControl'])) {
12233
+ if (theme.options.alarmMessageOptions !== null && !((_theme_controls2 = theme.controls) == null ? void 0 : _theme_controls2['alarmMessageControl']) && theme.options.sdkType === 'base') {
12046
12234
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
12047
12235
  theme.controls['alarmMessageControl'] = new Controls['alarmMessage'](_extends$1({
12048
12236
  rootContainer: theme.$container,
@@ -12057,6 +12245,8 @@
12057
12245
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options.alarmMessageOptions) || {}, {
12058
12246
  props: props
12059
12247
  }));
12248
+ theme.emit(EVENTS$2.control.alarmMessageControlInit);
12249
+ _checkPlayTypeSupport(theme, 'alarmMessage', Controls['alarmMessage']);
12060
12250
  }
12061
12251
  if ((theme.options.timeLineOptions !== null || !theme.options.disabledTimeLine) && ((_theme_options_mobileExtendOptions5 = theme.options.mobileExtendOptions) == null ? void 0 : _theme_options_mobileExtendOptions5.controls.includes('timeLine')) && _needTimeLine) {
12062
12252
  _renderTimeLine(theme, theme._mobileExtend.$content, props);
@@ -12097,6 +12287,8 @@
12097
12287
  showSectionIcon: ((_theme_options1 = theme.options) == null ? void 0 : _theme_options1["recListOptions"]) !== null ? (_ref = (_this = ((_theme_options2 = theme.options) == null ? void 0 : _theme_options2["timeLineOptions"]) || {}) == null ? void 0 : _this.showSectionIcon) != null ? _ref : true : true,
12098
12288
  props: props
12099
12289
  }));
12290
+ theme.emit(EVENTS$2.control.timeLineControlInit);
12291
+ _checkPlayTypeSupport(theme, 'timeLine', Controls['timeLine']);
12100
12292
  }
12101
12293
  };
12102
12294
  var _renderSegmentProgress = function _renderSegmentProgress(theme, container, props) {
@@ -12114,6 +12306,8 @@
12114
12306
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options["segmentProgressOptions"]) || {}, {
12115
12307
  props: props
12116
12308
  }));
12309
+ theme.emit(EVENTS$2.control.segmentProgressControlInit);
12310
+ _checkPlayTypeSupport(theme, 'segmentProgress', Controls['segmentProgress']);
12117
12311
  }
12118
12312
  };
12119
12313
  var _renderDatePicker = function _renderDatePicker(theme, container, props) {
@@ -12130,6 +12324,8 @@
12130
12324
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options["dateOptions"]) || {}, {
12131
12325
  props: props
12132
12326
  }));
12327
+ theme.emit(EVENTS$2.control.dateControlInit);
12328
+ _checkPlayTypeSupport(theme, 'date', Controls['date']);
12133
12329
  }
12134
12330
  };
12135
12331
  var _renderTimePicker = function _renderTimePicker(theme, container, props) {
@@ -12146,6 +12342,8 @@
12146
12342
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options["timeOptions"]) || {}, {
12147
12343
  props: props
12148
12344
  }));
12345
+ theme.emit(EVENTS$2.control.timeControlInit);
12346
+ _checkPlayTypeSupport(theme, 'time', Controls['time']);
12149
12347
  }
12150
12348
  };
12151
12349
  var _renderRecType = function _renderRecType(theme, container, recType, props) {
@@ -12164,31 +12362,33 @@
12164
12362
  }, ((_theme_options = theme.options) == null ? void 0 : _theme_options["recOptions"]) || {}, {
12165
12363
  props: props
12166
12364
  }));
12365
+ theme.emit(EVENTS$2.control.recControlInit);
12366
+ _checkPlayTypeSupport(theme, 'rec', Controls['rec']);
12167
12367
  }
12168
12368
  if ((_theme_controls1 = theme.controls) == null ? void 0 : _theme_controls1['recControl']) ((_theme_controls2 = theme.controls) == null ? void 0 : _theme_controls2['recControl']).addRecType(recType);
12169
12369
  };
12170
12370
 
12171
- /**
12172
- * 布局溢出(More 收纳)与响应式尺寸分档的**纯函数**模块。
12173
- *
12174
- * @remarks
12175
- * 这些函数只做「计算 / 判定」,不含任何 DOM 副作用,因此可以在没有布局引擎的环境(如 jsdom)
12176
- * 中被完整单元测试。`theme.ts` 中的命令式外壳(读取 `clientWidth`、增删 class、创建 More、
12177
- * 搬移控件)负责副作用,具体的判定逻辑全部下沉到这里。
12178
- */ /**
12179
- * 一次 classList 变更集合:需要添加与需要移除的类名。
12180
- */ /**
12181
- * 根据尺寸计算某一维度(宽或高)需要增删的响应式档位类名。
12182
- *
12183
- * 档位规则:
12184
- * - `(280, 375]` → medium
12185
- * - `(200, 280]` → small
12186
- * - `<= 200` → mini
12187
- * - 其它(> 375)→ 无档位(移除全部)
12188
- *
12189
- * @param size 尺寸(px)
12190
- * @param axis `'width'` 或 `'height'`
12191
- * @param prefix 类名前缀(如 `ezplayer`)
12371
+ /**
12372
+ * 布局溢出(More 收纳)与响应式尺寸分档的**纯函数**模块。
12373
+ *
12374
+ * @remarks
12375
+ * 这些函数只做「计算 / 判定」,不含任何 DOM 副作用,因此可以在没有布局引擎的环境(如 jsdom)
12376
+ * 中被完整单元测试。`theme.ts` 中的命令式外壳(读取 `clientWidth`、增删 class、创建 More、
12377
+ * 搬移控件)负责副作用,具体的判定逻辑全部下沉到这里。
12378
+ */ /**
12379
+ * 一次 classList 变更集合:需要添加与需要移除的类名。
12380
+ */ /**
12381
+ * 根据尺寸计算某一维度(宽或高)需要增删的响应式档位类名。
12382
+ *
12383
+ * 档位规则:
12384
+ * - `(280, 375]` → medium
12385
+ * - `(200, 280]` → small
12386
+ * - `<= 200` → mini
12387
+ * - 其它(> 375)→ 无档位(移除全部)
12388
+ *
12389
+ * @param size 尺寸(px)
12390
+ * @param axis `'width'` 或 `'height'`
12391
+ * @param prefix 类名前缀(如 `ezplayer`)
12192
12392
  */ function computeDimensionClasses(size, axis, prefix) {
12193
12393
  var medium = prefix + "-medium-" + axis;
12194
12394
  var small = prefix + "-small-" + axis;
@@ -12214,11 +12414,11 @@
12214
12414
  remove: remove
12215
12415
  };
12216
12416
  }
12217
- /**
12218
- * 计算宽、高两个维度的响应式档位类名增删集合。
12219
- * @param width 容器宽度(px)
12220
- * @param height 容器高度(px)
12221
- * @param prefix 类名前缀
12417
+ /**
12418
+ * 计算宽、高两个维度的响应式档位类名增删集合。
12419
+ * @param width 容器宽度(px)
12420
+ * @param height 容器高度(px)
12421
+ * @param prefix 类名前缀
12222
12422
  */ function computeSizeClasses(width, height, prefix) {
12223
12423
  var w = computeDimensionClasses(width, 'width', prefix);
12224
12424
  var h = computeDimensionClasses(height, 'height', prefix);
@@ -12227,34 +12427,34 @@
12227
12427
  remove: [].concat(w.remove, h.remove)
12228
12428
  };
12229
12429
  }
12230
- /**
12231
- * header 左右控件宽度之和 + 30 是否超过容器宽度 —— 超过则需要显示 More。
12430
+ /**
12431
+ * header 左右控件宽度之和 + 30 是否超过容器宽度 —— 超过则需要显示 More。
12232
12432
  */ function shouldShowHeaderMore(width, leftWidth, rightWidth) {
12233
12433
  return leftWidth + rightWidth + 30 > width;
12234
12434
  }
12235
- /**
12236
- * header 剩余空间是否 > 100 —— 足够则可以移除 More,把控件放回工具栏。
12435
+ /**
12436
+ * header 剩余空间是否 > 100 —— 足够则可以移除 More,把控件放回工具栏。
12237
12437
  */ function shouldRemoveHeaderMore(width, leftWidth, rightWidth) {
12238
12438
  return width - leftWidth - rightWidth > 100;
12239
12439
  }
12240
- /**
12241
- * footer 剩余空间是否 < 16 —— 不足则需要把控件收拢进 More。
12440
+ /**
12441
+ * footer 剩余空间是否 < 16 —— 不足则需要把控件收拢进 More。
12242
12442
  */ function shouldCollapseFooter(width, leftWidth, rightWidth) {
12243
12443
  return width - leftWidth - rightWidth < 16;
12244
12444
  }
12245
- /**
12246
- * footer 从 More 中释放控件时的展开阈值。
12247
- *
12248
- * 基准为 50;当 More 中已有控件时,加上首个控件宽度(保持与历史实现一致的运算与兜底:
12249
- * `50 + firstItemWidth || 0`)。
12250
- * @param firstItemWidth More 列表中第一个控件的宽度;未提供表示 More 为空。
12445
+ /**
12446
+ * footer 从 More 中释放控件时的展开阈值。
12447
+ *
12448
+ * 基准为 50;当 More 中已有控件时,加上首个控件宽度(保持与历史实现一致的运算与兜底:
12449
+ * `50 + firstItemWidth || 0`)。
12450
+ * @param firstItemWidth More 列表中第一个控件的宽度;未提供表示 More 为空。
12251
12451
  */ function computeFooterExpandOffset(firstItemWidth) {
12252
12452
  var base = 50;
12253
12453
  if (firstItemWidth === undefined) return base;
12254
12454
  return base + firstItemWidth || 0;
12255
12455
  }
12256
- /**
12257
- * footer 剩余空间是否足够把一个控件从 More 释放回工具栏。
12456
+ /**
12457
+ * footer 剩余空间是否足够把一个控件从 More 释放回工具栏。
12258
12458
  */ function shouldExpandFooter(width, leftWidth, rightWidth, offset) {
12259
12459
  return width - leftWidth - rightWidth > offset;
12260
12460
  }
@@ -12458,6 +12658,11 @@
12458
12658
  if (n === "Map" || n === "Set") return Array.from(n);
12459
12659
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
12460
12660
  }
12661
+ /**
12662
+ * 语言包缺 key 时的兜底文案 key
12663
+ *
12664
+ * 拼写沿用语言包中既有的 `UNKOWN_ISSUE`(少了一个 N),改名属破坏性变更,故保持原样。
12665
+ */ var UNKOWN_ISSUE_KEY = 'UNKOWN_ISSUE';
12461
12666
  var THEME_DEFAULT_OPTIONS = {
12462
12667
  dblClickFullscreen: true,
12463
12668
  language: 'zh',
@@ -12533,7 +12738,7 @@
12533
12738
  */ _this._footerMoreControl = null, /** 头部控件 @since 0.0.1 @private */ _this._header = null, /** 低部控件 @since 0.0.1 @private */ _this._footer = null, /** 回放底部时间轴 @since 0.0.1 @private */ _this._recFooter = null, /**
12534
12739
  * 移动端扩展容器, 扩展的控件渲染在指定容器以外, 仅只用端适用, 为了可以放置大的控件和方便开发接入
12535
12740
  * @private
12536
- */ _this._mobileExtend = null, /** @since 0.0.1 @private */ _this._interactiveResult = null, /** @since 0.0.1 @private */ _this._themeData = null, _this._fullscreen = null, _this.zoomUtil = null, /** 清除屏幕旋转 */ _this._cleanupOrientation = null, /** resizeObserver 监听销毁 */ _this._cleanUpResizeObserver = null, /** 容器的宽 */ _this._width = 0, /** 容器的高 */ _this._height = 0, /** 当前容器的全屏状态 true: 全屏, false: 非全屏 */ _this._isCurrentFullscreen = false, /** 屏幕旋转角度 0 | 90 | 180 | 270 */ _this._orientationAngle = 0, _this._url = '', /** 是否播放中 @private */ _this._playing = false, /** @private 加载中 */ _this._loading = false, /** 音量 */ _this._volume = 0, /** 静音 */ _this._muted = false, /** 电子放大倍数 @private */ _this._zoom = 1, /** 放大中 true: 可缩放状态,false: 禁止缩放状态(不能缩放) @private */ _this._zooming = false, /** 录制中 @private */ _this._recording = false, /** 对讲中 @private */ _this._talking = false, /** 倍速 @private */ _this._speed = 1, /** 自定清晰度 @private */ _this._videoLevelAuto = false, /** 清晰度列表 */ _this.videoLevelList = [], /** 回放片段列表 */ _this.recordList = [], /**
12741
+ */ _this._mobileExtend = null, /** @since 0.0.1 @private */ _this._interactiveResult = null, /** @since 0.0.1 @private */ _this._themeData = null, _this._fullscreen = null, _this.zoomUtil = null, /** 清除屏幕旋转 */ _this._cleanupOrientation = null, /** resizeObserver 监听销毁 */ _this._cleanUpResizeObserver = null, /** 容器的宽 */ _this._width = 0, /** 容器的高 */ _this._height = 0, /** 当前容器的全屏状态 true: 全屏, false: 非全屏 */ _this._isCurrentFullscreen = false, /** 屏幕旋转角度 0 | 90 | 180 | 270 */ _this._orientationAngle = 0, _this._url = '', /** 是否播放中 @private */ _this._playing = false, /** @private 加载中 */ _this._loading = false, /** 音量 */ _this._volume = 0, /** 静音 */ _this._muted = false, /** 正在兜底的原始 scope,非 null 表示处于兜底取值中(用于避免 customizeMissing 无限递归) */ _this._missingScope = null, /** 电子放大倍数 @private */ _this._zoom = 1, /** 放大中 true: 可缩放状态,false: 禁止缩放状态(不能缩放) @private */ _this._zooming = false, /** 录制中 @private */ _this._recording = false, /** 对讲中 @private */ _this._talking = false, /** 倍速 @private */ _this._speed = 1, /** 自定清晰度 @private */ _this._videoLevelAuto = false, /** 清晰度列表 */ _this.videoLevelList = [], /** 回放片段列表 */ _this.recordList = [], /**
12537
12742
  * 播放区间(片段分享),null 表示不约束。
12538
12743
  * 由 SDK 层在初始化时通过 props 下发,主题层据此决定日历/回放类型按钮
12539
12744
  * 是否渲染、片段进度条是否渲染。区间没有运行时变更入口。
@@ -12796,6 +13001,50 @@
12796
13001
  }
12797
13002
  };
12798
13003
  /**
13004
+ * 获取多语言文案
13005
+ *
13006
+ * 相比直接用 `theme.i18n.t()`:返回类型收窄为 `string`(底层签名是 `string | number`,
13007
+ * 调用处不必再写 `as string`)。缺失 key 的兜底由 i18n 实例上的 `customizeMissing`
13008
+ * 统一处理,因此两者在兜底行为上一致。
13009
+ * @param scope 多语言 key
13010
+ * @param variables 插值变量,如 `{ zoom: 8 }`;传 `defaultvalue` 可指定自己的兜底文案
13011
+ * @returns 文案;scope 不存在时返回「未知问题 【scope】」
13012
+ * @example
13013
+ * ```ts
13014
+ * theme.t('ZOOM_LIMIT_MAX', { zoom: 8 });
13015
+ * theme.t('NOT_EXIST_KEY'); // 未知问题 【NOT_EXIST_KEY】
13016
+ * theme.t('NOT_EXIST_KEY', { defaultvalue: '自定义兜底' }); // 自定义兜底
13017
+ * ```
13018
+ */ _proto.t = function t(scope, variables) {
13019
+ return this.i18n.t(scope, variables);
13020
+ };
13021
+ /**
13022
+ * 语言包缺 key 时的兜底文案(`customizeMissing` 的实现)
13023
+ *
13024
+ * 注意底层是把本方法的返回值「原样返回」、不再做插值,所以这里借
13025
+ * `i18n.t(UNKOWN_ISSUE)` 完成插值。而这一次取值本身也可能缺失
13026
+ * (如 `language` 传了不存在的语言,当前语言包整体不存在),
13027
+ * 那会再次回调到这里造成无限递归,因此用重入标记兜住,退化为直接返回原始 scope。
13028
+ *
13029
+ * 注:`options.locales` 与内置语言包是深合并,无法移除内置的 UNKOWN_ISSUE,
13030
+ * 因此正常配置下不会走到退化分支。
13031
+ * @param scope 缺失的多语言 key
13032
+ * @param variables 原始插值变量
13033
+ */ _proto._missingText = function _missingText(scope, variables) {
13034
+ // 兜底文案自身也缺失(如当前语言的语言包不存在):直接返回最初的 scope,
13035
+ // 而不是兜底 key 本身,否则用户看到的是 'UNKOWN_ISSUE' 这种无意义内容
13036
+ if (this._missingScope !== null) return "" + this._missingScope;
13037
+ this._missingScope = scope;
13038
+ try {
13039
+ // scope 放在最后,避免调用方传入同名变量把它覆盖掉
13040
+ return this.i18n.t(UNKOWN_ISSUE_KEY, _extends({}, variables, {
13041
+ scope: scope
13042
+ }));
13043
+ } finally{
13044
+ this._missingScope = null;
13045
+ }
13046
+ };
13047
+ /**
12799
13048
  * 销毁包括事件、控件 ...
12800
13049
  *
12801
13050
  * Destroy (including events, controls...)
@@ -12836,14 +13085,14 @@
12836
13085
  });
12837
13086
  this.$container.classList.remove("" + PREFIX_CLASS$1);
12838
13087
  this._themeData = null;
12839
- if (this.i18n) this.i18n = null;
13088
+ // if (this.i18n) this.i18n = null!; // 注释是为了防止出错
12840
13089
  this.recType = '';
12841
13090
  this.recMonth = []; // 清空数据
12842
13091
  // 重置
12843
13092
  this._videoInfo = {};
12844
13093
  this.emit(EVENTS$2.theme.destroyed);
12845
13094
  this.removeAllListeners();
12846
- if (this.logger) this.logger = null;
13095
+ // if (this.logger) this.logger = null!; // 注释是为了防止出错
12847
13096
  // 销毁后,将 destroyed 设置为 true
12848
13097
  this.destroyed = true;
12849
13098
  };
@@ -12851,6 +13100,7 @@
12851
13100
  // 私有方法
12852
13101
  // ==============================================================================================
12853
13102
  /** 初始化配置项 */ _proto._initOptions = function _initOptions(options) {
13103
+ var _this = this;
12854
13104
  if (options === void 0) options = {};
12855
13105
  var _this_options_loggerOptions, _this_options_definitionOptions_list, _this_options_definitionOptions, _this_options_videoLevelList;
12856
13106
  // 先对模块级默认配置做一次深拷贝,得到全新的嵌套对象/数组,
@@ -12903,7 +13153,13 @@
12903
13153
  });
12904
13154
  // prettier-ignore
12905
13155
  this.i18n = new I18n(locales, {
12906
- defaultLocale: language
13156
+ defaultLocale: language,
13157
+ // 语言包缺 key 时,底层默认返回 `[missing "zh.XXX" translation]`,
13158
+ // 这种占位串一旦透到 UI 上对用户毫无意义。挂在 i18n 实例上统一兜底,
13159
+ // 这样控件内直接调用 `i18n.t()` 的地方也能受益,无需逐处改造。
13160
+ customizeMissing: function customizeMissing(scope, variables) {
13161
+ return _this._missingText(scope, variables);
13162
+ }
12907
13163
  });
12908
13164
  // 默认清晰度列表
12909
13165
  if (((_this_options_definitionOptions = this.options.definitionOptions) == null ? void 0 : (_this_options_definitionOptions_list = _this_options_definitionOptions.list) == null ? void 0 : _this_options_definitionOptions_list.length) > 0 || ((_this_options_videoLevelList = this.options.videoLevelList) == null ? void 0 : _this_options_videoLevelList.length) > 0) {
@@ -13429,6 +13685,9 @@
13429
13685
  },
13430
13686
  set: function set(url) {
13431
13687
  this._url = url;
13688
+ // 地址变了回放类型也要跟着变,否则 recType / playType 会停留在上一个地址的结果,
13689
+ // 进而影响倍速档位过滤、回放类型控件激活态与控件支持性校验
13690
+ this._getRecType(url);
13432
13691
  }
13433
13692
  },
13434
13693
  {
@@ -13442,6 +13701,32 @@
13442
13701
  return {};
13443
13702
  }
13444
13703
  },
13704
+ {
13705
+ key: "playType",
13706
+ get: /**
13707
+ * 当前播放类型,由播放地址解析得出
13708
+ *
13709
+ * 取值 `'live' | 'rec' | 'cloudRec' | 'cloudRecord'`,无法判定时为空字符串 `''`。
13710
+ *
13711
+ * 与 {@link recType} 的关系:`recType` 只覆盖三种回放,直播时为空串;
13712
+ * 本 getter 把直播也纳入同一个枚举,作为「当前播放类型」的统一出口。
13713
+ *
13714
+ * @remarks 空串表示无法从地址判定(如 rtmp、webrtc、地址未设置)。
13715
+ * 此时控件支持性校验会整体跳过,避免对判不出类型的地址误报。
13716
+ * @since 3.1.7
13717
+ * ```ts
13718
+ * theme.playType // 'cloudRec'
13719
+ * ```
13720
+ */ function get() {
13721
+ var _this_urlInfo;
13722
+ // 回放三类由 _getRecType 解析(含 busType=7 → cloudRecord 的区分)
13723
+ if (this.recType) return this.recType;
13724
+ if (((_this_urlInfo = this.urlInfo) == null ? void 0 : _this_urlInfo.type) === 'live') return 'live';
13725
+ // 标准流直播:http(s) 且不走回放路径 /openpb/
13726
+ if (this._url && distExports$3.isHttp(this._url) && !this._url.includes('/openpb/')) return 'live';
13727
+ return '';
13728
+ }
13729
+ },
13445
13730
  {
13446
13731
  key: "width",
13447
13732
  get: /**
@@ -13928,7 +14213,7 @@
13928
14213
  zh: zh,
13929
14214
  en: en
13930
14215
  };
13931
- /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.6-beta.1';
14216
+ /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.7-beta.1';
13932
14217
 
13933
14218
  // 不要动这里的代码, 这个出口是为了编译成 umd 规范的文件
13934
14219