@video-supply/dahua-player 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,7 +58,9 @@ player.sdk.playRecordVideo({
58
58
  });
59
59
 
60
60
  player.sdk.playSpeed(2, 0);
61
- player.sdk.jumpPlayByDateTime('2026-03-01 12:00:00', 0);
61
+ await player.sdk.jumpPlayByDateTimeAsync('2026-03-01 12:00:00', 0, {
62
+ onDone: ({ timeSec }) => console.log('seek done', timeSec),
63
+ });
62
64
  player.sdk.setFullScreen();
63
65
  ```
64
66
 
@@ -91,7 +93,9 @@ Optional:
91
93
  - `staticPath?: string` (default `/wsplayer-gov`)
92
94
  - `sdkUrl?: string` (default `/wsplayer-gov/wsplayer.min.js`)
93
95
  - `debug?: boolean` (default `false`)
94
- - callbacks: `onReady/onPlay/onPause/onError/onDestroy`
96
+ - callbacks: `onReady/onPlay/onPause/onPlaybackTime/onError/onDestroy`
97
+ - `onPlaybackTime(payload)` is record-mode only and fires when `timeSec` changes (about once per second).
98
+ - payload: `{ timeMs, timeSec, windowIndex?, channelCode?, raw? }`
95
99
 
96
100
  Returns: `DahuaPlayerInstance`
97
101
 
@@ -107,8 +111,37 @@ Returns: `DahuaPlayerInstance`
107
111
  - Destroys the instance and releases resources.
108
112
  - Removes DOM nodes, clears timers, and releases sessionStorage shims.
109
113
  - `on(event, handler) / off(event, handler)`
110
- - Subscribe/unsubscribe events: `ready` / `play` / `pause` / `error` / `destroy`.
114
+ - Subscribe/unsubscribe events: `ready` / `play` / `pause` / `playbackTime` / `error` / `destroy`.
111
115
  - `play` payload: `{ mode?: 'real' | 'record' }`.
116
+ - `getPlaybackTimeMs(): number | null`
117
+ - Returns the latest playback time in epoch milliseconds (record mode only).
118
+ - Returns `null` before the first playback timestamp arrives.
119
+
120
+ #### Playback time example (callback + imperative getter)
121
+
122
+ ```ts
123
+ const player = DahuaPlayer.init({
124
+ container: 'player',
125
+ auth: { token: 'YOUR_DAHUA_TOKEN' },
126
+ mode: 'record',
127
+ onPlaybackTime: ({ timeMs, timeSec }) => {
128
+ console.log('playback time changed:', timeSec, timeMs);
129
+ },
130
+ });
131
+
132
+ await player.ready;
133
+
134
+ player.on('playbackTime', ({ timeMs, timeSec }) => {
135
+ console.log('playbackTime event:', timeSec, timeMs);
136
+ });
137
+
138
+ player.sdk.playRecordVideo({
139
+ startTime: Math.floor(Date.now() / 1000) - 60,
140
+ endTime: Math.floor(Date.now() / 1000),
141
+ });
142
+
143
+ console.log('getPlaybackTimeMs:', player.getPlaybackTimeMs());
144
+ ```
112
145
 
113
146
  #### SDK methods (`instance.sdk`)
114
147
 
@@ -138,6 +171,18 @@ Returns: `DahuaPlayerInstance`
138
171
  - Seeks and plays at the given datetime (record mode only).
139
172
  - `datetime` supports `YYYY-MM-DD HH:mm:ss` string, `Date`, or epoch seconds/milliseconds.
140
173
  - `index` is the window index (defaults to 0).
174
+ - `jumpPlayByDateTimeAsync(datetime: string | Date | number, index?: number, options?): Promise<{ timeMs, timeSec, windowIndex?, channelCode?, raw? }>`
175
+ - Record seek helper (record mode only).
176
+ - Resolves when playback time reaches the target (based on `getVideoFrameInfo`).
177
+ - Default timeout: 30s.
178
+ - Resolves with `{ timeMs, timeSec, windowIndex?, channelCode?, raw? }` (the matched playback-time payload).
179
+ - `options` supports two forms:
180
+ - callback form: `jumpPlayByDateTimeAsync(dt, idx, (payload) => {})` (same as `onDone`)
181
+ - object form:
182
+ - `timeoutMs?: number` (default 30000)
183
+ - `toleranceMs?: number` (default 1500)
184
+ - `onDone?: (payload) => void` (called before resolve)
185
+ - Rejects on timeout / destroyed / underlying SDK error (also reported via `onError` / `error` event).
141
186
  - `playSpeed(speed: number, index: number): void`
142
187
  - Sets record playback speed (record mode only).
143
188
  - Allowed speeds: `0.125/0.25/0.5/1/1.25/1.5/2/4/8`.
@@ -308,6 +353,8 @@ await player.ready;
308
353
  - `onReady`:内核初始化完成(不等同于播放成功)
309
354
  - `onPlay`:播放成功(包含 real/record)
310
355
  - `onPause`:暂停
356
+ - `onPlaybackTime`:回放当前时间变化(仅 mode=record,默认按秒变化触发)
357
+ - payload:`{ timeMs, timeSec, windowIndex?, channelCode?, raw? }`
311
358
  - `onError`:初始化/播放等错误
312
359
  - `onDestroy`:销毁
313
360
  - `onSdkMessage`:透出 WSPlayer 原始消息(排障用)
@@ -329,8 +376,11 @@ await instance.ready;
329
376
  - 销毁播放器实例并释放资源
330
377
  - 会移除 DOM、清理定时器、释放 sessionStorage shim
331
378
  - `instance.on(event, handler) / instance.off(event, handler)`
332
- - 订阅/取消订阅事件:`ready` / `play` / `pause` / `error` / `destroy`
379
+ - 订阅/取消订阅事件:`ready` / `play` / `pause` / `playbackTime` / `error` / `destroy`
333
380
  - `play` 事件 payload:`{ mode?: 'real' | 'record' }`
381
+ - `instance.getPlaybackTimeMs(): number | null`
382
+ - 主动获取最近一次收到的“当前回放时间(epoch ms)”
383
+ - 仅 mode=record 时有意义;未收到回放时间前返回 null
334
384
 
335
385
  `instance.sdk`:
336
386
 
package/README.zh-CN.md CHANGED
@@ -107,6 +107,14 @@ await player.ready;
107
107
  - `onReady`:内核初始化完成(不等同于播放成功)
108
108
  - `onPlay`:播放成功(包含 real/record)
109
109
  - `onPause`:暂停
110
+ - `onPlaybackTime`:回放当前时间变化(仅 mode=record,默认按秒变化触发)
111
+ - 触发时机:底层 SDK 会高频推送回放帧信息;库内部只在 `timeSec` 变化时对外触发(约 1 次/秒)
112
+ - payload:`{ timeMs, timeSec, windowIndex?, channelCode?, raw? }`
113
+ - `timeMs`:当前回放时间(epoch 毫秒)
114
+ - `timeSec`:当前回放时间(epoch 秒)
115
+ - `windowIndex`:窗口索引(可选)
116
+ - `channelCode`:通道编码(可选)
117
+ - `raw`:原始 SDK data(可选,用于排障)
110
118
  - `onError`:初始化/播放等错误
111
119
  - `onDestroy`:销毁
112
120
  - `onSdkMessage`:透出 WSPlayer 原始消息(排障用)
@@ -128,8 +136,38 @@ await instance.ready;
128
136
  - 销毁播放器实例并释放资源
129
137
  - 会移除 DOM、清理定时器、释放 sessionStorage shim
130
138
  - `instance.on(event, handler) / instance.off(event, handler)`
131
- - 订阅/取消订阅事件:`ready` / `play` / `pause` / `error` / `destroy`
139
+ - 订阅/取消订阅事件:`ready` / `play` / `pause` / `playbackTime` / `error` / `destroy`
132
140
  - `play` 事件 payload:`{ mode?: 'real' | 'record' }`
141
+ - `instance.getPlaybackTimeMs(): number | null`
142
+ - 主动获取最近一次收到的“当前回放时间(epoch ms)”
143
+ - 仅 mode=record 时有意义;未收到回放时间前返回 null
144
+
145
+ ### 回放时间示例(回调 + 主动获取)
146
+
147
+ ```ts
148
+ const player = DahuaPlayer.init({
149
+ container: 'player',
150
+ auth: { token: 'YOUR_DAHUA_TOKEN' },
151
+ mode: 'record',
152
+ onPlaybackTime: ({ timeMs, timeSec, windowIndex, channelCode }) => {
153
+ console.log('回放时间变化(秒级触发):', timeSec, timeMs, windowIndex, channelCode);
154
+ },
155
+ });
156
+
157
+ await player.ready;
158
+
159
+ player.on('playbackTime', ({ timeMs, timeSec }) => {
160
+ console.log('playbackTime 事件:', timeSec, timeMs);
161
+ });
162
+
163
+ player.sdk.playRecordVideo({
164
+ startTime: Math.floor(Date.now() / 1000) - 60,
165
+ endTime: Math.floor(Date.now() / 1000),
166
+ });
167
+
168
+ const t = player.getPlaybackTimeMs();
169
+ console.log('主动获取(可能为null):', t);
170
+ ```
133
171
 
134
172
  `instance.sdk`:
135
173
 
@@ -163,6 +201,18 @@ await instance.ready;
163
201
  - `Date`
164
202
  - `number`:时间戳(秒或毫秒,内部会自动兼容)
165
203
  - `index`:窗口索引(默认窗口 0)
204
+ - `jumpPlayByDateTimeAsync(datetime: string | Date | number, index?: number, options?): Promise<{ timeMs, timeSec, windowIndex?, channelCode?, raw? }>`
205
+ - 录像跳转播放(仅 `mode=record` 可用)
206
+ - 内部基于回放时间(`getVideoFrameInfo`)判断跳转是否完成
207
+ - 默认超时:30 秒
208
+ - 返回:Promise resolve 为 `{ timeMs, timeSec, windowIndex?, channelCode?, raw? }`(命中目标时间点时的回放时间 payload)
209
+ - `options` 支持两种写法:
210
+ - 直接传回调函数:`jumpPlayByDateTimeAsync(dt, idx, (payload) => {})`(等价于 `onDone`)
211
+ - 传配置对象:
212
+ - `timeoutMs?: number`:超时时间(默认 30000)
213
+ - `toleranceMs?: number`:时间命中容差(默认 1500)
214
+ - `onDone?: (payload) => void`:跳转完成回调(在 Promise resolve 前触发)
215
+ - reject 场景:超时 / 播放器销毁 / SDK 抛错(会触发 `onError`/`error` 事件)
166
216
  - `playSpeed(speed: number, index: number): void`
167
217
  - 设置录像回放倍速(仅 `mode=record` 可用)
168
218
  - `speed` 支持:`0.125/0.25/0.5/1/1.25/1.5/2/4/8`
@@ -198,5 +248,7 @@ player.sdk.playRecordVideo({
198
248
  });
199
249
 
200
250
  player.sdk.playSpeed(2, 0);
201
- player.sdk.jumpPlayByDateTime('2026-03-01 12:00:00', 0);
251
+ await player.sdk.jumpPlayByDateTimeAsync('2026-03-01 12:00:00', 0, {
252
+ onDone: ({ timeSec }) => console.log('跳转完成', timeSec),
253
+ });
202
254
  ```
