@sssxyd/face-liveness-detector 0.2.22 → 0.2.23

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.js CHANGED
@@ -373,16 +373,16 @@
373
373
  */
374
374
  async function _initializeOpenCV(timeout) {
375
375
  const initStartTime = performance.now();
376
- console.log('[FaceDetectionEngine] Waiting for OpenCV WASM initialization...');
376
+ console.log('Waiting for OpenCV WASM initialization...');
377
377
  // 快速路径:检查是否已经初始化
378
378
  if (cvModule.Mat) {
379
379
  const initTime = performance.now() - initStartTime;
380
- console.log(`[FaceDetectionEngine] OpenCV.js already initialized, took ${initTime.toFixed(2)}ms`);
380
+ console.log(`OpenCV.js already initialized, took ${initTime.toFixed(2)}ms`);
381
381
  return cvModule;
382
382
  }
383
383
  if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
384
384
  const initTime = performance.now() - initStartTime;
385
- console.log(`[FaceDetectionEngine] OpenCV.js already initialized (from global), took ${initTime.toFixed(2)}ms`);
385
+ console.log(`OpenCV.js already initialized (from global), took ${initTime.toFixed(2)}ms`);
386
386
  cvModule = globalThis.cv;
387
387
  return cvModule;
388
388
  }
@@ -390,10 +390,10 @@
390
390
  if (typeof globalThis !== 'undefined' && !globalThis.cv) {
391
391
  if (cvModule && Object.isExtensible(cvModule)) {
392
392
  globalThis.cv = cvModule;
393
- console.log('[FaceDetectionEngine] cvModule assigned to globalThis.cv');
393
+ console.log('cvModule assigned to globalThis.cv');
394
394
  }
395
395
  else {
396
- console.log('[FaceDetectionEngine] cvModule is not extensible or globalThis already has cv');
396
+ console.log('cvModule is not extensible or globalThis already has cv');
397
397
  }
398
398
  }
