@daboss2003/liveness-web 1.0.5 → 1.0.6

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/engine.d.ts CHANGED
@@ -72,14 +72,15 @@ export declare class LivenessEngine {
72
72
  private lastDetectTs;
73
73
  private lastOvalState;
74
74
  private stepSoundPlayedForCurrentStep;
75
- private currentStepAudio;
76
- private currentStepAudioCleanup;
75
+ private currentAudio;
76
+ private currentAudioCleanup;
77
+ private currentAudioToken;
77
78
  private sessionTimeoutId;
78
79
  constructor(opts: LivenessOptions);
79
80
  private playSound;
80
81
  private getSoundUrl;
81
82
  private playStepSound;
82
- private stopStepSound;
83
+ private stopAllSounds;
83
84
  private clearSessionTimeout;
84
85
  private playGoodSound;
85
86
  private playCaptureSound;
package/dist/engine.js CHANGED
@@ -174,22 +174,36 @@ export class LivenessEngine {
174
174
  this.lastDetectTs = -1;
175
175
  this.lastOvalState = null;
176
176
  this.stepSoundPlayedForCurrentStep = false;
177
- this.currentStepAudio = null;
178
- this.currentStepAudioCleanup = null;
177
+ this.currentAudio = null;
178
+ this.currentAudioCleanup = null;
179
+ this.currentAudioToken = 0;
179
180
  this.sessionTimeoutId = null;
180
181
  }
181
182
  playSound(url, onEnded) {
183
+ this.stopAllSounds();
184
+ const token = ++this.currentAudioToken;
182
185
  const a = new Audio(url);
183
- if (onEnded) {
184
- const done = () => {
185
- a.removeEventListener("ended", done);
186
- a.removeEventListener("error", done);
187
- onEnded();
188
- };
189
- a.addEventListener("ended", done);
190
- a.addEventListener("error", done);
191
- }
192
- a.play().catch(() => onEnded?.());
186
+ a.preload = "auto";
187
+ const done = () => {
188
+ if (token !== this.currentAudioToken)
189
+ return;
190
+ a.removeEventListener("ended", done);
191
+ a.removeEventListener("error", done);
192
+ if (this.currentAudio === a)
193
+ this.currentAudio = null;
194
+ if (this.currentAudioCleanup === cleanup)
195
+ this.currentAudioCleanup = null;
196
+ onEnded?.();
197
+ };
198
+ const cleanup = () => {
199
+ a.removeEventListener("ended", done);
200
+ a.removeEventListener("error", done);
201
+ };
202
+ this.currentAudio = a;
203
+ this.currentAudioCleanup = cleanup;
204
+ a.addEventListener("ended", done);
205
+ a.addEventListener("error", done);
206
+ a.play().catch(() => done());
193
207
  }
194
208
  getSoundUrl(key) {
195
209
  const s = this.opts.sounds;
@@ -211,34 +225,17 @@ export class LivenessEngine {
211
225
  const url = this.getSoundUrl(key);
212
226
  if (!url)
213
227
  return;
214
- this.stopStepSound();
215
- const a = new Audio(url);
216
- const done = () => {
217
- a.removeEventListener("ended", done);
218
- a.removeEventListener("error", done);
219
- if (this.currentStepAudio === a)
220
- this.currentStepAudio = null;
221
- if (this.currentStepAudioCleanup === cleanup)
222
- this.currentStepAudioCleanup = null;
223
- };
224
- const cleanup = () => {
225
- a.removeEventListener("ended", done);
226
- a.removeEventListener("error", done);
227
- };
228
- this.currentStepAudio = a;
229
- this.currentStepAudioCleanup = cleanup;
230
- a.addEventListener("ended", done);
231
- a.addEventListener("error", done);
232
- a.play().catch(() => done());
228
+ this.playSound(url);
233
229
  }
234
- stopStepSound() {
235
- if (this.currentStepAudio) {
236
- this.currentStepAudio.pause();
237
- this.currentStepAudio.currentTime = 0;
230
+ stopAllSounds() {
231
+ this.currentAudioToken += 1;
232
+ if (this.currentAudio) {
233
+ this.currentAudio.pause();
234
+ this.currentAudio.currentTime = 0;
238
235
  }
239
- this.currentStepAudioCleanup?.();
240
- this.currentStepAudioCleanup = null;
241
- this.currentStepAudio = null;
236
+ this.currentAudioCleanup?.();
237
+ this.currentAudioCleanup = null;
238
+ this.currentAudio = null;
242
239
  }
243
240
  clearSessionTimeout() {
244
241
  if (this.sessionTimeoutId != null) {
@@ -292,7 +289,7 @@ export class LivenessEngine {
292
289
  stopDetectionOnly() {
293
290
  this.running = false;
294
291
  this.clearSessionTimeout();
295
- this.stopStepSound();
292
+ this.stopAllSounds();
296
293
  if (this.rafId != null) {
297
294
  cancelAnimationFrame(this.rafId);
298
295
  this.rafId = null;
@@ -532,7 +529,7 @@ export class LivenessEngine {
532
529
  return "none";
533
530
  }
534
531
  advanceStep(now) {
535
- this.stopStepSound();
532
+ this.stopAllSounds();
536
533
  this.stepIndex += 1;
537
534
  if (this.stepIndex >= this.steps.length) {
538
535
  this.playGoodSound();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daboss2003/liveness-web",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Web liveness detection using MediaPipe Face Landmarker (CDN)",
5
5
  "keywords": [
6
6
  "liveness",
package/src/engine.ts CHANGED
@@ -260,24 +260,35 @@ export class LivenessEngine {
260
260
  private lastDetectTs = -1;
261
261
  private lastOvalState: boolean | null = null;
262
262
  private stepSoundPlayedForCurrentStep = false;
263
- private currentStepAudio: HTMLAudioElement | null = null;
264
- private currentStepAudioCleanup: (() => void) | null = null;
263
+ private currentAudio: HTMLAudioElement | null = null;
264
+ private currentAudioCleanup: (() => void) | null = null;
265
+ private currentAudioToken = 0;
265
266
  private sessionTimeoutId: number | null = null;
266
267
 
267
268
  constructor(private opts: LivenessOptions) {}
268
269
 
269
270
  private playSound(url: string, onEnded?: () => void): void {
271
+ this.stopAllSounds();
272
+ const token = ++this.currentAudioToken;
270
273
  const a = new Audio(url);
271
- if (onEnded) {
272
- const done = () => {
273
- a.removeEventListener("ended", done);
274
- a.removeEventListener("error", done);
275
- onEnded();
276
- };
277
- a.addEventListener("ended", done);
278
- a.addEventListener("error", done);
279
- }
280
- a.play().catch(() => onEnded?.());
274
+ a.preload = "auto";
275
+ const done = () => {
276
+ if (token !== this.currentAudioToken) return;
277
+ a.removeEventListener("ended", done);
278
+ a.removeEventListener("error", done);
279
+ if (this.currentAudio === a) this.currentAudio = null;
280
+ if (this.currentAudioCleanup === cleanup) this.currentAudioCleanup = null;
281
+ onEnded?.();
282
+ };
283
+ const cleanup = () => {
284
+ a.removeEventListener("ended", done);
285
+ a.removeEventListener("error", done);
286
+ };
287
+ this.currentAudio = a;
288
+ this.currentAudioCleanup = cleanup;
289
+ a.addEventListener("ended", done);
290
+ a.addEventListener("error", done);
291
+ a.play().catch(() => done());
281
292
  }
282
293
 
283
294
  private getSoundUrl(key: string): string | undefined {
@@ -296,33 +307,18 @@ export class LivenessEngine {
296
307
  if (!key) return;
297
308
  const url = this.getSoundUrl(key);
298
309
  if (!url) return;
299
- this.stopStepSound();
300
- const a = new Audio(url);
301
- const done = () => {
302
- a.removeEventListener("ended", done);
303
- a.removeEventListener("error", done);
304
- if (this.currentStepAudio === a) this.currentStepAudio = null;
305
- if (this.currentStepAudioCleanup === cleanup) this.currentStepAudioCleanup = null;
306
- };
307
- const cleanup = () => {
308
- a.removeEventListener("ended", done);
309
- a.removeEventListener("error", done);
310
- };
311
- this.currentStepAudio = a;
312
- this.currentStepAudioCleanup = cleanup;
313
- a.addEventListener("ended", done);
314
- a.addEventListener("error", done);
315
- a.play().catch(() => done());
310
+ this.playSound(url);
316
311
  }
317
312
 
318
- private stopStepSound(): void {
319
- if (this.currentStepAudio) {
320
- this.currentStepAudio.pause();
321
- this.currentStepAudio.currentTime = 0;
313
+ private stopAllSounds(): void {
314
+ this.currentAudioToken += 1;
315
+ if (this.currentAudio) {
316
+ this.currentAudio.pause();
317
+ this.currentAudio.currentTime = 0;
322
318
  }
323
- this.currentStepAudioCleanup?.();
324
- this.currentStepAudioCleanup = null;
325
- this.currentStepAudio = null;
319
+ this.currentAudioCleanup?.();
320
+ this.currentAudioCleanup = null;
321
+ this.currentAudio = null;
326
322
  }
327
323
 
328
324
  private clearSessionTimeout(): void {
@@ -378,7 +374,7 @@ export class LivenessEngine {
378
374
  private stopDetectionOnly(): void {
379
375
  this.running = false;
380
376
  this.clearSessionTimeout();
381
- this.stopStepSound();
377
+ this.stopAllSounds();
382
378
  if (this.rafId != null) { cancelAnimationFrame(this.rafId); this.rafId = null; }
383
379
  if (this.landmarker) { this.landmarker.close(); this.landmarker = null; }
384
380
  }
@@ -629,7 +625,7 @@ export class LivenessEngine {
629
625
  }
630
626
 
631
627
  private advanceStep(now: number): "passed" | "none" {
632
- this.stopStepSound();
628
+ this.stopAllSounds();
633
629
  this.stepIndex += 1;
634
630
  if (this.stepIndex >= this.steps.length) {
635
631
  this.playGoodSound();