package/dist/index.cjs CHANGED
@@ -741,6 +741,64 @@ var PlayerAdapter = class {
741
741
  }
742
742
  };
743
743
 
744
+ // src/sdk/PlaybackTime.ts
745
+ function extractPlaybackTimeMsFromFrameInfo(data) {
746
+ const vf = data && typeof data === "object" ? data.videoFrameInfo : void 0;
747
+ const utcMsRaw = vf && typeof vf === "object" ? vf.utcTimeStamp : void 0;
748
+ const secRaw = data && typeof data === "object" ? data.timeStamp : void 0;
749
+ const utcMs = typeof utcMsRaw === "number" && Number.isFinite(utcMsRaw) ? Math.floor(utcMsRaw) : null;
750
+ const sec = typeof secRaw === "number" && Number.isFinite(secRaw) ? Math.floor(secRaw) : null;
751
+ const baseMs = utcMs != null ? utcMs : sec != null ? sec * 1e3 : null;
752
+ if (baseMs == null) return null;
753
+ const shouldApplySubMs = utcMs == null ? true : utcMs % 1e3 === 0;
754
+ if (!shouldApplySubMs) return baseMs;
755
+ const nTimeStampRaw = vf && typeof vf === "object" ? vf.nTimeStamp : void 0;
756
+ if (typeof nTimeStampRaw !== "number" || !Number.isFinite(nTimeStampRaw)) return baseMs;
757
+ const sub = (Math.floor(nTimeStampRaw) % 1e3 + 1e3) % 1e3;
758
+ return baseMs + sub;
759
+ }
760
+ function buildPlaybackTimePayloadFromFrameInfo(data) {
761
+ var _a;
762
+ const timeMs = extractPlaybackTimeMsFromFrameInfo(data);
763
+ if (timeMs == null) return null;
764
+ const secRaw = data && typeof data === "object" ? data.timeStamp : void 0;
765
+ const timeSec = typeof secRaw === "number" && Number.isFinite(secRaw) ? Math.floor(secRaw) : Math.floor(timeMs / 1e3);
766
+ const idxRaw = data && typeof data === "object" ? data.selectIndex : void 0;
767
+ const windowIndex = typeof idxRaw === "number" && Number.isFinite(idxRaw) ? Math.floor(idxRaw) : void 0;
768
+ const channelCodeRaw = data && typeof data === "object" ? (_a = data.channelData) == null ? void 0 : _a.channelCode : void 0;
769
+ const channelCode = typeof channelCodeRaw === "string" ? channelCodeRaw : void 0;
770
+ return { timeMs, timeSec, windowIndex, channelCode, raw: data };
771
+ }
772
+
773
+ // src/sdk/DateTime.ts
774
+ function parseDateTimeToMs(datetime) {
775
+ if (typeof datetime === "number") {
776
+ if (!Number.isFinite(datetime)) return NaN;
777
+ return Math.floor(datetime > 1e12 ? datetime : datetime * 1e3);
778
+ }
779
+ if (datetime instanceof Date) {
780
+ const ms2 = datetime.getTime();
781
+ return Number.isFinite(ms2) ? Math.floor(ms2) : NaN;
782
+ }
783
+ const raw = (datetime || "").trim();
784
+ if (!raw) return NaN;
785
+ const v = raw.includes("T") ? raw : raw.replace(" ", "T");
786
+ const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})$/.exec(v);
787
+ if (!m) {
788
+ const ms2 = new Date(v).getTime();
789
+ return Number.isFinite(ms2) ? Math.floor(ms2) : NaN;
790
+ }
791
+ const y = Number(m[1]);
792
+ const mon = Number(m[2]);
793
+ const d = Number(m[3]);
794
+ const hh = Number(m[4]);
795
+ const mm = Number(m[5]);
796
+ const ss = Number(m[6]);
797
+ const dt = new Date(y, mon - 1, d, hh, mm, ss, 0);
798
+ const ms = dt.getTime();
799
+ return Number.isFinite(ms) ? Math.floor(ms) : NaN;
800
+ }
801
+
744
802
  // src/DahuaPlayer.ts