399
399
  return new Promise((resolve, reject) => {
@@ -402,7 +402,7 @@
402
402
  // 防止多次调用 resolve/reject
403
403
  let finished = false;
404
404
  const timeoutId = setTimeout(() => {
405
- console.error('[FaceDetectionEngine] OpenCV.js initialization timeout after ' + timeout + 'ms');
405
+ console.error('OpenCV.js initialization timeout after ' + timeout + 'ms');
406
406
  finished = true;
407
407
  if (pollInterval) {
408
408
  clearInterval(pollInterval);
@@ -411,65 +411,65 @@
411
411
  }, timeout);
412
412
  const resolveOnce = (source) => {
413
413
  if (finished) {
414
- console.log('[FaceDetectionEngine] [resolveOnce] Already finished, ignoring call from:', source);
414
+ console.log('[resolveOnce] Already finished, ignoring call from:', source);
415
415
  return;
416
416
  }
417
417
  finished = true;
418
- console.log('[FaceDetectionEngine] [resolveOnce] Marking as finished');
418
+ console.log('[resolveOnce] Marking as finished');
419
419
  // 立即停止所有定时器和轮询
420
420
  clearTimeout(timeoutId);
421
421
  if (pollInterval !== null) {
422
422
  clearInterval(pollInterval);
423
423
  pollInterval = null;
424
- console.log('[FaceDetectionEngine] [resolveOnce] Poll interval cleared');
424
+ console.log('[resolveOnce] Poll interval cleared');
425
425
  }
426
426
  const initTime = performance.now() - initStartTime;
427
- console.log(`[FaceDetectionEngine] OpenCV.js initialized (${source}), took ${initTime.toFixed(2)}ms`);
427
+ console.log(`OpenCV.js initialized (${source}), took ${initTime.toFixed(2)}ms`);
428
428
  // 标记初始化完成
429
429
  opencvInitialized = true;
430
430
  // 返回简单的标记,实际的 cv 对象已经在 globalThis.cv 上了
431
431
  // 通过 getCvSync() 获取
432
432
  resolve(initTime);
433
- console.log('[FaceDetectionEngine] [resolveOnce] Promise resolved with true');
433
+ console.log('[resolveOnce] Promise resolved');
434
434
  };
435
435
  // 尝试设置回调(只有在 cvModule 可扩展时才尝试)
436
436
  const canSetCallback = cvModule && Object.isExtensible(cvModule);
437
437
  if (canSetCallback) {
438
438
  try {
439
439
  const originalOnRuntimeInitialized = cvModule.onRuntimeInitialized(cvModule).onRuntimeInitialized = () => {
440
- console.log('[FaceDetectionEngine] onRuntimeInitialized callback triggered');
440
+ console.log('[onRuntimeInitialized] callback triggered');
441
441
  // 调用原始回调(如果存在)
442
442
  if (originalOnRuntimeInitialized && typeof originalOnRuntimeInitialized === 'function') {
443
443
  try {
444
444
  originalOnRuntimeInitialized();
445
445
  }
446
446
  catch (e) {
447
- console.warn('[FaceDetectionEngine] Original onRuntimeInitialized callback failed:', e);
447
+ console.warn('[onRuntimeInitialized] callback failed:', e);
448
448
  }
449
449
  }
450
450
  resolveOnce('callback');
451
451
  };
452
- console.log('[FaceDetectionEngine] onRuntimeInitialized callback set successfully');
452
+ console.log('[onRuntimeInitialized] callback set successfully');
453
453
  }
454
454
  catch (e) {
455
- console.warn('[FaceDetectionEngine] Failed to set onRuntimeInitialized callback, will use polling:', e);
455
+ console.warn('[onRuntimeInitialized] Failed to set callback, will use polling:', e);
456
456
  }
457
457
  }
458
458
  else {
459
- console.log('[FaceDetectionEngine] cvModule is not extensible, using polling mode');
459
+ console.log('[polling] cvModule is not extensible, using polling mode');
460
460
  }
461
461
  // 启动轮询作为备用方案或主要方案
462
462
  pollInterval = setInterval(() => {
463
- console.log('[FaceDetectionEngine] [polling] Checking for Mat class...');
463
+ console.log('[polling] Checking for Mat class...');
464
464
  // 优先检查 cvModule 中是否有 Mat
465
465
  if (cvModule.Mat) {
466
- console.log('[FaceDetectionEngine] [polling] Found Mat in cvModule');
466
+ console.log('[polling] Found Mat in cvModule');
467
467
  resolveOnce('cvModule polling');
468
468
  return;
469
469
  }
470
470
  // 其次检查 globalThis.cv 中是否有 Mat
471
471
  if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
472
- console.log('[FaceDetectionEngine] [polling] Found Mat in globalThis.cv');
472
+ console.log('[polling] Found Mat in globalThis.cv');
473
473
  cvModule = globalThis.cv;
474
474
  resolveOnce('globalThis.cv polling');
475
475
  return;
@@ -483,38 +483,39 @@
483
483
  * @returns Promise that resolves with cv module
484
484
  */
485
485
  async function loadOpenCV(timeout = 30000) {
486
- console.log('[FaceDetectionEngine] loadOpenCV: START');
487
486
  try {
488
487
  // 快速检查是否已经初始化完成
489
488
  if (opencvInitialized) {
490
- console.log('[FaceDetectionEngine] loadOpenCV: Already initialized, returning immediately');
489
+ console.log('[loadOpenCV] Already initialized, returning immediately');
491
490
  const cv = getCvSync();
492
491
  if (cv) {
493
492
  return { cv };
494
493
  }
495
494
  }
496
495
  // 等待初始化
497
- console.log('[FaceDetectionEngine] loadOpenCV: Waiting for initialization...');
496
+ console.log('[loadOpenCV] Waiting for initialization...');
498
497
  if (!opencvInitPromise) {
499
- console.log('[FaceDetectionEngine] loadOpenCV: Starting new initialization');
498
+ console.log('[loadOpenCV] Starting new initialization');
500
499
  opencvInitPromise = _initializeOpenCV(timeout);
501
500
  }
502
- console.log('[FaceDetectionEngine] loadOpenCV: Awaiting opencvInitPromise');
501
+ console.log('[loadOpenCV] Awaiting opencvInitPromise');
503
502
  const initTime = await opencvInitPromise;
504
- console.log('[FaceDetectionEngine] loadOpenCV: After await, Promise resolved, cost :', initTime.toFixed(0), 'ms');
505
503
  // 清除 Promise 缓存
506
504
  opencvInitPromise = null;
507
505
  // 获取初始化后的 cv 对象
508
506
  const cv = getCvSync();
509
507
  if (!cv) {
510
- console.error('[FaceDetectionEngine] loadOpenCV: getCvSync returned null');
508
+ console.error('[loadOpenCV] getCvSync returned null');
511
509
  throw new Error('OpenCV module is invalid');
512
510
  }
513
- console.log('[FaceDetectionEngine] loadOpenCV: SUCCESS');
514
- return { cv };
511
+ console.log('[loadOpenCV] OpenCV.js load successfully', {
512
+ initTime: `${initTime.toFixed(2)}ms`,
513
+ version: getOpenCVVersion()
514
+ });
515
+ return cv;
515
516
  }
516
517
  catch (error) {
517
- console.error('[FaceDetectionEngine] loadOpenCV: ERROR', error);
518
+ console.error('[loadOpenCV] OpenCV.js load failed', error);
518
519
  opencvInitPromise = null;
519
520
  throw error;
520
521
  }
@@ -534,6 +535,35 @@
534
535
  }
535
536
  return null;
536
537
  }
538
+ /**
539
+ * Extract OpenCV version from getBuildInformation
540
+ * @returns version string like "4.12.0"
541
+ */
542
+ function getOpenCVVersion() {
543
+ try {
544
+ const cv = getCvSync();
545
+ if (!cv || !cv.getBuildInformation) {
546
+ return 'unknown';
547
+ }
548
+ const buildInfo = cv.getBuildInformation();
549
+ // 查找 "Version control:" 或 "OpenCV" 开头的行
550
+ // 格式: "Version control: 4.12.0"
551
+ const versionMatch = buildInfo.match(/Version\s+control:\s+(\d+\.\d+\.\d+)/i);
552
+ if (versionMatch && versionMatch[1]) {
553
+ return versionMatch[1];
554
+ }
555
+ // 备用方案:查找 "OpenCV X.X.X" 格式
556
+ const opencvMatch = buildInfo.match(/OpenCV\s+(\d+\.\d+\.\d+)/i);
557
+ if (opencvMatch && opencvMatch[1]) {
558
+ return opencvMatch[1];
559
+ }
560
+ return 'unknown';
561
+ }
562
+ catch (error) {
563
+ console.error('[getOpenCVVersion] Failed to get version:', error);
564
+ return 'unknown';
565
+ }
566
+ }
537
567
  /**
538
568
  * Load Human.js
539
569
  * @param modelPath - Path to model files (optional)
@@ -563,24 +593,17 @@
563
593
  if (wasmPath) {
564
594
  config.wasmPath = wasmPath;
565
595
  }
566
- console.log('[FaceDetectionEngine] Human.js config:', {
596
+ console.log('[loadHuman] Config:', {
567
597
  backend: config.backend,
568
598
  modelBasePath: config.modelBasePath || '(using default)',
569
599
  wasmPath: config.wasmPath || '(using default)'
570
600
  });
571
601
  const initStartTime = performance.now();
572
- console.log('[FaceDetectionEngine] Creating Human instance...');
573
602
  const human = new Human(config);
574
- const instanceCreateTime = performance.now() - initStartTime;
575
- console.log(`[FaceDetectionEngine] Human instance created, took ${instanceCreateTime.toFixed(2)}ms`);
576
- console.log('[FaceDetectionEngine] Loading Human.js models...');
577
- const modelLoadStartTime = performance.now();
578
603
  try {
579
604
  await human.load();
580
- const loadTime = performance.now() - modelLoadStartTime;
581
605
  const totalTime = performance.now() - initStartTime;
582
- console.log('[FaceDetectionEngine] Human.js loaded successfully', {
583
- modelLoadTime: `${loadTime.toFixed(2)}ms`,
606
+ console.log('[loadHuman] Loaded successfully', {
584
607
  totalInitTime: `${totalTime.toFixed(2)}ms`,
585
608
  version: human.version
586
609
  });
@@ -588,7 +611,32 @@
588
611
  }
589
612
  catch (error) {
590
613
  const errorMsg = error instanceof Error ? error.message : 'Unknown error';
591
- console.error('[FaceDetectionEngine] Human.js load failed:', errorMsg);
614
+ console.error('[loadHuman] Load failed:', errorMsg);
615
+ throw error;
616
+ }
617
+ }
618
+ async function loadLibraries(modelPath, wasmPath, timeout) {
619
+ console.log('[loadLibraries] Starting parallel load of OpenCV and Human...');
620
+ const startTime = performance.now();
621
+ if (timeout == undefined) {
622
+ timeout = 30000;
623
+ }
624
+ try {
625
+ // 并行加载 OpenCV 和 Human
626
+ const [cv, human] = await Promise.all([
627
+ loadOpenCV(timeout),
628
+ loadHuman(modelPath, wasmPath)
629
+ ]);
630
+ const totalTime = performance.now() - startTime;
631
+ console.log('[loadLibraries] Both libraries loaded successfully in', totalTime.toFixed(2), 'ms');
632
+ return {
633
+ cv,
634
+ human
635
+ };
636
+ }
637
+ catch (error) {
638
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
639
+ console.error('[loadLibraries] Failed to load libraries:', errorMsg);
592
640
  throw error;
593
641
  }
594
642
  }
@@ -1570,12 +1618,13 @@
1570
1618
  this.isInitializing = true;
1571
1619
  this.emitDebug('initialization', 'Starting to load detection libraries...');
1572
1620
  try {
1573
- // Load OpenCV
1574
- this.emitDebug('initialization', 'Loading OpenCV...');
1575
- const { cv } = await loadOpenCV(300000); // 5 minute timeout
1621
+ // Load Libraries
1622
+ this.emitDebug('initialization', 'Loading Libraries...');
1623
+ const startLoadTime = performance.now();
1624
+ const { cv, human } = await loadLibraries(this.config.human_model_path, this.config.tensorflow_wasm_path, 30000);
1576
1625
  if (!cv || !cv.Mat) {
1577
1626
  console.log('[FaceDetectionEngine] Failed to load OpenCV.js: module is null or invalid');
1578
- this.emit('detector-error', {
1627
+ this.emit('detector-loaded', {
1579
1628
  success: false,
1580
1629
  error: 'Failed to load OpenCV.js: module is null or invalid'
1581
1630
  });
@@ -1585,22 +1634,9 @@
1585
1634
  });
1586
1635
  return;
1587
1636
  }
1588
- this.emitDebug('initialization', 'OpenCV loaded successfully', {
1589
- version: cv?.getBuildInformation?.() || 'unknown'
1590
- });
1591
- console.log('[FaceDetectionEngine] OpenCV loaded successfully', {
1592
- version: cv?.getBuildInformation?.() || 'unknown'
1593
- });
1594
- // Load Human.js
1595
- console.log('[FaceDetectionEngine] Loading Human.js models...');
1596
- this.emitDebug('initialization', 'Loading Human.js...');
1597
- const humanStartTime = performance.now();
1598
- this.human = await loadHuman(this.config.human_model_path, this.config.tensorflow_wasm_path);
1599
- const humanLoadTime = performance.now() - humanStartTime;
1600
1637
  if (!this.human) {
1601
1638
  const errorMsg = 'Failed to load Human.js: instance is null';
1602
1639
  console.log('[FaceDetectionEngine] ' + errorMsg);
1603
- this.emitDebug('initialization', errorMsg, { loadTime: humanLoadTime }, 'error');
1604
1640
  this.emit('detector-loaded', {
1605
1641
  success: false,
1606
1642
  error: errorMsg
@@ -1611,21 +1647,14 @@
1611
1647
  });
1612
1648
  return;
1613
1649
  }
1614
- this.emitDebug('initialization', 'Human.js loaded successfully', {
1615
- loadTime: `${humanLoadTime.toFixed(2)}ms`,
1616
- version: this.human.version
1617
- });
1618
- console.log('[FaceDetectionEngine] Human.js loaded successfully', {
1619
- loadTime: `${humanLoadTime.toFixed(2)}ms`,
1620
- version: this.human.version
1621
- });
1622
1650
  this.isReady = true;
1623
1651
  const loadedData = {
1624
1652
  success: true,
1625
- opencv_version: cv?.getBuildInformation?.() || 'unknown',
1653
+ opencv_version: getOpenCVVersion(),
1626
1654
  human_version: this.human.version
1627
1655
  };
1628
1656
  console.log('[FaceDetectionEngine] Engine initialized and ready', {
1657
+ initCostTime: (performance.now() - startLoadTime).toFixed(2),
1629
1658
  opencv_version: loadedData.opencv_version,
1630
1659
  human_version: loadedData.human_version
1631
1660
  });
@@ -2398,6 +2427,7 @@
2398
2427
  exports.FaceDetectionEngine = FaceDetectionEngine;
2399
2428
  exports.default = FaceDetectionEngine;
2400
2429
  exports.getCvSync = getCvSync;
2430
+ exports.getOpenCVVersion = getOpenCVVersion;
2401
2431
  exports.loadOpenCV = loadOpenCV;
2402
2432
  exports.preloadOpenCV = preloadOpenCV;
2403
2433