@simprints/simface-sdk 0.6.1 → 0.8.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.
@@ -0,0 +1,287 @@
1
+ import { assessFaceQuality, assessFaceQualityForVideo } from '../services/face-detection.js';
2
+ import { AUTO_CAPTURE_ANALYSIS_INTERVAL_MS, AUTO_CAPTURE_COUNTDOWN_MS, autoCaptureCompleteMessage, autoCaptureCountdownMessage, } from './auto-capture.js';
3
+ import { blobToImage, createReusableFrameCapture, resumeVideoPlayback, waitForVideoReady, } from './capture-runtime.js';
4
+ export class CameraCaptureSessionController {
5
+ constructor(options) {
6
+ this.frameCapture = createReusableFrameCapture();
7
+ this.stopped = false;
8
+ this.animationFrameId = null;
9
+ this.analysisTimerId = null;
10
+ this.analysisInFlight = false;
11
+ this.lastAnalysisTimestamp = 0;
12
+ this.countdownStartedAt = null;
13
+ this.bestCaptureScore = -1;
14
+ this.bestQualityResult = null;
15
+ this.videoElement = options.videoElement;
16
+ this.copy = options.copy;
17
+ this.onStateChange = options.onStateChange;
18
+ this.waitForReady = options.waitForReady ?? ((video) => waitForVideoReady(video));
19
+ this.assessLiveQuality = options.assessLiveQuality ?? assessFaceQualityForVideo;
20
+ this.assessPreviewBlob = options.assessPreviewBlob ?? assessCapturedBlob;
21
+ this.mode = options.initialMode;
22
+ this.state = this.createStartingState();
23
+ this.emit(this.state);
24
+ }
25
+ getState() {
26
+ return this.state;
27
+ }
28
+ async start() {
29
+ if (this.stopped)
30
+ return;
31
+ this.emit(this.createStartingState());
32
+ await this.waitForReady(this.videoElement);
33
+ if (this.stopped)
34
+ return;
35
+ this.emit(this.createLiveState({
36
+ feedbackMessage: this.mode === 'auto'
37
+ ? this.copy.autoReadyMessage
38
+ : this.copy.manualReadyMessage,
39
+ feedbackTone: this.mode === 'auto' ? 'neutral' : 'manual',
40
+ }));
41
+ if (this.mode === 'auto') {
42
+ this.scheduleAutoAnalysis();
43
+ }
44
+ }
45
+ async takePhotoNow() {
46
+ if (this.stopped || this.state.phase !== 'live') {
47
+ return;
48
+ }
49
+ // Switch to manual mode and cancel any pending auto-analysis so that
50
+ // in-flight runAutoAnalysis / finishAutoCapture calls no-op and cannot
51
+ // override the preview state after this manual capture completes.
52
+ if (this.mode === 'auto') {
53
+ this.mode = 'manual';
54
+ this.cancelScheduledAnalysis();
55
+ }
56
+ const blob = await this.frameCapture.captureBlob(this.videoElement);
57
+ if (this.stopped)
58
+ return;
59
+ const qualityResult = await this.assessPreviewBlob(blob);
60
+ if (this.stopped)
61
+ return;
62
+ this.emit(this.createPreviewState(blob, qualityResult));
63
+ }
64
+ async retake() {
65
+ if (this.stopped || this.state.phase !== 'preview') {
66
+ return;
67
+ }
68
+ this.resetAutoState();
69
+ resumeVideoPlayback(this.videoElement);
70
+ this.emit(this.createLiveState({
71
+ feedbackMessage: this.mode === 'auto'
72
+ ? this.copy.autoReadyMessage
73
+ : (this.copy.retakeReadyMessage ?? this.copy.manualReadyMessage),
74
+ feedbackTone: this.mode === 'auto' ? 'neutral' : 'manual',
75
+ }));
76
+ if (this.mode === 'auto') {
77
+ this.scheduleAutoAnalysis();
78
+ }
79
+ }
80
+ confirm() {
81
+ if (this.state.phase !== 'preview') {
82
+ throw new Error('Failed to confirm the photo.');
83
+ }
84
+ return this.state.previewBlob;
85
+ }
86
+ stop() {
87
+ this.stopped = true;
88
+ this.cancelScheduledAnalysis();
89
+ }
90
+ createStartingState() {
91
+ return {
92
+ phase: 'starting',
93
+ mode: this.mode,
94
+ feedbackMessage: '',
95
+ feedbackTone: 'neutral',
96
+ countdownProgress: 0,
97
+ qualityResult: null,
98
+ fallbackReason: null,
99
+ previewBlob: null,
100
+ errorMessage: '',
101
+ canConfirm: false,
102
+ canTakePhoto: false,
103
+ };
104
+ }
105
+ createLiveState(options) {
106
+ return {
107
+ phase: 'live',
108
+ mode: this.mode,
109
+ feedbackMessage: options.feedbackMessage,
110
+ feedbackTone: options.feedbackTone,
111
+ countdownProgress: options.countdownProgress ?? 0,
112
+ qualityResult: options.qualityResult ?? null,
113
+ fallbackReason: options.fallbackReason ?? null,
114
+ previewBlob: null,
115
+ errorMessage: '',
116
+ canConfirm: false,
117
+ canTakePhoto: this.mode !== 'auto' || this.countdownStartedAt === null,
118
+ };
119
+ }
120
+ createPreviewState(blob, qualityResult, options) {
121
+ return {
122
+ phase: 'preview',
123
+ mode: this.mode,
124
+ feedbackMessage: options?.feedbackMessage
125
+ ?? qualityResult?.message
126
+ ?? 'Review the captured image before continuing.',
127
+ feedbackTone: options?.feedbackTone
128
+ ?? (qualityResult
129
+ ? qualityResult.passesQualityChecks
130
+ ? 'success'
131
+ : 'error'
132
+ : 'manual'),
133
+ countdownProgress: qualityResult ? 1 : 0,
134
+ qualityResult,
135
+ fallbackReason: null,
136
+ previewBlob: blob,
137
+ errorMessage: '',
138
+ canConfirm: qualityResult?.passesQualityChecks !== false,
139
+ canTakePhoto: false,
140
+ };
141
+ }
142
+ emitError(errorMessage) {
143
+ if (this.stopped)
144
+ return;
145
+ this.cancelScheduledAnalysis();
146
+ this.emit({
147
+ phase: 'error',
148
+ mode: this.mode,
149
+ feedbackMessage: errorMessage,
150
+ feedbackTone: 'error',
151
+ countdownProgress: 0,
152
+ qualityResult: null,
153
+ fallbackReason: null,
154
+ previewBlob: null,
155
+ errorMessage,
156
+ canConfirm: false,
157
+ canTakePhoto: false,
158
+ });
159
+ }
160
+ emit(state) {
161
+ if (this.stopped)
162
+ return;
163
+ this.state = state;
164
+ this.onStateChange(state);
165
+ }
166
+ scheduleAutoAnalysis() {
167
+ if (this.stopped || this.mode !== 'auto' || this.state.phase !== 'live') {
168
+ return;
169
+ }
170
+ const now = performance.now();
171
+ const delay = Math.max(AUTO_CAPTURE_ANALYSIS_INTERVAL_MS - (now - this.lastAnalysisTimestamp), 0);
172
+ this.cancelScheduledAnalysis();
173
+ this.analysisTimerId = window.setTimeout(() => {
174
+ this.analysisTimerId = null;
175
+ this.animationFrameId = window.requestAnimationFrame((timestamp) => {
176
+ void this.runAutoAnalysis(timestamp);
177
+ });
178
+ }, delay);
179
+ }
180
+ async runAutoAnalysis(timestamp) {
181
+ if (this.stopped)
182
+ return;
183
+ if (this.mode !== 'auto' || this.state.phase !== 'live' || this.analysisInFlight) {
184
+ this.scheduleAutoAnalysis();
185
+ return;
186
+ }
187
+ this.analysisInFlight = true;
188
+ this.lastAnalysisTimestamp = timestamp;
189
+ try {
190
+ const qualityResult = await this.assessLiveQuality(this.videoElement, timestamp);
191
+ if (this.stopped)
192
+ return;
193
+ if (this.mode !== 'auto' || this.state.phase !== 'live')
194
+ return;
195
+ if (qualityResult.passesQualityChecks) {
196
+ if (this.countdownStartedAt === null) {
197
+ this.countdownStartedAt = timestamp;
198
+ }
199
+ if (qualityResult.captureScore > this.bestCaptureScore) {
200
+ this.frameCapture.storeBestFrame(this.videoElement);
201
+ this.bestCaptureScore = qualityResult.captureScore;
202
+ this.bestQualityResult = qualityResult;
203
+ }
204
+ }
205
+ if (this.countdownStartedAt !== null) {
206
+ const countdownProgress = Math.min((timestamp - this.countdownStartedAt) / AUTO_CAPTURE_COUNTDOWN_MS, 1);
207
+ if (countdownProgress >= 1) {
208
+ await this.finishAutoCapture();
209
+ return;
210
+ }
211
+ this.emit(this.createLiveState({
212
+ feedbackMessage: autoCaptureCountdownMessage(timestamp, this.countdownStartedAt, qualityResult),
213
+ feedbackTone: qualityResult.passesQualityChecks ? 'success' : 'neutral',
214
+ countdownProgress,
215
+ qualityResult,
216
+ }));
217
+ }
218
+ else {
219
+ this.emit(this.createLiveState({
220
+ feedbackMessage: qualityResult.message,
221
+ feedbackTone: qualityResult.passesQualityChecks ? 'success' : 'neutral',
222
+ qualityResult,
223
+ }));
224
+ }
225
+ }
226
+ catch {
227
+ if (!this.stopped && this.mode === 'auto' && this.state.phase === 'live') {
228
+ this.switchToManual();
229
+ }
230
+ return;
231
+ }
232
+ finally {
233
+ this.analysisInFlight = false;
234
+ }
235
+ this.scheduleAutoAnalysis();
236
+ }
237
+ async finishAutoCapture() {
238
+ const blob = this.frameCapture.hasStoredBestFrame()
239
+ ? await this.frameCapture.storedBestFrameToBlob()
240
+ : await this.frameCapture.captureBlob(this.videoElement);
241
+ if (this.stopped || this.mode !== 'auto' || this.state.phase !== 'live')
242
+ return;
243
+ const qualityResult = this.bestQualityResult ?? await this.assessPreviewBlob(blob);
244
+ if (this.stopped || this.mode !== 'auto' || this.state.phase !== 'live')
245
+ return;
246
+ this.emit(this.createPreviewState(blob, qualityResult, {
247
+ feedbackMessage: autoCaptureCompleteMessage(qualityResult),
248
+ feedbackTone: qualityResult?.passesQualityChecks === false ? 'error' : 'success',
249
+ }));
250
+ }
251
+ switchToManual() {
252
+ this.mode = 'manual';
253
+ this.resetAutoState();
254
+ this.emit(this.createLiveState({
255
+ feedbackMessage: this.copy.autoUnavailableMessage,
256
+ feedbackTone: 'manual',
257
+ fallbackReason: 'auto-capture-unavailable',
258
+ }));
259
+ }
260
+ cancelScheduledAnalysis() {
261
+ if (this.analysisTimerId !== null) {
262
+ window.clearTimeout(this.analysisTimerId);
263
+ this.analysisTimerId = null;
264
+ }
265
+ if (this.animationFrameId !== null) {
266
+ window.cancelAnimationFrame(this.animationFrameId);
267
+ this.animationFrameId = null;
268
+ }
269
+ }
270
+ resetAutoState() {
271
+ this.cancelScheduledAnalysis();
272
+ this.countdownStartedAt = null;
273
+ this.bestCaptureScore = -1;
274
+ this.bestQualityResult = null;
275
+ this.frameCapture.resetStoredBestFrame();
276
+ }
277
+ }
278
+ async function assessCapturedBlob(blob) {
279
+ try {
280
+ const image = await blobToImage(blob);
281
+ return await assessFaceQuality(image);
282
+ }
283
+ catch {
284
+ return null;
285
+ }
286
+ }
287
+ //# sourceMappingURL=capture-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-session.js","sourceRoot":"","sources":["../../src/shared/capture-session.ts"],"names":[],"mappings":"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"}