745
803
  function normalizeStaticPath(path) {
746
804
  const raw = (path || "").trim();
@@ -912,6 +970,10 @@ var DahuaPlayer = class {
912
970
  };
913
971
  let readyReject = () => {
914
972
  };
973
+ let lastPlaybackTimeMs = null;
974
+ let lastEmittedPlaybackTimeSec = null;
975
+ const jumpWaiters = [];
976
+ let jumpWaiterId = 0;
915
977
  const safeOnError = (e) => {
916
978
  var _a2;
917
979
  try {
@@ -920,6 +982,29 @@ var DahuaPlayer = class {
920
982
  }
921
983
  emit(listeners, "error", e);
922
984
  };
985
+ const createDestroyedError = () => new DahuaPlayerError({
986
+ code: "DESTROYED" /* DESTROYED */,
987
+ message: "destroyed",
988
+ userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
989
+ });
990
+ const createNotReadyError = () => new DahuaPlayerError({
991
+ code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
992
+ message: "player not ready",
993
+ userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
994
+ });
995
+ const requireAdapter = () => {
996
+ if (destroyed) {
997
+ const err = createDestroyedError();
998
+ safeOnError(err);
999
+ throw err;
1000
+ }
1001
+ if (!adapter) {
1002
+ const err = createNotReadyError();
1003
+ safeOnError(err);
1004
+ throw err;
1005
+ }
1006
+ return adapter;
1007
+ };
923
1008
  const tryAutoPlay = () => {
924
1009
  if (!autoPlay) return;
925
1010
  if (mode === "real") {
@@ -993,11 +1078,41 @@ var DahuaPlayer = class {
993
1078
  playerOptions: opts.playerOptions,
994
1079
  debug: opts.debug,
995
1080
  onMessage: (type, data) => {
996
- var _a3;
1081
+ var _a3, _b2, _c2;
997
1082
  try {
998
1083
  (_a3 = opts.onSdkMessage) == null ? void 0 : _a3.call(opts, type, data);
999
1084
  } catch {
1000
1085
  }
1086
+ if (type === "getVideoFrameInfo") {
1087
+ const payload = buildPlaybackTimePayloadFromFrameInfo(data);
1088
+ if (!payload) return;
1089
+ lastPlaybackTimeMs = payload.timeMs;
1090
+ if (payload.timeSec !== lastEmittedPlaybackTimeSec) {
1091
+ lastEmittedPlaybackTimeSec = payload.timeSec;
1092
+ try {
1093
+ (_b2 = opts.onPlaybackTime) == null ? void 0 : _b2.call(opts, payload);
1094
+ } catch {
1095
+ }
1096
+ emit(listeners, "playbackTime", payload);
1097
+ }
1098
+ if (jumpWaiters.length > 0) {
1099
+ for (let i = jumpWaiters.length - 1; i >= 0; i--) {
1100
+ const w = jumpWaiters[i];
1101
+ if (typeof w.index === "number" && typeof payload.windowIndex === "number" && w.index !== payload.windowIndex) {
1102
+ continue;
1103
+ }
1104
+ if (Math.abs(payload.timeMs - w.targetMs) <= w.toleranceMs) {
1105
+ jumpWaiters.splice(i, 1);
1106
+ clearTimeout(w.timeoutTimer);
1107
+ try {
1108
+ (_c2 = w.onDone) == null ? void 0 : _c2.call(w, payload);
1109
+ } catch {
1110
+ }
1111
+ w.resolve(payload);
1112
+ }
1113
+ }
1114
+ }
1115
+ }
1001
1116
  },
1002
1117
  emit: (event, payload) => {
1003
1118
  var _a3, _b2, _c2;
@@ -1034,6 +1149,13 @@ var DahuaPlayer = class {
1034
1149
  }
1035
1150
  if (event === "error") {
1036
1151
  const msg = formatUserMessage(payload, "\u64AD\u653E\u5931\u8D25");
1152
+ if (jumpWaiters.length > 0) {
1153
+ const waiters = jumpWaiters.splice(0, jumpWaiters.length);
1154
+ for (const w of waiters) {
1155
+ clearTimeout(w.timeoutTimer);
1156
+ w.reject(payload);
1157
+ }
1158
+ }
1037
1159
  if (payload instanceof DahuaPlayerError) {
1038
1160
  const initCodes = /* @__PURE__ */ new Set([
1039
1161
  "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
@@ -1065,6 +1187,7 @@ var DahuaPlayer = class {
1065
1187
  readyReject(err);
1066
1188
  }
1067
1189
  })();
1190
+ const getPlaybackTimeMs = () => lastPlaybackTimeMs;
1068
1191
  const instance = {
1069
1192
  id,
1070
1193
  ready,
@@ -1077,6 +1200,7 @@ var DahuaPlayer = class {
1077
1200
  if (!adapter) return;
1078
1201
  adapter.pause();
1079
1202
  },
1203
+ getPlaybackTimeMs,
1080
1204
  /**
1081
1205
  * 销毁播放器实例并释放资源。
1082
1206
  *
@@ -1090,6 +1214,14 @@ var DahuaPlayer = class {
1090
1214
  if (destroyed) return;
1091
1215
  destroyed = true;
1092
1216
  clearTimeout(readyTimer);
1217
+ if (jumpWaiters.length > 0) {
1218
+ const waiters = jumpWaiters.splice(0, jumpWaiters.length);
1219
+ const err = createDestroyedError();
1220
+ for (const w of waiters) {
1221
+ clearTimeout(w.timeoutTimer);
1222
+ w.reject(err);
1223
+ }
1224
+ }
1093
1225
  if (transientOverlayTimer) {
1094
1226
  clearTimeout(transientOverlayTimer);
1095
1227
  transientOverlayTimer = null;
@@ -1130,26 +1262,9 @@ var DahuaPlayer = class {
1130
1262
  sdk: {
1131
1263
  getRaw: () => adapter == null ? void 0 : adapter.getRaw(),
1132
1264
  callRaw: (method, ...args) => {
1133
- if (destroyed) {
1134
- const err = new DahuaPlayerError({
1135
- code: "DESTROYED" /* DESTROYED */,
1136
- message: "destroyed",
1137
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1138
- });
1139
- safeOnError(err);
1140
- throw err;
1141
- }
1142
- if (!adapter) {
1143
- const err = new DahuaPlayerError({
1144
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1145
- message: "player not ready",
1146
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1147
- });
1148
- safeOnError(err);
1149
- throw err;
1150
- }
1265
+ const ad = requireAdapter();
1151
1266
  try {
1152
- return adapter.callRaw(method, ...args);
1267
+ return ad.callRaw(method, ...args);
1153
1268
  } catch (e) {
1154
1269
  const err = toDahuaError(e, {
1155
1270
  code: "PLAY_FAILED" /* PLAY_FAILED */,
@@ -1161,27 +1276,10 @@ var DahuaPlayer = class {
1161
1276
  }
1162
1277
  },
1163
1278
  playRealVideo: (opt) => {
1164
- if (destroyed) {
1165
- const err = new DahuaPlayerError({
1166
- code: "DESTROYED" /* DESTROYED */,
1167
- message: "destroyed",
1168
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1169
- });
1170
- safeOnError(err);
1171
- throw err;
1172
- }
1173
- if (!adapter) {
1174
- const err = new DahuaPlayerError({
1175
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1176
- message: "player not ready",
1177
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1178
- });
1179
- safeOnError(err);
1180
- throw err;
1181
- }
1279
+ const ad = requireAdapter();
1182
1280
  showLoading("\u52A0\u8F7D\u89C6\u9891\u4E2D\u2026");
1183
1281
  try {
1184
- adapter.playRealVideo(opt);
1282
+ ad.playRealVideo(opt);
1185
1283
  } catch (e) {
1186
1284
  setLoading(false);
1187
1285
  const err = toDahuaError(e, {
@@ -1194,27 +1292,10 @@ var DahuaPlayer = class {
1194
1292
  }
1195
1293
  },
1196
1294
  playRecordVideo: (opt) => {
1197
- if (destroyed) {
1198
- const err = new DahuaPlayerError({
1199
- code: "DESTROYED" /* DESTROYED */,
1200
- message: "destroyed",
1201
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1202
- });
1203
- safeOnError(err);
1204
- throw err;
1205
- }
1206
- if (!adapter) {
1207
- const err = new DahuaPlayerError({
1208
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1209
- message: "player not ready",
1210
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1211
- });
1212
- safeOnError(err);
1213
- throw err;
1214
- }
1295
+ const ad = requireAdapter();
1215
1296
  showLoading("\u52A0\u8F7D\u5F55\u50CF\u4E2D\u2026");
1216
1297
  try {
1217
- adapter.playRecordVideo(opt);
1298
+ ad.playRecordVideo(opt);
1218
1299
  } catch (e) {
1219
1300
  setLoading(false);
1220
1301
  const err = toDahuaError(e, {
@@ -1230,26 +1311,9 @@ var DahuaPlayer = class {
1230
1311
  play: (windowIndex) => adapter == null ? void 0 : adapter.playWindow(windowIndex),
1231
1312
  close: (windowIndex) => adapter == null ? void 0 : adapter.closeWindow(windowIndex),
1232
1313
  setPlayerNum: (n) => {
1233
- if (destroyed) {
1234
- const err = new DahuaPlayerError({
1235
- code: "DESTROYED" /* DESTROYED */,
1236
- message: "destroyed",
1237
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1238
- });
1239
- safeOnError(err);
1240
- throw err;
1241
- }
1242
- if (!adapter) {
1243
- const err = new DahuaPlayerError({
1244
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1245
- message: "player not ready",
1246
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1247
- });
1248
- safeOnError(err);
1249
- throw err;
1250
- }
1314
+ const ad = requireAdapter();
1251
1315
  try {
1252
- adapter.setPlayerNum(n);
1316
+ ad.setPlayerNum(n);
1253
1317
  } catch (e) {
1254
1318
  const err = toDahuaError(e, {
1255
1319
  code: "PLAY_FAILED" /* PLAY_FAILED */,
@@ -1261,28 +1325,84 @@ var DahuaPlayer = class {
1261
1325
  }
1262
1326
  },
1263
1327
  jumpPlayByDateTime: (datetime, index) => {
1264
- if (destroyed) {
1265
- const err = new DahuaPlayerError({
1266
- code: "DESTROYED" /* DESTROYED */,
1267
- message: "destroyed",
1268
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1328
+ const ad = requireAdapter();
1329
+ showLoading("\u8DF3\u8F6C\u4E2D\u2026");
1330
+ try {
1331
+ ad.jumpPlayByDateTime(datetime, index);
1332
+ } catch (e) {
1333
+ setLoading(false);
1334
+ const err = toDahuaError(e, {
1335
+ code: "PLAY_FAILED" /* PLAY_FAILED */,
1336
+ message: "jumpPlayByDateTime failed",
1337
+ userMessage: "\u5F55\u50CF\u8DF3\u8F6C\u64AD\u653E\u5931\u8D25"
1269
1338
  });
1270
1339
  safeOnError(err);
1271
1340
  throw err;
1272
1341
  }
1273
- if (!adapter) {
1342
+ },
1343
+ jumpPlayByDateTimeAsync: (datetime, index, options2) => {
1344
+ let ad;
1345
+ try {
1346
+ ad = requireAdapter();
1347
+ } catch (e) {
1348
+ return Promise.reject(e);
1349
+ }
1350
+ const onDone = typeof options2 === "function" ? options2 : options2 == null ? void 0 : options2.onDone;
1351
+ const timeoutMs = typeof options2 === "object" && options2 && Number.isFinite(options2.timeoutMs) ? Math.floor(Number(options2.timeoutMs)) : 3e4;
1352
+ const toleranceMs = typeof options2 === "object" && options2 && Number.isFinite(options2.toleranceMs) ? Math.floor(Number(options2.toleranceMs)) : 1500;
1353
+ const targetMs = parseDateTimeToMs(datetime);
1354
+ if (!Number.isFinite(targetMs)) {
1274
1355
  const err = new DahuaPlayerError({
1275
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1276
- message: "player not ready",
1277
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1356
+ code: "PLAY_FAILED" /* PLAY_FAILED */,
1357
+ message: "invalid datetime",
1358
+ userMessage: "\u8DF3\u8F6C\u65F6\u95F4\u683C\u5F0F\u4E0D\u5408\u6CD5",
1359
+ cause: { datetime }
1278
1360
  });
1279
1361
  safeOnError(err);
1280
- throw err;
1362
+ return Promise.reject(err);
1281
1363
  }
1282
1364
  showLoading("\u8DF3\u8F6C\u4E2D\u2026");
1365
+ const idx = typeof index === "number" ? Math.floor(index) : void 0;
1366
+ const id2 = ++jumpWaiterId;
1367
+ const p = new Promise((resolve, reject) => {
1368
+ const timeoutTimer = setTimeout(() => {
1369
+ const at = jumpWaiters.findIndex((w) => w.id === id2);
1370
+ if (at >= 0) jumpWaiters.splice(at, 1);
1371
+ setLoading(false);
1372
+ const err = new DahuaPlayerError({
1373
+ code: "PLAY_FAILED" /* PLAY_FAILED */,
1374
+ message: "jumpPlayByDateTimeAsync timeout",
1375
+ userMessage: "\u5F55\u50CF\u8DF3\u8F6C\u8D85\u65F6",
1376
+ cause: { timeoutMs, datetime, index: idx }
1377
+ });
1378
+ safeOnError(err);
1379
+ reject(err);
1380
+ }, Math.max(0, timeoutMs));
1381
+ jumpWaiters.push({
1382
+ id: id2,
1383
+ targetMs,
1384
+ toleranceMs: Math.max(0, toleranceMs),
1385
+ index: idx,
1386
+ timeoutTimer,
1387
+ onDone,
1388
+ resolve: (payload) => {
1389
+ setLoading(false);
1390
+ resolve(payload);
1391
+ },
1392
+ reject: (e) => {
1393
+ setLoading(false);
1394
+ reject(e);
1395
+ }
1396
+ });
1397
+ });
1283
1398
  try {
1284
- adapter.jumpPlayByDateTime(datetime, index);
1399
+ ad.jumpPlayByDateTime(datetime, idx);
1285
1400
  } catch (e) {
1401
+ const at = jumpWaiters.findIndex((w) => w.id === id2);
1402
+ if (at >= 0) {
1403
+ const w = jumpWaiters.splice(at, 1)[0];
1404
+ clearTimeout(w.timeoutTimer);
1405
+ }
1286
1406
  setLoading(false);
1287
1407
  const err = toDahuaError(e, {
1288
1408
  code: "PLAY_FAILED" /* PLAY_FAILED */,
@@ -1290,30 +1410,14 @@ var DahuaPlayer = class {
1290
1410
  userMessage: "\u5F55\u50CF\u8DF3\u8F6C\u64AD\u653E\u5931\u8D25"
1291
1411
  });
1292
1412
  safeOnError(err);
1293
- throw err;
1413
+ return Promise.reject(err);
1294
1414
  }
1415
+ return p;
1295
1416
  },
1296
1417
  playSpeed: (speed, index) => {
1297
- if (destroyed) {
1298
- const err = new DahuaPlayerError({
1299
- code: "DESTROYED" /* DESTROYED */,
1300
- message: "destroyed",
1301
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1302
- });
1303
- safeOnError(err);
1304
- throw err;
1305
- }
1306
- if (!adapter) {
1307
- const err = new DahuaPlayerError({
1308
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1309
- message: "player not ready",
1310
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1311
- });
1312
- safeOnError(err);
1313
- throw err;
1314
- }
1418
+ const ad = requireAdapter();
1315
1419
  try {
1316
- adapter.playSpeed(speed, index);
1420
+ ad.playSpeed(speed, index);
1317
1421
  } catch (e) {
1318
1422
  const err = toDahuaError(e, {
1319
1423
  code: "PLAY_FAILED" /* PLAY_FAILED */,
@@ -1325,26 +1429,9 @@ var DahuaPlayer = class {
1325
1429
  }
1326
1430
  },
1327
1431
  setFullScreen: () => {
1328
- if (destroyed) {
1329
- const err = new DahuaPlayerError({
1330
- code: "DESTROYED" /* DESTROYED */,
1331
- message: "destroyed",
1332
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1333
- });
1334
- safeOnError(err);
1335
- throw err;
1336
- }
1337
- if (!adapter) {
1338
- const err = new DahuaPlayerError({
1339
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1340
- message: "player not ready",
1341
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1342
- });
1343
- safeOnError(err);
1344
- throw err;
1345
- }
1432
+ const ad = requireAdapter();
1346
1433
  try {
1347
- adapter.setFullScreen();
1434
+ ad.setFullScreen();
1348
1435
  return;
1349
1436
  } catch {
1350
1437
  }
@@ -1362,26 +1449,9 @@ var DahuaPlayer = class {
1362
1449
  void req.call(el);
1363
1450
  },
1364
1451
  setExitFullScreen: () => {
1365
- if (destroyed) {
1366
- const err2 = new DahuaPlayerError({
1367
- code: "DESTROYED" /* DESTROYED */,
1368
- message: "destroyed",
1369
- userMessage: "\u64AD\u653E\u5668\u5DF2\u9500\u6BC1"
1370
- });
1371
- safeOnError(err2);
1372
- throw err2;
1373
- }
1374
- if (!adapter) {
1375
- const err2 = new DahuaPlayerError({
1376
- code: "SDK_INIT_FAILED" /* SDK_INIT_FAILED */,
1377
- message: "player not ready",
1378
- userMessage: "\u64AD\u653E\u5668\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7B49\u5F85 ready \u540E\u518D\u8C03\u7528"
1379
- });
1380
- safeOnError(err2);
1381
- throw err2;
1382
- }
1452
+ const ad = requireAdapter();
1383
1453
  try {
1384
- adapter.setExitFullScreen();
1454
+ ad.setExitFullScreen();
1385
1455
  return;
1386
1456
  } catch {
1387
1457
  }