@authme/util 2.8.28 → 2.8.30
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/index.cjs +134 -14
- package/index.js +134 -14
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ var fileSaver = require('file-saver');
|
|
|
27
27
|
var JSZip = require('jszip');
|
|
28
28
|
require('core-js/modules/es.parse-int.js');
|
|
29
29
|
var Lottie = require('lottie-web');
|
|
30
|
+
require('core-js/modules/es.number.to-fixed.js');
|
|
30
31
|
require('core-js/modules/es.array.sort.js');
|
|
31
32
|
require('core-js/modules/es.string.trim.js');
|
|
32
33
|
require('core-js/modules/es.string.starts-with.js');
|
|
@@ -1447,6 +1448,42 @@ const videoConstraintsFactory = (isPC, facingMode) => {
|
|
|
1447
1448
|
}
|
|
1448
1449
|
};
|
|
1449
1450
|
};
|
|
1451
|
+
/**
|
|
1452
|
+
* 等待camera完全就緒
|
|
1453
|
+
* 用於解決外接camera初始化延遲問題
|
|
1454
|
+
* @param videoTrack - MediaStreamTrack 實例
|
|
1455
|
+
* @param maxWaitMs - 最大等待時間(毫秒)
|
|
1456
|
+
* @returns Promise<boolean> - true表示camera已就緒,false表示超時
|
|
1457
|
+
*/
|
|
1458
|
+
function waitForCameraReady(videoTrack, maxWaitMs = 100) {
|
|
1459
|
+
var _a, _b, _c, _d;
|
|
1460
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1461
|
+
const startTime = Date.now();
|
|
1462
|
+
const checkInterval = 50; // 每50ms檢查一次
|
|
1463
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
1464
|
+
const _settings = videoTrack.getSettings();
|
|
1465
|
+
const capabilities = (_a = videoTrack.getCapabilities) === null || _a === void 0 ? void 0 : _a.call(videoTrack);
|
|
1466
|
+
// 檢查camera是否已提供完整資訊
|
|
1467
|
+
// 1. 必須有基本的寬高設定
|
|
1468
|
+
// 2. 如果支援 getCapabilities,確認有最大解析度資訊
|
|
1469
|
+
const hasBasicSettings = _settings.width && _settings.height;
|
|
1470
|
+
const hasCapabilities = !capabilities || ((_b = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _b === void 0 ? void 0 : _b.max) && ((_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _c === void 0 ? void 0 : _c.max);
|
|
1471
|
+
if (hasBasicSettings && hasCapabilities) {
|
|
1472
|
+
const elapsedTime = Date.now() - startTime;
|
|
1473
|
+
console.log(`✅ Camera就緒 (耗時: ${elapsedTime}ms, 解析度: ${_settings.width}x${_settings.height})`);
|
|
1474
|
+
return true;
|
|
1475
|
+
}
|
|
1476
|
+
yield new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
1477
|
+
}
|
|
1478
|
+
const settings = videoTrack.getSettings();
|
|
1479
|
+
console.warn(`⚠️ Camera未在時限內完全就緒 (${maxWaitMs}ms), 當前狀態:`, {
|
|
1480
|
+
width: settings.width,
|
|
1481
|
+
height: settings.height,
|
|
1482
|
+
hasCapabilities: !!((_d = videoTrack.getCapabilities) === null || _d === void 0 ? void 0 : _d.call(videoTrack))
|
|
1483
|
+
});
|
|
1484
|
+
return false;
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1450
1487
|
function inferFacingModeFromLabel(label) {
|
|
1451
1488
|
const pattern = /rear|back|rück|arrière|trasera|trás|traseira|posteriore|后|後|背|задней|الخلفية|후|arka|achterzijde|หลัง|baksidan|bagside|sau|bak|tylny|takakamera|belakang|אחורית|πίσω|spate|hátsó|zadní|darrere|zadná|задня|stražnja|belakang|बैक/i;
|
|
1452
1489
|
if (pattern.test(label !== null && label !== void 0 ? label : '')) {
|
|
@@ -1501,7 +1538,9 @@ function arrayFromAsync(asyncIterable) {
|
|
|
1501
1538
|
});
|
|
1502
1539
|
}
|
|
1503
1540
|
function switchCamera(deviceId, video) {
|
|
1541
|
+
var _a, _b;
|
|
1504
1542
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1543
|
+
const startTime = performance.now();
|
|
1505
1544
|
try {
|
|
1506
1545
|
if (stream) {
|
|
1507
1546
|
stream.getTracks().forEach(track => track.stop());
|
|
@@ -1515,13 +1554,15 @@ function switchCamera(deviceId, video) {
|
|
|
1515
1554
|
};
|
|
1516
1555
|
const constraint = localStorage.getItem('camera_constraint');
|
|
1517
1556
|
stream = yield navigator.mediaDevices.getUserMedia(basicConstraints);
|
|
1518
|
-
//
|
|
1557
|
+
// 第二階段:等待就緒策略 + 漸進式重試提升解析度
|
|
1519
1558
|
if (!constraint && stream) {
|
|
1520
1559
|
const videoTrack = stream.getVideoTracks()[0];
|
|
1521
1560
|
if (videoTrack && videoTrack.applyConstraints) {
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1561
|
+
// 🆕 策略 1: 等待camera完全就緒(特別針對外接camera)
|
|
1562
|
+
const isReady = yield waitForCameraReady(videoTrack, 2000);
|
|
1563
|
+
if (isReady) {
|
|
1564
|
+
// 🆕 策略 2: 漸進式重試邏輯
|
|
1565
|
+
const targetConstraints = {
|
|
1525
1566
|
width: {
|
|
1526
1567
|
ideal: 1920,
|
|
1527
1568
|
max: 3840
|
|
@@ -1530,10 +1571,60 @@ function switchCamera(deviceId, video) {
|
|
|
1530
1571
|
ideal: 1080,
|
|
1531
1572
|
max: 2160
|
|
1532
1573
|
}
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
//
|
|
1574
|
+
};
|
|
1575
|
+
const maxRetries = 3;
|
|
1576
|
+
const delays = [0, 100, 300]; // 第一次立即嘗試,後續間隔遞增
|
|
1577
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1578
|
+
try {
|
|
1579
|
+
if (delays[attempt] > 0) {
|
|
1580
|
+
yield new Promise(resolve => setTimeout(resolve, delays[attempt]));
|
|
1581
|
+
}
|
|
1582
|
+
yield videoTrack.applyConstraints(targetConstraints);
|
|
1583
|
+
const settings = videoTrack.getSettings();
|
|
1584
|
+
console.log(`✅ 解析度提升成功 (嘗試 ${attempt + 1}/${maxRetries})`, {
|
|
1585
|
+
resolution: `${settings.width}x${settings.height}`,
|
|
1586
|
+
deviceLabel: videoTrack.label
|
|
1587
|
+
});
|
|
1588
|
+
break; // 成功後跳出
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
if (attempt === maxRetries - 1) {
|
|
1591
|
+
// 最後一次嘗試失敗,記錄警告但不影響功能
|
|
1592
|
+
const settings = videoTrack.getSettings();
|
|
1593
|
+
console.warn(`⚠️ 無法提升解析度,使用基本設定 (${settings.width}x${settings.height})`, error);
|
|
1594
|
+
} else {
|
|
1595
|
+
console.log(`⏳ 解析度提升嘗試 ${attempt + 1} 失敗,準備重試...`);
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
} else {
|
|
1600
|
+
// Camera未完全就緒,但仍嘗試套用約束
|
|
1601
|
+
console.warn('⚠️ Camera未完全就緒,嘗試套用解析度約束...');
|
|
1602
|
+
try {
|
|
1603
|
+
yield videoTrack.applyConstraints({
|
|
1604
|
+
width: {
|
|
1605
|
+
ideal: 1920,
|
|
1606
|
+
max: 3840
|
|
1607
|
+
},
|
|
1608
|
+
height: {
|
|
1609
|
+
ideal: 1080,
|
|
1610
|
+
max: 2160
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
} catch (error) {
|
|
1614
|
+
console.warn('⚠️ 解析度提升失敗,使用預設解析度', error);
|
|
1615
|
+
}
|
|
1536
1616
|
}
|
|
1617
|
+
// 🆕 記錄最終解析度資訊
|
|
1618
|
+
const finalSettings = videoTrack.getSettings();
|
|
1619
|
+
const initTime = (performance.now() - startTime).toFixed(2);
|
|
1620
|
+
console.log('📹 Camera初始化完成', {
|
|
1621
|
+
deviceId,
|
|
1622
|
+
deviceLabel: videoTrack.label,
|
|
1623
|
+
resolution: `${finalSettings.width}x${finalSettings.height}`,
|
|
1624
|
+
frameRate: finalSettings.frameRate,
|
|
1625
|
+
facingMode: finalSettings.facingMode,
|
|
1626
|
+
initTime: `${initTime}ms`
|
|
1627
|
+
});
|
|
1537
1628
|
}
|
|
1538
1629
|
}
|
|
1539
1630
|
// try {
|
|
@@ -1579,12 +1670,28 @@ function switchCamera(deviceId, video) {
|
|
|
1579
1670
|
video.srcObject = stream;
|
|
1580
1671
|
}, 10);
|
|
1581
1672
|
} catch (e) {
|
|
1673
|
+
// 🆕 增強錯誤日誌
|
|
1674
|
+
const initTime = (performance.now() - startTime).toFixed(2);
|
|
1675
|
+
console.error('❌ Camera切換失敗', {
|
|
1676
|
+
deviceId,
|
|
1677
|
+
error: e,
|
|
1678
|
+
errorName: e === null || e === void 0 ? void 0 : e.name,
|
|
1679
|
+
errorMessage: e === null || e === void 0 ? void 0 : e.message,
|
|
1680
|
+
initTime: `${initTime}ms`,
|
|
1681
|
+
streamExists: !!stream,
|
|
1682
|
+
trackCount: (_b = (_a = stream === null || stream === void 0 ? void 0 : stream.getTracks()) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0
|
|
1683
|
+
});
|
|
1582
1684
|
throw new AuthmeError(exports.ErrorCode.CAMERA_NOT_SUPPORT, e);
|
|
1583
1685
|
}
|
|
1584
1686
|
});
|
|
1585
1687
|
}
|
|
1586
1688
|
function _requestCamera(video, facingMode) {
|
|
1689
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1587
1690
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1691
|
+
const requestStartTime = performance.now();
|
|
1692
|
+
console.log('🎬 開始camera請求流程', {
|
|
1693
|
+
facingMode
|
|
1694
|
+
});
|
|
1588
1695
|
if (!('mediaDevices' in navigator)) {
|
|
1589
1696
|
throw BROWSER_CAMERA_ERRORS.NOT_SUPPORT;
|
|
1590
1697
|
}
|
|
@@ -1607,7 +1714,7 @@ function _requestCamera(video, facingMode) {
|
|
|
1607
1714
|
// 輪詢取得攝影機 解析度等資訊
|
|
1608
1715
|
const videoDevices = (yield navigator.mediaDevices.enumerateDevices()).filter(device => device.kind === 'videoinput');
|
|
1609
1716
|
const deviceMetas = yield arrayFromAsync(asyncMap(device => __awaiter(this, void 0, void 0, function* () {
|
|
1610
|
-
var
|
|
1717
|
+
var _g, _h, _j, _k;
|
|
1611
1718
|
const stream = yield navigator.mediaDevices.getUserMedia({
|
|
1612
1719
|
video: {
|
|
1613
1720
|
deviceId: {
|
|
@@ -1615,10 +1722,10 @@ function _requestCamera(video, facingMode) {
|
|
|
1615
1722
|
}
|
|
1616
1723
|
}
|
|
1617
1724
|
});
|
|
1618
|
-
const track = (
|
|
1619
|
-
const capabilities = ((
|
|
1620
|
-
const widthMax = (
|
|
1621
|
-
const heightMax = (
|
|
1725
|
+
const track = (_g = stream.getVideoTracks()) === null || _g === void 0 ? void 0 : _g[0];
|
|
1726
|
+
const capabilities = ((_h = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _h !== void 0 ? _h : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
|
|
1727
|
+
const widthMax = (_j = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _j === void 0 ? void 0 : _j.max;
|
|
1728
|
+
const heightMax = (_k = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _k === void 0 ? void 0 : _k.max;
|
|
1622
1729
|
const resolution = widthMax && heightMax ? widthMax * heightMax : 0;
|
|
1623
1730
|
const facingModeFromLabel = inferFacingModeFromLabel(device === null || device === void 0 ? void 0 : device.label);
|
|
1624
1731
|
const facingModeFromapabilities = inferFacingModeFromCapabilities(capabilities);
|
|
@@ -1678,6 +1785,19 @@ function _requestCamera(video, facingMode) {
|
|
|
1678
1785
|
stream.getTracks().forEach(track => track.stop());
|
|
1679
1786
|
}
|
|
1680
1787
|
yield switchCamera(deviceId, video);
|
|
1788
|
+
// 🆕 記錄整個請求流程的總結資訊
|
|
1789
|
+
const totalTime = (performance.now() - requestStartTime).toFixed(2);
|
|
1790
|
+
console.log('🎉 Camera請求流程完成', {
|
|
1791
|
+
totalTime: `${totalTime}ms`,
|
|
1792
|
+
selectedDevice: {
|
|
1793
|
+
deviceId,
|
|
1794
|
+
label: firstDevice.device.label,
|
|
1795
|
+
facingMode: firstDevice.meta.facingMode,
|
|
1796
|
+
resolution: `${(_c = (_b = (_a = firstDevice.meta.capabilities) === null || _a === void 0 ? void 0 : _a.width) === null || _b === void 0 ? void 0 : _b.max) !== null && _c !== void 0 ? _c : 0}x${(_f = (_e = (_d = firstDevice.meta.capabilities) === null || _d === void 0 ? void 0 : _d.height) === null || _e === void 0 ? void 0 : _e.max) !== null && _f !== void 0 ? _f : 0}`
|
|
1797
|
+
},
|
|
1798
|
+
availableDevices: deviceMetas.length,
|
|
1799
|
+
isSamsung
|
|
1800
|
+
});
|
|
1681
1801
|
return {
|
|
1682
1802
|
facingMode: firstDevice.meta.facingMode,
|
|
1683
1803
|
deviceMetas: deviceMetas
|
|
@@ -3243,8 +3363,8 @@ const themeConfigDefault = {
|
|
|
3243
3363
|
};
|
|
3244
3364
|
|
|
3245
3365
|
var name = "authme/sdk";
|
|
3246
|
-
var version$1 = "2.8.
|
|
3247
|
-
var date = "2025-10-
|
|
3366
|
+
var version$1 = "2.8.30";
|
|
3367
|
+
var date = "2025-10-30T10:27:17+0000";
|
|
3248
3368
|
var packageInfo = {
|
|
3249
3369
|
name: name,
|
|
3250
3370
|
version: version$1,
|
package/index.js
CHANGED
|
@@ -23,6 +23,7 @@ import { saveAs } from 'file-saver';
|
|
|
23
23
|
import JSZip from 'jszip';
|
|
24
24
|
import 'core-js/modules/es.parse-int.js';
|
|
25
25
|
import Lottie from 'lottie-web';
|
|
26
|
+
import 'core-js/modules/es.number.to-fixed.js';
|
|
26
27
|
import 'core-js/modules/es.array.sort.js';
|
|
27
28
|
import 'core-js/modules/es.string.trim.js';
|
|
28
29
|
import 'core-js/modules/es.string.starts-with.js';
|
|
@@ -1437,6 +1438,42 @@ const videoConstraintsFactory = (isPC, facingMode) => {
|
|
|
1437
1438
|
}
|
|
1438
1439
|
};
|
|
1439
1440
|
};
|
|
1441
|
+
/**
|
|
1442
|
+
* 等待camera完全就緒
|
|
1443
|
+
* 用於解決外接camera初始化延遲問題
|
|
1444
|
+
* @param videoTrack - MediaStreamTrack 實例
|
|
1445
|
+
* @param maxWaitMs - 最大等待時間(毫秒)
|
|
1446
|
+
* @returns Promise<boolean> - true表示camera已就緒,false表示超時
|
|
1447
|
+
*/
|
|
1448
|
+
function waitForCameraReady(videoTrack, maxWaitMs = 100) {
|
|
1449
|
+
var _a, _b, _c, _d;
|
|
1450
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1451
|
+
const startTime = Date.now();
|
|
1452
|
+
const checkInterval = 50; // 每50ms檢查一次
|
|
1453
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
1454
|
+
const _settings = videoTrack.getSettings();
|
|
1455
|
+
const capabilities = (_a = videoTrack.getCapabilities) === null || _a === void 0 ? void 0 : _a.call(videoTrack);
|
|
1456
|
+
// 檢查camera是否已提供完整資訊
|
|
1457
|
+
// 1. 必須有基本的寬高設定
|
|
1458
|
+
// 2. 如果支援 getCapabilities,確認有最大解析度資訊
|
|
1459
|
+
const hasBasicSettings = _settings.width && _settings.height;
|
|
1460
|
+
const hasCapabilities = !capabilities || ((_b = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _b === void 0 ? void 0 : _b.max) && ((_c = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _c === void 0 ? void 0 : _c.max);
|
|
1461
|
+
if (hasBasicSettings && hasCapabilities) {
|
|
1462
|
+
const elapsedTime = Date.now() - startTime;
|
|
1463
|
+
console.log(`✅ Camera就緒 (耗時: ${elapsedTime}ms, 解析度: ${_settings.width}x${_settings.height})`);
|
|
1464
|
+
return true;
|
|
1465
|
+
}
|
|
1466
|
+
yield new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
1467
|
+
}
|
|
1468
|
+
const settings = videoTrack.getSettings();
|
|
1469
|
+
console.warn(`⚠️ Camera未在時限內完全就緒 (${maxWaitMs}ms), 當前狀態:`, {
|
|
1470
|
+
width: settings.width,
|
|
1471
|
+
height: settings.height,
|
|
1472
|
+
hasCapabilities: !!((_d = videoTrack.getCapabilities) === null || _d === void 0 ? void 0 : _d.call(videoTrack))
|
|
1473
|
+
});
|
|
1474
|
+
return false;
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1440
1477
|
function inferFacingModeFromLabel(label) {
|
|
1441
1478
|
const pattern = /rear|back|rück|arrière|trasera|trás|traseira|posteriore|后|後|背|задней|الخلفية|후|arka|achterzijde|หลัง|baksidan|bagside|sau|bak|tylny|takakamera|belakang|אחורית|πίσω|spate|hátsó|zadní|darrere|zadná|задня|stražnja|belakang|बैक/i;
|
|
1442
1479
|
if (pattern.test(label !== null && label !== void 0 ? label : '')) {
|
|
@@ -1491,7 +1528,9 @@ function arrayFromAsync(asyncIterable) {
|
|
|
1491
1528
|
});
|
|
1492
1529
|
}
|
|
1493
1530
|
function switchCamera(deviceId, video) {
|
|
1531
|
+
var _a, _b;
|
|
1494
1532
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1533
|
+
const startTime = performance.now();
|
|
1495
1534
|
try {
|
|
1496
1535
|
if (stream) {
|
|
1497
1536
|
stream.getTracks().forEach(track => track.stop());
|
|
@@ -1505,13 +1544,15 @@ function switchCamera(deviceId, video) {
|
|
|
1505
1544
|
};
|
|
1506
1545
|
const constraint = localStorage.getItem('camera_constraint');
|
|
1507
1546
|
stream = yield navigator.mediaDevices.getUserMedia(basicConstraints);
|
|
1508
|
-
//
|
|
1547
|
+
// 第二階段:等待就緒策略 + 漸進式重試提升解析度
|
|
1509
1548
|
if (!constraint && stream) {
|
|
1510
1549
|
const videoTrack = stream.getVideoTracks()[0];
|
|
1511
1550
|
if (videoTrack && videoTrack.applyConstraints) {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1551
|
+
// 🆕 策略 1: 等待camera完全就緒(特別針對外接camera)
|
|
1552
|
+
const isReady = yield waitForCameraReady(videoTrack, 2000);
|
|
1553
|
+
if (isReady) {
|
|
1554
|
+
// 🆕 策略 2: 漸進式重試邏輯
|
|
1555
|
+
const targetConstraints = {
|
|
1515
1556
|
width: {
|
|
1516
1557
|
ideal: 1920,
|
|
1517
1558
|
max: 3840
|
|
@@ -1520,10 +1561,60 @@ function switchCamera(deviceId, video) {
|
|
|
1520
1561
|
ideal: 1080,
|
|
1521
1562
|
max: 2160
|
|
1522
1563
|
}
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
//
|
|
1564
|
+
};
|
|
1565
|
+
const maxRetries = 3;
|
|
1566
|
+
const delays = [0, 100, 300]; // 第一次立即嘗試,後續間隔遞增
|
|
1567
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1568
|
+
try {
|
|
1569
|
+
if (delays[attempt] > 0) {
|
|
1570
|
+
yield new Promise(resolve => setTimeout(resolve, delays[attempt]));
|
|
1571
|
+
}
|
|
1572
|
+
yield videoTrack.applyConstraints(targetConstraints);
|
|
1573
|
+
const settings = videoTrack.getSettings();
|
|
1574
|
+
console.log(`✅ 解析度提升成功 (嘗試 ${attempt + 1}/${maxRetries})`, {
|
|
1575
|
+
resolution: `${settings.width}x${settings.height}`,
|
|
1576
|
+
deviceLabel: videoTrack.label
|
|
1577
|
+
});
|
|
1578
|
+
break; // 成功後跳出
|
|
1579
|
+
} catch (error) {
|
|
1580
|
+
if (attempt === maxRetries - 1) {
|
|
1581
|
+
// 最後一次嘗試失敗,記錄警告但不影響功能
|
|
1582
|
+
const settings = videoTrack.getSettings();
|
|
1583
|
+
console.warn(`⚠️ 無法提升解析度,使用基本設定 (${settings.width}x${settings.height})`, error);
|
|
1584
|
+
} else {
|
|
1585
|
+
console.log(`⏳ 解析度提升嘗試 ${attempt + 1} 失敗,準備重試...`);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
} else {
|
|
1590
|
+
// Camera未完全就緒,但仍嘗試套用約束
|
|
1591
|
+
console.warn('⚠️ Camera未完全就緒,嘗試套用解析度約束...');
|
|
1592
|
+
try {
|
|
1593
|
+
yield videoTrack.applyConstraints({
|
|
1594
|
+
width: {
|
|
1595
|
+
ideal: 1920,
|
|
1596
|
+
max: 3840
|
|
1597
|
+
},
|
|
1598
|
+
height: {
|
|
1599
|
+
ideal: 1080,
|
|
1600
|
+
max: 2160
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
} catch (error) {
|
|
1604
|
+
console.warn('⚠️ 解析度提升失敗,使用預設解析度', error);
|
|
1605
|
+
}
|
|
1526
1606
|
}
|
|
1607
|
+
// 🆕 記錄最終解析度資訊
|
|
1608
|
+
const finalSettings = videoTrack.getSettings();
|
|
1609
|
+
const initTime = (performance.now() - startTime).toFixed(2);
|
|
1610
|
+
console.log('📹 Camera初始化完成', {
|
|
1611
|
+
deviceId,
|
|
1612
|
+
deviceLabel: videoTrack.label,
|
|
1613
|
+
resolution: `${finalSettings.width}x${finalSettings.height}`,
|
|
1614
|
+
frameRate: finalSettings.frameRate,
|
|
1615
|
+
facingMode: finalSettings.facingMode,
|
|
1616
|
+
initTime: `${initTime}ms`
|
|
1617
|
+
});
|
|
1527
1618
|
}
|
|
1528
1619
|
}
|
|
1529
1620
|
// try {
|
|
@@ -1569,12 +1660,28 @@ function switchCamera(deviceId, video) {
|
|
|
1569
1660
|
video.srcObject = stream;
|
|
1570
1661
|
}, 10);
|
|
1571
1662
|
} catch (e) {
|
|
1663
|
+
// 🆕 增強錯誤日誌
|
|
1664
|
+
const initTime = (performance.now() - startTime).toFixed(2);
|
|
1665
|
+
console.error('❌ Camera切換失敗', {
|
|
1666
|
+
deviceId,
|
|
1667
|
+
error: e,
|
|
1668
|
+
errorName: e === null || e === void 0 ? void 0 : e.name,
|
|
1669
|
+
errorMessage: e === null || e === void 0 ? void 0 : e.message,
|
|
1670
|
+
initTime: `${initTime}ms`,
|
|
1671
|
+
streamExists: !!stream,
|
|
1672
|
+
trackCount: (_b = (_a = stream === null || stream === void 0 ? void 0 : stream.getTracks()) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0
|
|
1673
|
+
});
|
|
1572
1674
|
throw new AuthmeError(ErrorCode.CAMERA_NOT_SUPPORT, e);
|
|
1573
1675
|
}
|
|
1574
1676
|
});
|
|
1575
1677
|
}
|
|
1576
1678
|
function _requestCamera(video, facingMode) {
|
|
1679
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1577
1680
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1681
|
+
const requestStartTime = performance.now();
|
|
1682
|
+
console.log('🎬 開始camera請求流程', {
|
|
1683
|
+
facingMode
|
|
1684
|
+
});
|
|
1578
1685
|
if (!('mediaDevices' in navigator)) {
|
|
1579
1686
|
throw BROWSER_CAMERA_ERRORS.NOT_SUPPORT;
|
|
1580
1687
|
}
|
|
@@ -1597,7 +1704,7 @@ function _requestCamera(video, facingMode) {
|
|
|
1597
1704
|
// 輪詢取得攝影機 解析度等資訊
|
|
1598
1705
|
const videoDevices = (yield navigator.mediaDevices.enumerateDevices()).filter(device => device.kind === 'videoinput');
|
|
1599
1706
|
const deviceMetas = yield arrayFromAsync(asyncMap(device => __awaiter(this, void 0, void 0, function* () {
|
|
1600
|
-
var
|
|
1707
|
+
var _g, _h, _j, _k;
|
|
1601
1708
|
const stream = yield navigator.mediaDevices.getUserMedia({
|
|
1602
1709
|
video: {
|
|
1603
1710
|
deviceId: {
|
|
@@ -1605,10 +1712,10 @@ function _requestCamera(video, facingMode) {
|
|
|
1605
1712
|
}
|
|
1606
1713
|
}
|
|
1607
1714
|
});
|
|
1608
|
-
const track = (
|
|
1609
|
-
const capabilities = ((
|
|
1610
|
-
const widthMax = (
|
|
1611
|
-
const heightMax = (
|
|
1715
|
+
const track = (_g = stream.getVideoTracks()) === null || _g === void 0 ? void 0 : _g[0];
|
|
1716
|
+
const capabilities = ((_h = track === null || track === void 0 ? void 0 : track.getCapabilities) !== null && _h !== void 0 ? _h : () => undefined).bind(track)(); // firefox 沒有 getCapabilities 可以用。
|
|
1717
|
+
const widthMax = (_j = capabilities === null || capabilities === void 0 ? void 0 : capabilities.width) === null || _j === void 0 ? void 0 : _j.max;
|
|
1718
|
+
const heightMax = (_k = capabilities === null || capabilities === void 0 ? void 0 : capabilities.height) === null || _k === void 0 ? void 0 : _k.max;
|
|
1612
1719
|
const resolution = widthMax && heightMax ? widthMax * heightMax : 0;
|
|
1613
1720
|
const facingModeFromLabel = inferFacingModeFromLabel(device === null || device === void 0 ? void 0 : device.label);
|
|
1614
1721
|
const facingModeFromapabilities = inferFacingModeFromCapabilities(capabilities);
|
|
@@ -1668,6 +1775,19 @@ function _requestCamera(video, facingMode) {
|
|
|
1668
1775
|
stream.getTracks().forEach(track => track.stop());
|
|
1669
1776
|
}
|
|
1670
1777
|
yield switchCamera(deviceId, video);
|
|
1778
|
+
// 🆕 記錄整個請求流程的總結資訊
|
|
1779
|
+
const totalTime = (performance.now() - requestStartTime).toFixed(2);
|
|
1780
|
+
console.log('🎉 Camera請求流程完成', {
|
|
1781
|
+
totalTime: `${totalTime}ms`,
|
|
1782
|
+
selectedDevice: {
|
|
1783
|
+
deviceId,
|
|
1784
|
+
label: firstDevice.device.label,
|
|
1785
|
+
facingMode: firstDevice.meta.facingMode,
|
|
1786
|
+
resolution: `${(_c = (_b = (_a = firstDevice.meta.capabilities) === null || _a === void 0 ? void 0 : _a.width) === null || _b === void 0 ? void 0 : _b.max) !== null && _c !== void 0 ? _c : 0}x${(_f = (_e = (_d = firstDevice.meta.capabilities) === null || _d === void 0 ? void 0 : _d.height) === null || _e === void 0 ? void 0 : _e.max) !== null && _f !== void 0 ? _f : 0}`
|
|
1787
|
+
},
|
|
1788
|
+
availableDevices: deviceMetas.length,
|
|
1789
|
+
isSamsung
|
|
1790
|
+
});
|
|
1671
1791
|
return {
|
|
1672
1792
|
facingMode: firstDevice.meta.facingMode,
|
|
1673
1793
|
deviceMetas: deviceMetas
|
|
@@ -3233,8 +3353,8 @@ const themeConfigDefault = {
|
|
|
3233
3353
|
};
|
|
3234
3354
|
|
|
3235
3355
|
var name = "authme/sdk";
|
|
3236
|
-
var version$1 = "2.8.
|
|
3237
|
-
var date = "2025-10-
|
|
3356
|
+
var version$1 = "2.8.30";
|
|
3357
|
+
var date = "2025-10-30T10:27:17+0000";
|
|
3238
3358
|
var packageInfo = {
|
|
3239
3359
|
name: name,
|
|
3240
3360
|
version: version$1,
|