@voltom.io/sdk 1.0.5 → 1.0.7
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/assets/locales/ar.json +34 -2
- package/dist/assets/locales/ch.json +34 -2
- package/dist/assets/locales/de.json +34 -2
- package/dist/assets/locales/en.json +34 -2
- package/dist/assets/locales/es.json +34 -2
- package/dist/assets/locales/fr.json +34 -2
- package/dist/assets/locales/it.json +34 -2
- package/dist/assets/locales/ja.json +34 -2
- package/dist/assets/locales/pt.json +34 -2
- package/dist/assets/locales/ru.json +34 -2
- package/dist/assets/locales/zh.json +34 -2
- package/dist/sdk/PoseSilhouette-D2pGu7Lh.js +2 -0
- package/dist/sdk/PoseSuccess-R_8JYo--.js +2 -0
- package/dist/sdk/errors.d.ts +121 -0
- package/dist/sdk/facegate/global.d.ts +1 -1
- package/dist/sdk/facegate.d.ts +42 -19
- package/dist/sdk/facegate.dist.js +4 -4
- package/dist/sdk/facegate.js +1 -1
- package/dist/sdk/facekey.browser-VlDa2K-w.js +2 -0
- package/dist/sdk/facekey.d.ts +50 -26
- package/dist/sdk/facekey.dist.js +6 -6
- package/dist/sdk/facekey.js +1 -1
- package/dist/sdk/presentation-COhoAxj3.js +8 -0
- package/dist/sdk/presentation-ye0KVm6U.js +2 -0
- package/dist/sdk/requests-DW8zDX51.js +65 -0
- package/dist/sdk/verify.d.ts +58 -22
- package/dist/sdk/verify.dist.js +18 -18
- package/dist/sdk/verify.js +1 -1
- package/dist/sdk/view-CF_YOVly.js +3 -0
- package/dist/sdk/view-Cb4XCb-z.js +3 -0
- package/dist/sdk/view-DcbwHph_.js +2 -0
- package/package.json +7 -5
- package/dist/sdk/PoseSilhouette-Bbwmry4Z.js +0 -2
- package/dist/sdk/PoseSuccess-C3aBF88E.js +0 -2
- package/dist/sdk/eyeLevelCamera-DY4onSBz.js +0 -65
- package/dist/sdk/facekey.browser-CVJiBw1f.js +0 -2
- package/dist/sdk/media-BRKPXpu3.js +0 -2
- package/dist/sdk/presentation-B-TOKUZ3.js +0 -8
- package/dist/sdk/presentation-BsnbDv0i.js +0 -2
- package/dist/sdk/view-Bfg8u_hZ.js +0 -2
- package/dist/sdk/view-CHSkN6gO.js +0 -3
- package/dist/sdk/view-DmGKdc3M.js +0 -3
package/dist/sdk/facekey.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
|
|
2
|
-
import{D as e,O as t,Y as n,a as r,d as i,et as a,f as o,i as s,l as c,n as l,o as u,r as d,s as f,t as p,tt as m,u as h,y as g}from"./eyeLevelCamera-DY4onSBz.js";import{D as _,a as v,c as y,d as b,h as x,i as S,p as C,s as w,t as T,u as E}from"./media-BRKPXpu3.js";import{n as D,r as O,t as k}from"./facekey.browser-CVJiBw1f.js";import{t as A}from"./presentation-BsnbDv0i.js";var j=e=>{if(typeof e.token!=`string`||e.token.length<32||e.token.length>128||e.userId!==void 0&&(typeof e.userId!=`string`||e.userId.length<1||e.userId.length>255))throw Error(x.INVALID_OPTIONS);return e},M=e=>e.length===512&&e.every(e=>Number.isFinite(e))&&Math.abs(Math.hypot(...e)-1)<.001?e:null,N=({pose:e,rejection:t,language:n})=>{let{translate:r}=b({language:n});return r(t?o({code:t}):i({pose:e}).primary)},{detectDocumentBox:P,loadDocumentBoxDetector:F}=k,{detectPictureFaces:I,loadFaceDetector:L}=D,{imageBitmap:R,loadFaceMatch:z,preparedFaceGrayscaleEmbedding:B,prepareFace:V,warmupFaceMatch:H}=O,U=({face:e})=>e?{left:e.blendshapes.eyeBlinkLeft??0,right:e.blendshapes.eyeBlinkRight??0}:null,W=({face:e,frame:t})=>e.boundingRect.height/Math.min(t.width,t.height)<.5?`FACE_TOO_SMALL`:null,G=({face:e,frame:t})=>{let n=e.boundingRect.x+e.boundingRect.width/2,r=e.boundingRect.y+e.boundingRect.height/2,i=Math.min(t.width,t.height);return Math.hypot(n-t.width/2,r-t.height/2)<=i*.08},K=async({frame:n,pose:r,signal:i,neutral:a,requireEyeLevelCamera:o,language:s})=>{let c=await I(n);i.throwIfAborted();let u=c.length===1?c[0]:null,f=u?await P(n):null;i.throwIfAborted();let m=!!(u&&f&&e({face:u,polygon:f.polygon})),h=!!(u&&W({face:u,frame:n})),g=!!(u&&G({face:u,frame:n})),_=u?{pitch:u.pitch,yaw:u.yaw,roll:u.roll}:null,v=_?d({alignment:_,blendshapes:u?.blendshapes??{},neutral:a,pose:r,options:t}):null,y=u?l({pitch:u.pitch,pose:r,requireEyeLevelCamera:o,options:t}):null,x=null,S=`Keep one face in view`;if(u&&(S=null,m?S=`In polygon`:h?S=`Face too small`:g?v?.code&&(S=v.code):S=`Center your face in the circle`),!u)x=`FACE_NOT_DETECTED`;else if(m)x=`FACE_IN_POLYGON`;else if(h)x=`FACE_TOO_SMALL`;else if(!g)x=`FACE_NOT_CENTERED`;else if(y){let{translate:e}=b({language:s});x=y,S=e(p())}return{faces:c,face:u,faceInPolygon:m,centered:g,framing:x,guidance:v,alignment:_,reason:S}},q=async({capture:e,requireEyeLevelCamera:t,neutral:n,pose:r,signal:i,language:a})=>{let o=await R({blob:e});try{i.throwIfAborted();let e=await K({frame:o,pose:r,signal:i,neutral:n,requireEyeLevelCamera:t,language:a}),{face:s,guidance:c}=e,l=U({face:s}),u=c?.code&&e.reason===c.code?N({pose:r,rejection:c.code,language:a}):e.reason;if(!s||u)return{vector:null,reason:u,eyeScores:l};let d=V({alignment:`eyes-nose-mouth`,face:s,frame:o}),f=d?await B({face:d}):null;if(i.throwIfAborted(),!f)return{vector:null,reason:x.FACE_NOT_USABLE,eyeScores:l};let p=M(f);return{vector:p,reason:p?null:x.INVALID_MODEL_OUTPUT,eyeScores:l}}finally{o.close()}},J=class{options;view=null;useUi;display=A();events=new EventTarget;controller=null;operationId=``;neutralPose=null;guidanceCodeState=r();correctiveState=s();modelsReady=null;preloading=null;prepared=!1;disposed=!1;subscriptions=new Set;constructor(e){if(this.useUi=e.ui??!e.video,!this.useUi&&!e.video)throw Error(x.INVALID_OPTIONS);this.options=Object.freeze({...e,requireEyeLevelCamera:e.requireEyeLevelCamera??!1,capabilities:Object.freeze([...e.capabilities??[`enroll`,`unlock`]])})}async caniuse(){return await T()}async preload(){if(this.disposed)throw Error(x.SDK_NOT_READY);if(this.preloading)return this.preloading;let e=(async()=>{await C({language:this.options.language}),this.options.capabilities.length>0&&await n({filenames:[`dd.ort`,`fd.ort`,`fl.ort`,`fe.ort`,`fmu.ort`,`ort-wasm-simd-threaded.mjs`,`ort-wasm-simd-threaded.wasm`]})})();this.preloading=e;try{if(await e,this.disposed)throw Error(x.SDK_NOT_READY)}catch(t){throw this.preloading===e&&(this.preloading=null),t}}async prepare(){if(this.disposed)throw Error(x.SDK_NOT_READY);if(this.prepared)return;if(await this.preload(),this.useUi&&!this.view){let{createFaceKeyView:e}=await import(`./view-CHSkN6gO.js`);if(this.disposed)throw Error(x.SDK_NOT_READY);this.view=e({options:this.options,display:this.display,events:this.events,onStop:()=>this.stop()})}if(!this.modelsReady){let e=this.options.capabilities.length>0?Promise.all([F(),L({faceDetector:`standard`}),z()]).then(async()=>{let e=document.createElement(`canvas`);e.width=640,e.height=480;let t=await createImageBitmap(e);try{await Promise.all([I(t),P(t),H()])}finally{t.close()}}):Promise.resolve();this.modelsReady=e}let e=this.modelsReady;try{if(await e,this.disposed)throw Error(x.SDK_NOT_READY);this.prepared=!0}catch(t){throw this.modelsReady===e&&(this.modelsReady=null),t}}async request({path:e,input:t,body:n,signal:r}){let i={authorization:`Bearer ${this.options.clientKey}`,"content-type":`application/json`},a=await fetch(`${(this.options.apiUrl??`https://api.voltom.io`).replace(/\/$/,``)}/facekey/${e}`,{method:`POST`,headers:i,body:JSON.stringify(n??t),signal:r}),o=await a.json();if(r.throwIfAborted(),!a.ok)throw Error(typeof o.code==`string`?o.code:x.INVALID_SERVICE_RESPONSE);return o}async capture({poses:e,signal:t,expiresAt:n,operation:i,input:o}){let l=this.useUi?this.view?.requiredVideo():this.options.video;if(!l)throw Error(x.INVALID_OPTIONS);let{translate:d}=b({language:this.options.language}),p=[];this.display.progress.value={completed:0,total:e.length},this.neutralPose=null,this.guidanceCodeState=r(),this.correctiveState=s();let m=null,_={userId:o.userId??``,matched:!1,matches:[],reason:null},C=o.token;t.throwIfAborted();let T=await w({facingMode:`user`,video:l,signal:t});t.throwIfAborted(),this.display.facingMode.value=T,this.display.phase.value=`capturing`;for(let[y,b]of e.entries()){let w=0,T=null;for(this.guidanceCodeState=r(),this.correctiveState=s(),a(()=>{this.display.match.value=null,this.display.phase.value=`capturing`,this.display.guidance.value=null,this.display.corrective.value=null,this.display.instruction.value={framing:null,retry:null}});w<3;){if(await E({video:l,signal:t}),t.throwIfAborted(),Date.now()>=Date.parse(n))throw Error(x.FACEKEY_TOKEN_INVALID);if(l.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)continue;let r=await createImageBitmap(l);try{let s=await K({frame:r,pose:b,signal:t,neutral:this.neutralPose,requireEyeLevelCamera:this.options.requireEyeLevelCamera??!1,language:this.options.language}),{framing:l,guidance:E}=s,D=E?.code??null;if(w=l===null&&D===null?w+1:0,b===`faceStraight`&&D===null&&l===null&&(this.neutralPose=s.alignment),E){this.guidanceCodeState=f({state:this.guidanceCodeState,code:E.code,requiredFrames:3});let e=this.guidanceCodeState.published,t=c({pose:b,code:e}).corrective,n=performance.now();this.correctiveState=u({label:t,now:n,state:this.correctiveState}),this.display.guidance.value={...E,code:e},this.display.corrective.value=h({label:t,now:n,state:this.correctiveState})}let O={...s,frame:r,operation:i,pose:b,poseRejection:D,stable:w};if(this.view?.collectCaptureDebug(O),this.display.instruction.value={framing:l,retry:T},w===3){let s=await S({frame:r});try{if(i===`unlock`){this.display.phase.value=`checking`;let n={token:C,userId:_.userId,poses:[b],faces:[await v({image:s})]},r=await this.request({path:`unlock/step`,input:{...o,token:C},body:n,signal:t});if(r.userId!==_.userId||r.matched&&(r.matches.length!==1||r.matches[0].pose!==b||!r.matches[0].matched))throw Error(x.INVALID_SERVICE_RESPONSE);if(this.display.match.value={accepted:r.matched,reason:r.reason,score:r.matches.length?r.matches[0].score:null},this.view?.collectCaptureDebug({...O,force:!0,reason:r.reason}),!r.matched){if(r.complete||!r.token)throw Error(x.INVALID_SERVICE_RESPONSE);C=r.token,w=0,T=d(`faceRetryPose`),a(()=>{this.display.phase.value=`capturing`,this.display.instruction.value={framing:l,retry:T}}),await this.showFeedback({matched:!1,signal:t});continue}if(_={userId:r.userId,matched:r.complete,matches:[..._.matches,...r.matches],reason:r.reason},r.complete!==(y===e.length-1))throw Error(x.INVALID_SERVICE_RESPONSE);if(!r.complete){if(!r.token)throw Error(x.INVALID_SERVICE_RESPONSE);C=r.token}}else{let e=await q({capture:s,requireEyeLevelCamera:this.options.requireEyeLevelCamera??!1,pose:b,signal:t,language:this.options.language,neutral:this.neutralPose}),r=e.vector;if(t.throwIfAborted(),Date.now()>=Date.parse(n))throw Error(x.FACEKEY_TOKEN_INVALID);let i=m&&r?g({first:m,second:r}):null,o=!!(r&&(i===null||i>.5)),c=e.reason??(o?null:x.POSE_IDENTITY_MISMATCH);if(this.display.match.value={accepted:o,reason:c,reference:!m&&o,score:i},this.view?.collectCaptureDebug({...O,force:!0,reason:c}),!r||!o){w=0,T=d(r?`faceRetryMatch`:`faceRetryUsable`),a(()=>{this.display.phase.value=`capturing`,this.display.instruction.value={framing:l,retry:T}}),r&&await this.showFeedback({matched:!1,signal:t});continue}m||=r}p.push(s)}catch(e){let t=e instanceof Error?e.message:`Capture failed`;throw this.display.match.value={accepted:!1,reason:t,score:null},this.view?.collectCaptureDebug({...O,force:!0,reason:t}),e}}}finally{r.close()}}this.display.progress.value={completed:y+1,total:e.length},await this.showFeedback({matched:!0,signal:t})}return y({video:l}),{captures:p,unlock:_}}async showFeedback({matched:e,signal:t}){t.throwIfAborted();let n=this.operationId;a(()=>{this.display.failures.value=e?0:this.display.failures.value+1,this.display.feedback.value={matched:e,animating:!0}});let r=Promise.withResolvers(),i=setTimeout(()=>r.resolve(),500),o=()=>r.resolve();t.addEventListener(`abort`,o,{once:!0});try{await r.promise,t.throwIfAborted()}finally{clearTimeout(i),t.removeEventListener(`abort`,o),this.operationId===n&&(this.display.feedback.value=e?null:{matched:!1,animating:!1})}}async run({operation:e,input:t,externalSignal:n,debug:r}){if(this.disposed||!this.prepared)throw Error(x.SDK_NOT_READY);if(!this.options.capabilities.includes(e))throw Error(x.SDK_CAPABILITY_NOT_CONFIGURED);if(this.controller)throw Error(x.INVALID_OPTIONS);let i=j(t);if(e!==`enroll`&&!i.userId)throw Error(x.INVALID_OPTIONS);let o=new AbortController;this.controller=o;let s=o.signal,c=()=>o.abort();n?.addEventListener(`abort`,c,{once:!0}),n?.aborted&&c();let l=[];this.operationId=crypto.randomUUID();try{a(()=>{this.display.operation.value=e,this.display.phase.value=`loading`,this.display.instruction.value=null,this.display.guidance.value=null,this.display.corrective.value=null,this.display.feedback.value=null,this.display.failures.value=0,this.display.error.value=null,this.display.debug.value=[],this.display.debugEnabled.value=r??this.options.debug??!1,this.display.match.value=null,this.display.progress.value={completed:0,total:1},this.display.facingMode.value=null}),this.view?.open();let t=await this.request({path:`challenge`,input:i,signal:s});if(t.operation!==e||i.userId&&t.userId!==i.userId)throw Error(x.FACEKEY_TOKEN_INVALID);let n=await this.capture({poses:t.poses,signal:s,expiresAt:t.expiresAt,operation:e,input:{...i,userId:t.userId}});l.push(...n.captures),s.throwIfAborted();let o=n.unlock;if(e===`enroll`){this.display.phase.value=`processing`;let n={token:i.token,userId:t.userId,poses:t.poses,faces:await Promise.all(l.map(e=>v({image:e})))};o=await this.request({path:e,input:i,body:n,signal:s})}let c=!(`matched`in o)||o.matched===!0;return this.display.phase.value=c?`success`:`failure`,await this.showFeedback({matched:c,signal:s}),o}catch(e){throw this.view?.dialog?.open&&a(()=>{this.display.phase.value=`failure`,this.display.error.value=e}),e}finally{n?.removeEventListener(`abort`,c),this.display.debugEnabled.value=this.options.debug??!1,l.length=0;let e=this.useUi?this.view?.dialog?.open?this.view.requiredVideo():null:this.options.video;e&&y({video:e}),this.view?.close(),this.controller=null}}async faceEnroll(e,{signal:t,debug:n}={}){return await this.run({operation:`enroll`,input:e,externalSignal:t,debug:n})}async faceUnlock(e,{signal:t,debug:n}={}){return await this.run({operation:`unlock`,input:e,externalSignal:t,debug:n})}stop(){this.controller&&this.controller.abort(new DOMException(x.VERIFICATION_CANCELLED,`AbortError`));let e=this.useUi?this.view?.dialog?.open?this.view.requiredVideo():null:this.options.video;e&&y({video:e}),this.view?.close()}dispose(){if(!this.disposed){this.disposed=!0,this.stop();for(let e of this.subscriptions)e();this.subscriptions.clear(),this.events=new EventTarget}}getState(){return{operation:this.display.operation.value,phase:this.display.phase.value,instruction:this.display.instruction.value,feedback:this.display.feedback.value,error:this.display.error.value,progress:this.display.progress.value,match:this.display.match.value,debug:this.display.debug.value}}subscribe(e){if(this.disposed)throw Error(x.SDK_NOT_READY);let t=m(()=>e(this.getState()));return this.subscriptions.add(t),()=>{t(),this.subscriptions.delete(t)}}};_({moduleUrl:import.meta.url});var Y=J;export{J as VoltomFaceKey,Y as default};
|
|
2
|
+
import{A as e,Bt as t,Ct as n,Gt as r,Ht as i,I as a,Kt as o,L as s,M as c,Ot as l,Ut as u,Vt as d,_t as f,a as p,at as m,c as h,d as g,dt as _,f as v,gt as y,h as ee,ht as b,i as x,lt as S,m as C,mt as te,n as ne,o as w,ot as T,p as E,qt as D,r as O,s as k,st as A,t as j,u as M,ut as N,w as P,xt as F,yt as I}from"./requests-DW8zDX51.js";import{a as L,i as R,n as z,r as B}from"./facekey.browser-VlDa2K-w.js";import{t as re}from"./presentation-ye0KVm6U.js";var V=t=>{if(!t||typeof t!=`object`)throw i({code:u.INVALID_SERVICE_RESPONSE});ee({intent:t,action:t.action});let n=c.intent.safeParse({...t,poses:t.poses??[...e]});if(!n.success||n.data.poses.length===0||new Set(n.data.poses).size!==n.data.poses.length)throw i({code:u.INVALID_SERVICE_RESPONSE,cause:t});return n.data},H=e=>e.length===512&&e.every(e=>Number.isFinite(e))&&Math.abs(Math.hypot(...e)-1)<.001?e:null,U=({pose:e,rejection:t,language:n})=>{let{translate:r}=F({language:n});return r(t?E({code:t}):v({pose:e}).primary)},{detectDocumentBox:W,loadDocumentBoxDetector:G}=z,{detectPictureFaces:K,loadFaceDetector:q}=B,{imageBitmap:J,loadFaceMatch:Y,preparedFaceGrayscaleEmbedding:X,prepareFace:ie,warmupFaceMatch:ae}=L,{detectFaceLiveness:oe,loadFaceLiveness:se}=R,ce=({face:e})=>e?{left:e.blendshapes.eyeBlinkLeft??0,right:e.blendshapes.eyeBlinkRight??0}:null,Z=({face:e,frame:t})=>e.boundingRect.height/Math.min(t.width,t.height)<.5?`FACE_TOO_SMALL`:null,le=({face:e,frame:t})=>{let n=e.boundingRect.x+e.boundingRect.width/2,r=e.boundingRect.y+e.boundingRect.height/2,i=Math.min(t.width,t.height);return Math.hypot(n-t.width/2,r-t.height/2)<=i*.08},Q=async({frame:e,pose:t,signal:n,neutral:r,requireEyeLevelCamera:i,language:o})=>{let c=await K(e);n.throwIfAborted();let l=c.length===1?c[0]:null,u=l?await W(e):null;n.throwIfAborted();let d=!!(l&&u&&a({face:l,polygon:u.polygon})),f=!!(l&&Z({face:l,frame:e})),p=!!(l&&le({face:l,frame:e})),m=l?{pitch:l.pitch,yaw:l.yaw,roll:l.roll}:null,h=m?x({alignment:m,blendshapes:l?.blendshapes??{},neutral:r,pose:t,options:s}):null,g=l?O({pitch:l.pitch,pose:t,requireEyeLevelCamera:i,options:s}):null,_=null,v=`Keep one face in view`;if(l&&(v=null,d?v=`In polygon`:f?v=`Face too small`:p?h?.code&&(v=h.code):v=`Center your face in the circle`),!l)_=`FACE_NOT_DETECTED`;else if(d)_=`FACE_IN_POLYGON`;else if(f)_=`FACE_TOO_SMALL`;else if(!p)_=`FACE_NOT_CENTERED`;else if(g){let{translate:e}=F({language:o});_=g,v=e(ne())}return{faces:c,face:l,faceInPolygon:d,centered:p,framing:_,guidance:h,alignment:m,reason:v}},ue=async({capture:e,requireEyeLevelCamera:t,neutral:n,pose:r,signal:a,language:o})=>{let s=await J({blob:e});try{a.throwIfAborted();let e=await Q({frame:s,pose:r,signal:a,neutral:n,requireEyeLevelCamera:t,language:o}),{face:c,guidance:l}=e,d=ce({face:c}),f=l?.code&&e.reason===l.code?U({pose:r,rejection:l.code,language:o}):e.reason;if(!c||f)return{vector:null,reason:f,eyeScores:d};let p=await oe({detection:c,frame:s});if(a.throwIfAborted(),!p.live)throw i({code:u.FACE_SPOOF_DETECTED});let m=ie({alignment:`eyes-nose-mouth`,face:c,frame:s}),h=m?await X({face:m}):null;if(a.throwIfAborted(),!h)return{vector:null,reason:u.FACE_NOT_USABLE,eyeScores:d};let g=H(h);return{vector:g,reason:g?null:u.INVALID_MODEL_OUTPUT,eyeScores:d}}finally{s.close()}},$=class{static Errors=u;static isSdkError=t;options;view=null;display=re();events=new EventTarget;controller=null;operationId=``;neutralPose=null;guidanceCodeState=w();correctiveState=p();modelsReady=null;preloading=null;prepared=!1;disposed=!1;subscriptions=new Set;constructor(e){S({options:e,capabilities:[`enroll`,`unlock`],authorizeRequired:!0});let{prepare:t=m.prepare,...n}=e;if(typeof n.authorize!=`function`)throw i({code:u.INVALID_OPTIONS});this.options=Object.freeze({debug:m.debug,...A(n),...T(n),requireEyeLevelCamera:n.requireEyeLevelCamera??!0,capabilities:Object.freeze([...n.capabilities??[`enroll`,`unlock`]])}),t&&this.prepare().catch(e=>console.error(e))}async caniuse(){return await _()}async preload(){try{await this.preloadInternal()}catch(e){throw d({error:e,fallback:u.MODEL_LOAD_FAILED})}}async preloadInternal(){if(this.disposed)throw i({code:u.SDK_DISPOSED});if(this.preloading)return this.preloading;let e=(async()=>{await n({language:this.options.language}),this.options.capabilities.length>0&&await l({filenames:[`dd.ort`,`fd.ort`,`fl.ort`,`fe.ort`,`flv.ort`,`flw.ort`,`fmu.ort`,`ort-wasm-simd-threaded.mjs`,`ort-wasm-simd-threaded.wasm`]})})();this.preloading=e;try{if(await e,this.disposed)throw i({code:u.SDK_DISPOSED})}catch(t){throw this.preloading===e&&(this.preloading=null),d({error:t,fallback:u.MODEL_LOAD_FAILED})}}async prepare(){try{await this.prepareModels()}catch(e){throw d({error:e,fallback:u.MODEL_LOAD_FAILED})}}async prepareModels(){if(this.disposed)throw i({code:u.SDK_DISPOSED});if(this.prepared)return;if(await this.preload(),!this.view){let{createFaceKeyView:e}=await import(`./view-Cb4XCb-z.js`);if(this.disposed)throw i({code:u.SDK_DISPOSED});this.view=e({options:this.options,display:this.display,events:this.events,onStop:()=>this.stop()})}if(!this.modelsReady){let e=this.options.capabilities.length>0?Promise.all([G(),q({faceDetector:`standard`}),se(),Y()]).then(async()=>{let e=document.createElement(`canvas`);e.width=640,e.height=480;let t=await createImageBitmap(e);try{await Promise.all([K(t),W(t),ae()])}finally{t.close()}}):Promise.resolve();this.modelsReady=e}let e=this.modelsReady;try{if(await e,this.disposed)throw i({code:u.SDK_DISPOSED});this.prepared=!0}catch(t){throw this.modelsReady===e&&(this.modelsReady=null),d({error:t,fallback:u.MODEL_LOAD_FAILED})}}async request({path:e,input:t,body:n,signal:r}){return await j({apiUrl:this.options.apiUrl,path:`/facekey/${e}`,clientKey:this.options.clientKey,body:JSON.stringify(n??t),signal:r})}async capture({poses:e,signal:t,expiresAt:n,operation:r}){let a=this.view?.requiredVideo();if(!a)throw i({code:u.UI_ELEMENT_NOT_FOUND});let{translate:s}=F({language:this.options.language}),c=[];this.display.progress.value={completed:0,total:e.length},this.neutralPose=null,this.guidanceCodeState=w(),this.correctiveState=p();let l=null;t.throwIfAborted();let d=await y({facingMode:`user`,video:a,signal:t});t.throwIfAborted(),this.display.facingMode.value=d,this.display.phase.value=`capturing`;for(let[d,f]of e.entries()){let m=0,_=null;for(this.guidanceCodeState=w(),this.correctiveState=p(),o(()=>{this.display.match.value=null,this.display.phase.value=`capturing`,this.display.guidance.value=null,this.display.corrective.value=null,this.display.instruction.value={framing:null,retry:null}});m<3;){if(await I({video:a,signal:t}),t.throwIfAborted(),Date.now()>=Date.parse(n))throw i({code:u.INTENT_TOKEN_INVALID});if(a.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)continue;let e=await createImageBitmap(a);try{let a=await Q({frame:e,pose:f,signal:t,neutral:this.neutralPose,requireEyeLevelCamera:this.options.requireEyeLevelCamera??!0,language:this.options.language}),{framing:d,guidance:p}=a,v=p?.code??null;if(m=d===null&&v===null?m+1:0,f===`faceStraight`&&v===null&&d===null&&(this.neutralPose=a.alignment),p){this.guidanceCodeState=h({state:this.guidanceCodeState,code:p.code,requiredFrames:3});let e=this.guidanceCodeState.published,t=M({pose:f,code:e}).corrective,n=performance.now();this.correctiveState=k({label:t,now:n,state:this.correctiveState}),this.display.guidance.value={...p,code:e},this.display.corrective.value=g({label:t,now:n,state:this.correctiveState})}let y={...a,frame:e,operation:r,pose:f,poseRejection:v,stable:m};if(this.view?.collectCaptureDebug(y),this.display.instruction.value={framing:d,retry:_},m===3){let r=await te({frame:e});try{let e=await ue({capture:r,requireEyeLevelCamera:this.options.requireEyeLevelCamera??!0,pose:f,signal:t,language:this.options.language,neutral:this.neutralPose}),a=e.vector;if(t.throwIfAborted(),Date.now()>=Date.parse(n))throw i({code:u.INTENT_TOKEN_INVALID});let p=l&&a?P({first:l,second:a}):null,h=!!(a&&(p===null||p>.5)),g=e.reason??(h?null:u.POSE_IDENTITY_MISMATCH);if(this.display.match.value={accepted:h,reason:g,reference:!l&&h,score:p},this.view?.collectCaptureDebug({...y,force:!0,reason:g}),!a||!h){m=0,_=s(a?`faceRetryMatch`:`faceRetryUsable`),o(()=>{this.display.phase.value=`capturing`,this.display.instruction.value={framing:d,retry:_}}),a&&await this.showFeedback({matched:!1,signal:t});continue}l||=a,c.push(r)}catch(e){let t=e instanceof Error?e.message:`Capture failed`;throw this.display.match.value={accepted:!1,reason:t,score:null},this.view?.collectCaptureDebug({...y,force:!0,reason:t}),e}}}finally{e.close()}}this.display.progress.value={completed:d+1,total:e.length},await this.showFeedback({matched:!0,signal:t})}return f({video:a}),{captures:c}}async showFeedback({matched:e,signal:t}){t.throwIfAborted();let n=this.operationId;o(()=>{this.display.failures.value=e?0:this.display.failures.value+1,this.display.feedback.value={matched:e,animating:!0}});let r=Promise.withResolvers(),i=setTimeout(()=>r.resolve(),500),a=()=>r.resolve();t.addEventListener(`abort`,a,{once:!0});try{await r.promise,t.throwIfAborted()}finally{clearTimeout(i),t.removeEventListener(`abort`,a),this.operationId===n&&(this.display.feedback.value=e?null:{matched:!1,animating:!1})}}async run({operation:e,externalSignal:t,debug:n}){if(this.disposed)throw i({code:u.SDK_DISPOSED});if(!this.options.capabilities.includes(e))throw i({code:u.SDK_CAPABILITY_NOT_CONFIGURED});if(this.controller)throw i({code:u.OPERATION_IN_PROGRESS});let a=new AbortController;this.controller=a;let s=a.signal,l=()=>a.abort(i({code:u.OPERATION_CANCELLED}));t?.addEventListener(`abort`,l,{once:!0}),t?.aborted&&l();let p=[];this.operationId=crypto.randomUUID();try{s.throwIfAborted(),await r({operation:this.prepare(),signal:s}),s.throwIfAborted(),o(()=>{this.display.operation.value=e,this.display.phase.value=`loading`,this.display.instruction.value=null,this.display.guidance.value=null,this.display.corrective.value=null,this.display.feedback.value=null,this.display.failures.value=0,this.display.error.value=null,this.display.debug.value=[],this.display.debugEnabled.value=n??this.options.debug??!1,this.display.match.value=null,this.display.progress.value={completed:0,total:1},this.display.facingMode.value=null});let t=await r({operation:C({task:()=>this.options.authorize({action:e})}),signal:s});s.throwIfAborted();let a=V(t);if(a.action!==e)throw i({code:u.INTENT_TOKEN_INVALID});this.view?.open();let l=await this.capture({poses:a.poses,signal:s,expiresAt:a.expiresAt,operation:e});p.push(...l.captures),s.throwIfAborted(),this.display.phase.value=`processing`;let d={token:a.token,subjectId:a.subjectId,poses:a.poses,faces:await Promise.all(p.map(e=>b({image:e})))},f=await this.request({path:e,input:{token:a.token,subjectId:a.subjectId},body:d,signal:s}),m=e===`enroll`?c.identity.safeParse(f):c.unlock.safeParse(f);if(!m.success||m.data.subjectId!==a.subjectId)throw i({code:u.INVALID_SERVICE_RESPONSE});let h={...m.data,resultId:a.resultId};`matched`in h&&(this.display.match.value={accepted:h.matched,reason:h.reason,score:h.matches[0]?.score??null});let g=!(`matched`in h)||h.matched===!0;return this.display.phase.value=g?`success`:`failure`,await this.showFeedback({matched:g,signal:s}),h}catch(e){let t=d({error:e,signal:s});throw this.view?.dialog?.open&&o(()=>{this.display.phase.value=`failure`,this.display.error.value=t}),t}finally{t?.removeEventListener(`abort`,l),this.display.debugEnabled.value=this.options.debug??!1,p.length=0;let e=this.view?.dialog?.open?this.view.requiredVideo():null;e&&f({video:e}),this.view?.close(),this.controller=null}}setDebug({enabled:e}){if(this.disposed)throw i({code:u.SDK_DISPOSED});if(typeof e!=`boolean`)throw i({code:u.INVALID_OPTIONS});this.options=Object.freeze({...this.options,debug:e}),this.display.debugEnabled.value=e,e||(this.display.debug.value=[])}async faceEnroll(e={}){N({options:e});let{signal:t,debug:n}=e;return await this.run({operation:`enroll`,externalSignal:t,debug:n})}async faceUnlock(e={}){N({options:e});let{signal:t,debug:n}=e;return await this.run({operation:`unlock`,externalSignal:t,debug:n})}stop(){this.controller&&this.controller.abort(i({code:u.OPERATION_CANCELLED}));let e=this.view?.dialog?.open?this.view.requiredVideo():null;e&&f({video:e}),this.view?.close()}dispose(){if(!this.disposed){this.disposed=!0,this.stop();for(let e of this.subscriptions)e();this.subscriptions.clear(),this.events=new EventTarget}}getState(){return{operation:this.display.operation.value,phase:this.display.phase.value,instruction:this.display.instruction.value,feedback:this.display.feedback.value,error:this.display.error.value,progress:this.display.progress.value,match:this.display.match.value,debug:this.display.debug.value}}subscribe(e){if(this.disposed)throw i({code:u.SDK_DISPOSED});let t=D(()=>e(this.getState()));return this.subscriptions.add(t),()=>{t(),this.subscriptions.delete(t)}}},de=$;export{u as Errors,$ as VoltomFaceKey,de as default,t as isSdkError};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
|
|
2
|
+
import{$ as e,B as t,C as n,D as r,Dt as i,E as a,Ft as o,G as s,H as c,Ht as l,I as u,J as d,Jt as f,K as p,Pt as m,R as h,Tt as g,U as _,Ut as v,V as y,W as b,Wt as x,X as S,Y as C,Z as w,_ as T,a as E,b as D,c as O,d as k,ft as A,g as j,i as M,jt as N,l as ee,mt as te,n as P,nt as F,o as ne,p as I,q as L,r as re,rt as ie,s as ae,tt as oe,v as se,wt as ce,x as le,y as ue,yt as de,z as fe}from"./requests-DW8zDX51.js";var pe=({box:e,image:t})=>{let n=Math.max(0,Math.floor(e.left)),r=Math.max(0,Math.floor(e.top)),i=Math.min(t.width,Math.ceil(e.right)),a=Math.min(t.height,Math.ceil(e.bottom)),o=Math.max(1,i-n),s=Math.max(1,a-r),c=new Uint8ClampedArray(o*s*4);for(let e=0;e<s;e+=1){let i=((r+e)*t.width+n)*4,a=e*o*4;c.set(t.data.subarray(i,i+o*4),a)}return{data:c,height:s,width:o}},me=({height:e,image:t,width:n})=>{let r=new Uint8ClampedArray(n*e*4),i=t.width/n,a=t.height/e;for(let o=0;o<e;o+=1){let e=Math.min(t.height-1,Math.floor((o+.5)*a));for(let a=0;a<n;a+=1){let s=Math.min(t.width-1,Math.floor((a+.5)*i)),c=(e*t.width+s)*4,l=(o*n+a)*4;r[l]=t.data[c]??0,r[l+1]=t.data[c+1]??0,r[l+2]=t.data[c+2]??0,r[l+3]=255}}return{data:r,height:e,width:n}},he=.3,ge=.6,_e=12,ve=3,ye=async({session:e,tensor:t})=>{let n=performance.now();try{let n=await e.run({[e.inputNames[0]]:t}),r=n[e.outputNames[0]];if(!r){for(let e of Object.values(n))e.dispose();throw Error(v.INVALID_MODEL_OUTPUT)}for(let e of Object.values(n))e!==r&&e.dispose();return r}catch(e){throw Error(x({error:e,fallback:v.INFERENCE_FAILED}),{cause:e})}finally{F({category:`inference`,duration:performance.now()-n,key:`ocr`}),t.dispose()}},be=({text:e})=>e.normalize(`NFKC`).replace(/\r\n?/gu,`
|
|
3
|
+
`).replace(/[\t\f\v ]+/gu,` `).replace(/ *\n */gu,`
|
|
4
|
+
`).trim(),xe=({pixels:e,runtime:t})=>{let n=Math.max(32,Math.ceil(e.width/32)*32),r=Math.max(32,Math.ceil(e.height/32)*32),i=new Float32Array(3*n*r),a=[.485,.456,.406],o=[.229,.224,.225];for(let e=0;e<3;e+=1)i.fill((1-(a[e]??0))/(o[e]??1),e*n*r,(e+1)*n*r);for(let t=0;t<e.height;t+=1)for(let s=0;s<e.width;s+=1){let c=(t*e.width+s)*4,l=t*n+s;for(let t=0;t<3;t+=1){let s=(e.data[c+t]??0)/255;i[t*n*r+l]=(s-(a[t]??0))/(o[t]??1)}}return{height:r,tensor:new t.Tensor(`float32`,i,[1,3,r,n]),width:n}},Se=({height:e,scores:t,width:n})=>{let r=new Uint8Array(n*e),i=[],a=new Int32Array(n*e);for(let o=0;o<t.length;o+=1){if(r[o]||(t[o]??0)<he)continue;let s=0,c=1,l=o%n,u=l,d=Math.floor(o/n),f=d,p=0,m=0;for(a[0]=o,r[o]=1;s<c;){let i=a[s]??0;s+=1;let o=i%n,h=Math.floor(i/n);l=Math.min(l,o),u=Math.max(u,o),d=Math.min(d,h),f=Math.max(f,h),p+=t[i]??0,m+=1;for(let i=-1;i<=1;i+=1)for(let s=-1;s<=1;s+=1){let l=o+s,u=h+i;if(l<0||l>=n||u<0||u>=e)continue;let d=u*n+l;r[d]||(t[d]??0)<he||(r[d]=1,a[c]=d,c+=1)}}let h=u-l+1,g=f-d+1;if(m<_e||h<ve||g<ve||p/m<ge)continue;let _=h*.25,v=g*.35;i.push({bottom:f+1+v,left:l-_,right:u+1+_,score:p/m,top:d-v})}return i},Ce=({boxes:e})=>e.sort((e,t)=>{let n=e.bottom-e.top,r=t.bottom-t.top,i=Math.max(n,r)*.6;return Math.abs(e.top-t.top)<=i?e.left-t.left:e.top-t.top}),we=async({pixels:e,runtime:t,session:n})=>{let r=xe({pixels:e,runtime:t}),i=await ye({session:n,tensor:r.tensor});try{let e=Number(i.dims.at(-2)),t=Number(i.dims.at(-1)),n=Se({height:e,scores:i.data,width:t}),a=r.width/t,o=r.height/e;return Ce({boxes:n.map(({bottom:e,left:t,right:n,top:r})=>({bottom:e*o,left:t*a,right:n*a,top:r*o}))})}finally{i.dispose()}},Te=({pixels:e,runtime:t,model:n})=>{let r=n.recognitionHeight,i=Math.max(1,Math.round(e.width/e.height*r)),a=Math.max(32,Math.ceil(i/32)*32),o=me({height:r,image:e,width:i}),s=new Float32Array(3*a*r);for(let e=0;e<r;e+=1)for(let t=0;t<i;t+=1){let c=(e*i+t)*4,l=e*a+t,u=o.data[c],d=o.data[c+1],f=o.data[c+2],p=u*.299+d*.587+f*.114;s[l]=((n.channels===`grayscale`?p:f)/255-.5)/.5,s[a*r+l]=((n.channels===`grayscale`?p:d)/255-.5)/.5,s[2*a*r+l]=((n.channels===`grayscale`?p:u)/255-.5)/.5}return new t.Tensor(`float32`,s,[1,3,r,a])},Ee=({text:e})=>{let t=[],n=``;for(let r of e)/[a-zA-Z0-9 :*./%+-]/u.test(r)?n+=r:(n&&t.push(n),t.push(r),n=``);return n&&t.push(n),t.reverse().join(``)},De=({dictionary:e,output:t,reverse:n})=>{let r=Number(t.dims.at(-1)),i=Number(t.dims.at(-2)),a=e[0]===``?[...e]:[``,...e];if(a.length===r-1&&a.push(` `),a.length!==r)throw Error(v.OCR_DICTIONARY_MISMATCH);let o=-1,s=``;for(let e=0;e<i;e+=1){let n=e*r,i=0,c=t.data[n]??-1/0;for(let e=1;e<r;e+=1){let r=t.data[n+e]??-1/0;r<=c||(i=e,c=r)}i!==0&&i!==o&&(s+=a[i]??``),o=i}let c=s.trim();return n?Ee({text:c}):c},Oe=({lines:e})=>e.filter((t,n)=>{let r=t.box.width*t.box.height;return!e.some((e,i)=>{if(i===n||!e.text.endsWith(t.text))return!1;let a=e.box.width*e.box.height;if(a<r||e.text.length===t.text.length&&a===r&&i>n)return!1;let o=Math.max(0,Math.min(t.box.x+t.box.width,e.box.x+e.box.width)-Math.max(t.box.x,e.box.x)),s=Math.max(0,Math.min(t.box.y+t.box.height,e.box.y+e.box.height)-Math.max(t.box.y,e.box.y));return r>0&&o*s>=r*.95})}),ke=async({adapter:e,model:t})=>{let[n,r,i]=await Promise.all([e.session(t.detection),e.session(t.recognition),e.load(t.dictionary)]),a=new TextDecoder().decode(i).replace(/\r/gu,``).split(`
|
|
5
|
+
`);for(;a.at(-1)===``;)a.pop();return{model:t.id,assets:[t.detection,t.recognition,t.dictionary],recognize:async({image:i})=>{let o=await e.decode(i),s=await we({pixels:o,runtime:e.runtime,session:n}),c=[];for(let n of s){let i=Te({pixels:pe({box:n,image:o}),runtime:e.runtime,model:t}),s=await ye({session:r,tensor:i}),l;try{l=De({dictionary:a,output:s,reverse:t.reverseArabic})}finally{s.dispose()}if(!l)continue;let u={height:Math.max(0,Math.min(o.height,n.bottom)-Math.max(0,n.top)),width:Math.max(0,Math.min(o.width,n.right)-Math.max(0,n.left)),x:Math.max(0,n.left),y:Math.max(0,n.top)};c.push({angle:0,box:u,confidence:null,text:l,words:[{box:u,confidence:null,text:l}]})}let l=Oe({lines:c}),u=be({text:l.map(e=>e.text).join(`
|
|
6
|
+
`)});return{engine:t.id,height:o.height,lines:l,text:u,width:o.width}}}},R=`odm.ort`,Ae={tiny:{id:`tiny`,detection:`od.ort`,recognition:`or.ort`,dictionary:`ot.txt`,recognitionHeight:48,channels:`grayscale`,reverseArabic:!1},small:{id:`small`,detection:`ods.ort`,recognition:`ors.ort`,dictionary:`ots.txt`,recognitionHeight:48,channels:`grayscale`,reverseArabic:!1},japanese:{id:`japanese`,detection:R,recognition:`orj.ort`,dictionary:`otj.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},"chinese-simplified":{id:`chinese-simplified`,detection:R,recognition:`orcs.ort`,dictionary:`otcs.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},"chinese-traditional":{id:`chinese-traditional`,detection:R,recognition:`orct.ort`,dictionary:`otct.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},cyrillic:{id:`cyrillic`,detection:R,recognition:`orc.ort`,dictionary:`otc.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!1},arabic:{id:`arabic`,detection:R,recognition:`ora.ort`,dictionary:`ota.txt`,recognitionHeight:48,channels:`bgr`,reverseArabic:!0}},je={eng:`eng`,en:`eng`,english:`eng`,latin:`latin`,deu:`latin`,de:`latin`,fra:`latin`,fr:`latin`,ita:`latin`,it:`latin`,por:`latin`,pt:`latin`,spa:`latin`,es:`latin`,jpn:`jpn`,ja:`jpn`,japan:`jpn`,chi_sim:`chi_sim`,zh:`chi_sim`,"zh-cn":`chi_sim`,"zh-hans":`chi_sim`,chi_tra:`chi_tra`,ch:`chi_tra`,"zh-tw":`chi_tra`,"zh-hant":`chi_tra`,rus:`rus`,ru:`rus`,ara:`ara`,ar:`ara`},Me=({language:e})=>{let t=je[e.trim().toLowerCase()];if(!t)throw Error(v.OCR_LANGUAGE_UNSUPPORTED);return t},Ne={eng:`tiny`,latin:`tiny`,jpn:`japanese`,chi_sim:`chinese-simplified`,chi_tra:`chinese-traditional`,rus:`cyrillic`,ara:`arabic`},Pe=({language:e,engine:t=`auto`})=>{let n=Me({language:e}),r=Ae[t===`auto`?Ne[n]:t];if(!r)throw Error(v.OCR_MODEL_UNSUPPORTED);return r},Fe=({language:e,engine:t})=>{let n=Pe({environment:`browser`,language:e,engine:t});return[n.detection,n.recognition,n.dictionary]},Ie=({adapter:e,environment:t})=>{let n=new Map,r=async r=>{if(r.environment!==t)throw Error(v.OCR_ENVIRONMENT_MISMATCH);let i=Pe(r),a=n.get(i.id);a||(a=ke({adapter:e,model:i}),n.set(i.id,a));try{return await a}catch(e){throw n.get(i.id)===a&&n.delete(i.id),e}};return{getOcr:r,ocr:async({image:e,language:n=`eng`,engine:i})=>await(await r({environment:t,language:n,engine:i})).recognize({image:e})}},Le=async({cache:e,key:t,load:n})=>{let r=e.get(t);r||(r=n(),e.set(t,r));try{return await r}catch(n){throw e.get(t)===r&&e.delete(t),n}},Re=new Map,{getOcr:ze,ocr:Be}=Ie({adapter:{decode:async e=>{if(!(e instanceof Blob)&&!(e instanceof Uint8Array))return e;let t=e instanceof Uint8Array?new Blob([e]):e,n=await d.createImageBitmap(t);try{return C({frame:n})}finally{n.close()}},load:async e=>await Le({cache:Re,key:e,load:async()=>{try{return await i({filename:e})}catch(e){throw Error(v.MODEL_LOAD_FAILED,{cause:e})}}}),session:async t=>await e({filename:t}),runtime:ie},environment:`browser`}),Ve=.24,He=.7,Ue=.16,We=({data:e,height:t,text:n,width:r})=>{let i=new Uint8Array(r*t);for(let t=0;t<i.length;t+=1){let n=t*4;i[t]=Math.round((e[n]??0)*.299+(e[n+1]??0)*.587+(e[n+2]??0)*.114)}let a=[];for(let e=0;e<t;e+=1)for(let n=0;n<r;n+=1){let o=e*r+n,s=i[o]??0;n+1<r&&a.push(s>=(i[o+1]??0)),e+1<t&&a.push(s>=(i[o+r]??0))}let o=new Uint8Array(Math.ceil(a.length/8));for(let[e,t]of a.entries())t&&(o[Math.floor(e/8)]|=1<<e%8);let s=[];for(let e=0;e<8;e+=1)for(let n=0;n<8;n+=1){let a=0,o=0;for(let s=Math.floor(e*t/8);s<Math.floor((e+1)*t/8);s+=1)for(let e=Math.floor(n*r/8);e<Math.floor((n+1)*r/8);e+=1)a+=i[s*r+e]??0,o+=1;s.push(o?a/o:0)}let c=s.reduce((e,t)=>e+t,0)/s.length,l=new Uint8Array(Math.ceil(s.length/8));for(let[e,t]of s.entries())t>=c&&(l[Math.floor(e/8)]|=1<<e%8);return{edgeHash:o,appearanceHash:l,textTokens:[...new Set(n.toUpperCase().normalize(`NFKC`).split(/[^\p{L}\d]+/u).filter(e=>e.length>=3))]}},Ge=({value:e})=>{let t=0,n=e;for(;n;)t+=n&1,n>>>=1;return t},z=({front:e,current:t})=>{if(!e||!t||e.edgeHash.length!==t.edgeHash.length||e.appearanceHash.length!==t.appearanceHash.length)return{distinct:!1,imageDistance:null,textOverlap:null};let n=e.edgeHash.reduce((e,n,r)=>e+Ge({value:n^(t.edgeHash[r]??0)}),0)/(e.edgeHash.length*8),r=e.appearanceHash.reduce((e,n,r)=>e+Ge({value:n^(t.appearanceHash[r]??0)}),0)/(e.appearanceHash.length*8),i=t.textTokens.filter(t=>e.textTokens.includes(t)).length,a=Math.min(e.textTokens.length,t.textTokens.length),o=e.textTokens.length>=3&&t.textTokens.length>=3?i/a:null;return{distinct:n>=Ve&&r>=Ue&&(o===null||o<He),imageDistance:n,textOverlap:o}},Ke=({text:e})=>{let t=e.toUpperCase().normalize(`NFKC`).split(`
|
|
7
|
+
`).map(e=>e.replace(/\s+/g,``)),n=t.findIndex(e=>e.startsWith(`P<`)&&e.length>=44&&(e.match(/</g)||[]).length>=2);if(n>=0&&t.slice(n+1).find(e=>/^[A-Z0-9<]{44}$/u.test(e)))return!0;let r=t.findIndex(e=>/^[A-Z0-9]<[A-Z]{3}/u.test(e)&&e.length>=30);return r<0?!1:t.slice(r+1).filter(e=>/^[A-Z0-9<]{30}$/u.test(e)).length>=2},qe={A:`AUT`,B:`BEL`,BG:`BGR`,CY:`CYP`,CZ:`CZE`,D:`DEU`,DK:`DNK`,E:`ESP`,EST:`EST`,F:`FRA`,FIN:`FIN`,GR:`GRC`,H:`HUN`,HR:`HRV`,I:`ITA`,IRL:`IRL`,L:`LUX`,LT:`LTU`,LV:`LVA`,M:`MLT`,NL:`NLD`,P:`PRT`,PL:`POL`,RO:`ROU`,S:`SWE`,SK:`SVK`,SLO:`SVN`},Je=({line:e,start:t,end:n})=>{let r=[],i=0;for(let a of e.words){let o=e.text.indexOf(a.text,i);if(o<0||!a.text.length)continue;i=o+a.text.length;let s=Math.max(t,o),c=Math.min(n,i);c<=s||r.push({...a.box,x:a.box.x+a.box.width*(s-o)/a.text.length,width:a.box.width*(c-s)/a.text.length})}if(!r.length)return{...e.box,x:e.box.x+e.box.width*t/e.text.length,width:e.box.width*(n-t)/e.text.length};let a=Math.min(...r.map(e=>e.x)),o=Math.min(...r.map(e=>e.y));return{x:a,y:o,width:Math.max(...r.map(e=>e.x+e.width))-a,height:Math.max(...r.map(e=>e.y+e.height))-o}},Ye=({line:e})=>{let t=e.text;if(!t.trim()||e.confidence!==null&&e.confidence<=0)return[];if(/^\s*\d{1,2}[./-]\d{1,2}[./-]\d{2,4}\s*$/u.test(t))return[{text:t.trim(),box:e.box,label:null}];let n=[...t.matchAll(/(?:^|\s)(4[a-d]|1[0-4]|[1-9])(?:[.:)]\s*|\s+|$|(?=\d{1,2}[./-]\d))/giu)];if(!n.length)return[{text:t,box:e.box,label:null}];let r=[],i=n[0].index;i>0&&r.push({text:t.slice(0,i).trim(),box:Je({line:e,start:0,end:i}),label:null});for(let[i,a]of n.entries()){let o=a.index+a[0].indexOf(a[1]),s=n[i+1]?.index??t.length,c=t.slice(a.index+a[0].length,s).trim(),l=Je({line:e,start:o,end:s});r.push({text:c,box:l,label:a[1].toLowerCase()})}return r},B=({label:e,fragments:t})=>{let n=t.filter(t=>t.label===e);if(n.length!==1)return null;let r=n[0],i=r.box.height,a=r.text?[r]:[],o=t.filter(e=>e.label&&e!==r);for(let e of t){if(e.label||!e.text)continue;let t=e.box.y-r.box.y,n=Math.abs(t)<Math.max(i,e.box.height)*.5,s=t>=i*.5&&t<=i*2.5;(n||s)&&(e.box.x<r.box.x-i*.5||n&&r.text||o.some(t=>{let n=Math.abs(t.box.y-r.box.y)<i*.5&&t.box.x>r.box.x&&e.box.x>=t.box.x-i*.25,a=t.box.y>r.box.y+i*.5&&t.box.y<=e.box.y+e.box.height*.5&&Math.abs(t.box.x-r.box.x)<i*3;return n||a})||o.some(n=>{let a=e.box.y-n.box.y,o=a>=-i*.5&&a<=i*2.5&&e.box.x>=n.box.x-i*.5,s=Math.abs(t)+Math.abs(e.box.x-r.box.x),c=Math.abs(a)+Math.abs(e.box.x-n.box.x);return o&&c<=s})||a.push(e))}return a.sort((e,t)=>Math.abs(e.box.y-t.box.y)<i*.5?e.box.x-t.box.x:e.box.y-t.box.y),a.map(e=>e.text).join(` `).trim()||null},V=({text:e,allowTwoDigitYear:t=!1})=>{if(!e)return null;let n=e.match(/^(?:(\d{1,2})([./-])(\d{1,2})\2(\d{2,4})|(\d{4})-(\d{2})-(\d{2}))$/u);if(!n)return null;let r=n[4]??n[5],i=Number(n[3]??n[6]),a=Number(n[1]??n[7]),o=Number(r);if(r.length===2){if(!t)return null;let e=new Date,n=e.getUTCFullYear(),r=e.getUTCMonth()+1,s=e.getUTCDate(),c=[1900+o,2e3+o].filter(e=>{let t=n-e-+(r<i||r===i&&s<a);return t>=16&&t<=100});if(c.length!==1)return null;o=c[0]}return o<1e3||i<1||i>12||a<1||a>new Date(Date.UTC(o,i,0)).getUTCDate()?null:`${o}-${String(i).padStart(2,`0`)}-${String(a).padStart(2,`0`)}`},Xe=({ocr:e,image:t})=>{let n=new Set;for(let r of e.lines)for(let e of r.words.length?r.words:[r]){let r=qe[e.text.trim().toUpperCase()],{x:i,y:a,width:o,height:s}=e.box;if(e.confidence!==null&&e.confidence<=0||!r||i<0||a<0||i+o>t.width*.3||a+s>t.height*.35)continue;let c=Math.max(o,s);p({...t,xStart:Math.max(0,i-c)/t.width,xEnd:Math.min(t.width,i+o+c)/t.width,yStart:Math.max(0,a-c)/t.height,yEnd:Math.min(t.height,a+s+c)/t.height,predicate:(e,t,n)=>n>45&&n>e*1.08&&n>t*1.04})>=.15&&n.add(r)}return n.size===1?[...n][0]:null},H=({ocr:e,image:n})=>{if(L(e))return null;let r=e.lines.flatMap(e=>Ye({line:e})),i=new Set(r.map(e=>e.label));if(!(i.has(`1`)||i.has(`2`))||![`3`,`4a`,`4b`,`5`].some(e=>i.has(e)))return null;let a=B({label:`1`,fragments:r}),o=B({label:`2`,fragments:r}),s=a&&/\p{L}/u.test(a)?a:null,c=o&&/\p{L}/u.test(o)?o:null,l=B({label:`3`,fragments:r})?.match(/^(\d{1,2}[./-]\d{1,2}[./-]\d{2,4}|\d{4}-\d{2}-\d{2})(?:\s+(.+))?$/u),u=V({allowTwoDigitYear:!0,text:l?l[1]:null}),d=l&&l[2]?.trim()||null,f=V({text:B({label:`4a`,fragments:r})}),p=V({text:B({label:`4b`,fragments:r})}),m=B({label:`4c`,fragments:r}),h=B({label:`5`,fragments:r}),g=Xe({ocr:e,image:n});return[s,c,u,d,f,p,m,h,g].some(Boolean)?t.parse({document:{source:`OCR`,type:`DRV`,issuing_country:g,issuing_authority:m,number:h,issue_date:f,expiry_date:p,optional_data:null},holder:{first_name:c,last_name:s,middle_name:null,birth_date:u,birth_place:d,sex:null,nationality:null,personal_number:null},address:null,raw_data:{mrz_lines:[],aamva_version:null}}):null},U=null,Ze=async()=>{if(globalThis.window===void 0)return`zxing-wasm/reader`;let e=await g({filename:`zxing-wasm/share.js`});return await g({filename:`zxing-wasm/reader/index.js`,imports:{"../share.js":e}})},Qe=async()=>{let e=await import(await Ze());return globalThis.window!==void 0&&e.setZXingModuleOverrides({wasmBinary:await i({filename:`zxing-wasm/reader/zxing_reader.wasm`})}),e},$e=async()=>{U??=Qe();try{return await U}catch(e){throw U=null,e}},et=async()=>{await(await $e()).prepareZXingModule({fireImmediately:!0})},tt=async({image:e})=>{let t=await(await $e()).readBarcodes(e,{formats:[`PDF417`],tryHarder:!0});for(let e of t)try{let t=fe(e.text);return{type:`aamva`,code:e.text,payload:t}}catch{}return null},nt=({runtime:e,detector:t,alignment:n,text:r,readImage:i})=>{let a=async({image:a,language:o,engine:s,scanBarcodes:c=!1})=>{let l=a instanceof Blob?a:new Blob([a]),u=await e.createImageBitmap(l);try{let a=await t.analyzeDocument({frame:u});if(!a.detection)throw Error(v.DOCUMENT_NOT_FOUND);let l=await n.orientDocumentFrame({frame:u,polygon:a.detection.polygon,orientation:a.detection.orientation});if(!l)throw Error(v.IMAGE_PROCESSING_FAILED);try{let t=b({image:i({frame:u}),polygon:a.detection.polygon,sourceOrientation:l.orientation.rotation}),n=await r.readRectifiedText({frame:l.frame,language:o,engine:s,image:t});if(!n)throw Error(v.DOCUMENT_TEXT_NOT_READABLE);let d=i({frame:l.frame}),f=null;if(c){let t=e.createImageData(d.width,d.height);t.data.set(d.data),f=await tt({image:t})}return{ocr:n,codes:[h({result:n}),f].filter(e=>e!==null),pixels:d,signature:We({...i({frame:l.frame,width:32,height:32}),text:n.text}),blurry:a.isBlurry}}finally{l.frame.close()}}finally{u.close()}};return{classifyDocument:async({document_front:e,document_back:t,language:n,engine:r})=>{let i=await a({image:e,language:n,engine:r}),o=s({image:i.pixels,text:i.ocr.text,codes:i.codes});if(!o)throw Error(v.DOCUMENT_NOT_RECOGNIZED);let c=o.europeanDrivingLicense?H({ocr:i.ocr,image:i.pixels}):null,l=y({document:o.document})&&t?await a({image:t,language:o.europeanDrivingLicense?`latin`:n,engine:o.europeanDrivingLicense?`tiny`:r,scanBarcodes:!0}):null,u=_({classification:{...o,identity:c},front:i,back:l}),d=[...u.reasons],f=l?l.blurry:!1;return(i.blurry||f)&&d.push(v.DOCUMENT_BLURRY),l&&!z({front:i.signature,current:l.signature}).distinct&&d.push(v.DOCUMENT_BACK_NOT_DISTINCT),{identity:c,...o,...u,reasons:d,valid:d.length===0,document_front:i.ocr,document_back:l?l.ocr:null}},detectDocument:async({image:e,language:t})=>{let n=await a({image:e,language:t,scanBarcodes:!0}),r=s({image:n.pixels,text:n.ocr.text,codes:n.codes});if(!r)throw Error(v.DOCUMENT_NOT_RECOGNIZED);let i=n.codes.find(e=>e.type===`mrz`),o=n.codes.find(e=>e.type===`aamva`),c=!!o||r.document===`id`&&!!i;return{identity:!c&&r.europeanDrivingLicense?H({ocr:n.ocr,image:n.pixels}):null,document_type:r.document===`driving_license`?`drv`:r.document,document_side:c?`back`:`front`,mrz_code:i?i.code:null,ammva_code:o?o.code:null}},extractDocumentCodes:async({images:e})=>{let t=[];for(let n of e){let e=await a({image:n,scanBarcodes:!0});t.push(...e.codes)}return[...new Map(t.map(e=>[`${e.type}:${e.code}`,e])).values()]}}},W=8,rt=.16,it=({x:e,y:t,width:n,height:r})=>{let i=e/n,a=t/r;return i<.2||i>=.8||a<.2||a>=.8},at=({value:e})=>{let t=0,n=e;for(;n;)t+=n&1,n>>>=1;return t},ot=({image:e})=>{let t=[];for(let n=0;n<W;n+=1)for(let r=0;r<W;r+=1){let i=0,a=0,o=Math.floor(n*e.height/W),s=Math.floor((n+1)*e.height/W),c=Math.floor(r*e.width/W),l=Math.floor((r+1)*e.width/W);for(let t=o;t<s;t+=1)for(let n=c;n<l;n+=1){if(!it({height:e.height,width:e.width,x:n,y:t}))continue;let r=(t*e.width+n)*4;i+=(e.data[r]??0)*.299+(e.data[r+1]??0)*.587+(e.data[r+2]??0)*.114,a+=1}t.push(a?i/a:0)}let n=t.reduce((e,t)=>e+t,0)/t.length,r=new Uint8Array(Math.ceil(t.length/8));for(let[e,i]of t.entries())i>=n&&(r[Math.floor(e/8)]|=1<<e%8);return{appearanceHash:r}},st=({first:e,second:t})=>{if(e.appearanceHash.length!==t.appearanceHash.length)return{distance:1,matched:!1};let n=e.appearanceHash.reduce((e,n,r)=>e+at({value:n^(t.appearanceHash[r]??0)}),0)/(e.appearanceHash.length*8);return{distance:n,matched:n<=rt}},ct=({candidate:e,identity:t})=>[{missing:!t?.holder.last_name,pattern:/^\s*1[.:)]\s+\p{L}/u},{missing:!t?.holder.first_name,pattern:/^\s*2[.:)]\s+\p{L}/u},{missing:!t?.holder.birth_date,pattern:/^\s*3[.:)]\s+\d{1,2}[./-]\d{1,2}[./-]\d{2,4}/u},{missing:!t?.document.number,pattern:/^\s*5[.:)]\s+[A-Z0-9]/u}].flatMap(({missing:t,pattern:n})=>{if(!t)return[];let r=e.lines.find(e=>n.test(e.text));return r?[r]:[]}),lt=({runtime:e,orientDocumentFrame:t,getOcr:n})=>{let r=`auto`,i=S({runtime:e}),a=async({engine:t=r,language:i=`eng`}={})=>{await n({environment:e.environment,engine:t,language:i})},o=async({classificationImage:t,engine:a=r,frame:o,language:l,image:u})=>{if(o.width<200||o.height<100)return null;let d=u??b({image:i({frame:o}),polygon:[{x:0,y:0},{x:o.width,y:0},{x:o.width,y:o.height},{x:0,y:o.height}]}),f=await(await n({environment:e.environment,engine:`tiny`,language:`latin`})).recognize({image:d}),p=h({result:f}),m=t??i({frame:o}),g=s({image:m,text:f.text,codes:p?[p]:[]}),_=g&&(g.document===`passport`||g.europeanDrivingLicense);if(g?.europeanDrivingLicense){let t=H({ocr:f,image:m});if(!c({identity:t})){let r=await(await n({environment:e.environment,engine:`small`,language:`latin`})).recognize({image:d}),i=H({ocr:r,image:m}),a=s({image:m,text:r.text,codes:[]});if(a?.europeanDrivingLicense&&c({identity:i}))f=r;else if(a?.europeanDrivingLicense){let e=ct({candidate:r,identity:t});if(e.length){let t=[...f.lines,...e];f={...f,lines:t,text:t.map(e=>e.text).join(`
|
|
8
|
+
`)}}}}}else if(!_){let t=Me({language:l??`eng`}),r=await n({environment:e.environment,engine:a,language:t});r.model!==`tiny`&&(f=await r.recognize({image:d}))}let v=o.width/f.width,y=o.height/f.height,x=({x:e,y:t,width:n,height:r})=>({x:e*v,y:t*y,width:n*v,height:r*y});return{...f,width:o.width,height:o.height,lines:f.lines.map(e=>({...e,box:x(e.box),words:e.words.map(e=>({...e,box:x(e.box)}))}))}},l=async e=>await o(e)??{height:e.frame.height,lines:[],text:``,width:e.frame.width};return{loadTextDetector:a,readRectifiedText:o,detectRectifiedText:l,detectDocumentText:async({engine:e=r,frame:n,language:i,polygon:a})=>{let o=await t({frame:n,polygon:a});if(!o)return{height:0,lines:[],rotation:0,text:``,width:0};try{return{...await l({engine:e,frame:o.frame,language:i}),rotation:o.orientation.rotation}}finally{o.frame.close()}}}},ut=({runtime:e,documentAlignment:t,rectifiedDocumentFace:n,orientDocumentFrame:r,restoreRectifiedFace:i,analyzeDocument:a,faceDetection:o,faceMatch:l,textDetection:u})=>{let d=S({runtime:e}),f=({frame:t,text:n})=>{let r=e.createCanvas(32,32),i=r.getContext(`2d`,{willReadFrequently:!0});if(!i)throw Error(v.IMAGE_PROCESSING_FAILED);i.drawImage(t,0,0,r.width,r.height);let{data:a}=i.getImageData(0,0,r.width,r.height);return w({canvas:r}),We({data:a,height:32,text:n,width:32})},p=({current:e,front:t})=>{let n=z({current:e.signature,front:t}),r=[],i=e.signature?.textTokens.length??0,a=Ke({text:e.text.text})||e.text.lines.length>=2&&i>=2;return e.detection||r.push(v.DOCUMENT_NOT_FOUND),e.documentAnalysis.isBlurry&&r.push(v.DOCUMENT_BLURRY),e.hasPictureFace&&r.push(v.DOCUMENT_BACK_CONTAINS_FACE),a||r.push(v.DOCUMENT_TEXT_NOT_READABLE),n.distinct||r.push(v.DOCUMENT_BACK_NOT_DISTINCT),{distinct:n.distinct,imageDistance:n.imageDistance,reasons:r,textOverlap:n.textOverlap,valid:r.length===0}},m=({alignment:e,detection:t,documentAnalysis:n,faceContained:r,requiresFace:i,text:a})=>{let o=[];return t||o.push(v.DOCUMENT_NOT_FOUND),n.isBlurry&&o.push(v.DOCUMENT_BLURRY),i&&!r&&o.push(v.DOCUMENT_FACE_NOT_CONTAINED),(!a.text||a.lines.length<2)&&o.push(v.DOCUMENT_TEXT_NOT_READABLE),!i||e.faceAreaValid&&e.faceDimensionsValid||o.push(v.DOCUMENT_FACE_GEOMETRY_INVALID),i&&(e.faceAdjacentTextLineCount<2||!e.textParallel||e.textSide!==`right`)&&o.push(v.DOCUMENT_TEXT_ALIGNMENT_INVALID),o},g=async({classification:e,codes:r,ocr:a,options:s,documentAnalysis:u,document:d,text:p,prepareForMatch:h})=>{let g=u.detection,_=s.requiresFace??!0,y={boundingRect:{height:d.height,width:d.width,x:0,y:0},polygon:[{x:0,y:0},{x:d.width,y:0},{x:d.width,y:d.height},{x:0,y:d.height}]},b=_?await o.detectDocumentFaces({detection:y,frame:d.frame}):{faces:[],pictureFaces:[],hasPictureFace:await o.detectDocumentFacePresence({detection:y,frame:d.frame})},x=b.pictureFaces.map(e=>i({document:d,face:e})),S=f({frame:d.frame,text:p.text}),C=r.find(e=>e.type===`mrz`)??null,w=null;for(let f of b.faces.length?b.faces:[null]){let y=f?i({document:d,face:f}):null,T=f?n({face:f}):null,E=_&&g?o.faceIsInsideDocument({detection:g,face:y})&&x.every(e=>o.faceIsInsideDocument({detection:g,face:e})):!1,D=t({documentSize:{height:p.height,width:p.width},face:T,lines:p.lines,maxAngleDifference:s.maxDocumentTextAngleDifference,maxFaceAreaRatio:s.maxDocumentFaceAreaRatio,maxFaceHeightRatio:s.maxDocumentFaceHeightRatio,maxFaceWidthRatio:s.maxDocumentFaceWidthRatio,minFaceAreaRatio:s.minDocumentFaceAreaRatio,minFaceHeightRatio:s.minDocumentFaceHeightRatio,minFaceWidthRatio:s.minDocumentFaceWidthRatio}),O=m({alignment:D,detection:g,documentAnalysis:u,faceContained:E,requiresFace:_,text:p});_&&!e&&O.push(v.DOCUMENT_NOT_RECOGNIZED),e?.europeanDrivingLicense&&!c({identity:e.identity})&&O.push(v.DOCUMENT_VALIDATION_FAILED);let k=O.length===0,A=null,j=null;if(_&&k&&f){let e=l.prepareFace({alignment:s.alignment??`eyes-nose-mouth`,face:f,frame:d.frame});if(!e)k=!1,O.push(v.FACE_NOT_USABLE);else if(h){let t=await l.preparedFaceArtifacts({face:e});A=t?.embeddings??null,j=t?.images??null,t||(k=!1,O.push(v.INVALID_MODEL_OUTPUT))}}let M={identity:e?e.identity:null,orientation:d.orientation,ocr:a,mrz:C,alignment:D,detection:g,documentAnalysis:u,documentKind:e?e.document:null,europeanDrivingLicense:e?e.europeanDrivingLicense:!1,codes:r,documentToSource:d.toSource,embeddings:A,images:j,face:y,faceContained:E,hasPictureFace:b.hasPictureFace??x.length>0,failureReasons:O,pictureFaces:x,signature:S,text:p,valid:k};if(M.valid)return M;w??=M}if(!w)throw Error(v.INTERNAL_ERROR);return w},y=async({frame:n,options:i,documentAnalysis:a,prepareForMatch:o=!1})=>{let c=a.detection;if(!c){let e={height:0,lines:[],text:``,width:0},n=t({documentSize:{height:e.height,width:e.width},face:null,lines:e.lines,maxAngleDifference:i.maxDocumentTextAngleDifference,maxFaceAreaRatio:i.maxDocumentFaceAreaRatio,maxFaceHeightRatio:i.maxDocumentFaceHeightRatio,maxFaceWidthRatio:i.maxDocumentFaceWidthRatio,minFaceAreaRatio:i.minDocumentFaceAreaRatio,minFaceHeightRatio:i.minDocumentFaceHeightRatio,minFaceWidthRatio:i.minDocumentFaceWidthRatio});return{identity:null,orientation:null,ocr:null,mrz:null,codes:[],europeanDrivingLicense:!1,alignment:n,detection:c,documentAnalysis:a,documentKind:null,documentToSource:null,embeddings:null,face:null,faceContained:!1,failureReasons:m({alignment:n,detection:c,documentAnalysis:a,faceContained:!1,requiresFace:i.requiresFace??!0,text:e}),images:null,pictureFaces:[],hasPictureFace:!1,signature:null,text:e,valid:!1}}let l=await r({frame:n,polygon:c.polygon,orientation:c.orientation});if(!l)throw Error(v.IMAGE_PROCESSING_FAILED);try{let t=performance.now(),r=b({image:d({frame:n}),polygon:c.polygon,sourceOrientation:l.orientation.rotation}),f=i.requiresFace===!1?`back`:`front`;F({category:`stages`,key:`ocr.prepare.${f}`,duration:performance.now()-t});let p=d({frame:l.frame}),m=await u.readRectifiedText({classificationImage:p,engine:i.ocrEngine,frame:l.frame,language:i.language,image:r}),_=m??{height:l.height,lines:[],text:``,width:l.width},v=m?h({result:m}):null,y=null;if(i.requiresFace===!1){let t=e.createImageData(p.width,p.height);t.data.set(p.data),y=await oe({key:`barcode.back`,operation:()=>tt({image:t})})}let x=[v,y].filter(e=>e!==null),S=s({image:p,text:_.text,codes:x}),C=i.requiresFace!==!1&&S?.europeanDrivingLicense&&m?H({ocr:m,image:p}):null,w=S?{...S,identity:C}:null;return await g({ocr:m,classification:w,codes:x,options:i,documentAnalysis:a,document:l,prepareForMatch:o,text:_})}finally{l.frame.close()}},x=async({frame:e,options:t,prepareForMatch:n=!1})=>{let r=await a({frame:e,minDocumentBoxRatio:t.minDocumentBoxRatio});return await y({frame:e,options:t,documentAnalysis:r,prepareForMatch:n})},C=({analysis:e,isBack:t,front:n})=>{if(!e.ocr)return[v.DOCUMENT_TEXT_NOT_READABLE];if(t&&!n)return[v.CAPTURES_INCOMPLETE];if(!t&&!e.documentKind)return[v.DOCUMENT_NOT_RECOGNIZED];let r={ocr:e.ocr,codes:e.codes},i=t&&n?n:{document:e.documentKind,europeanDrivingLicense:e.europeanDrivingLicense,identity:e.identity};return _({classification:i,front:t&&n?n:r,back:t?r:null}).reasons.filter(e=>t||e!==v.DOCUMENT_BACK_REQUIRED)};return{validateDocumentBack:p,analyzeDocumentFrame:x,hasValidDocumentSideData:e=>C(e).length===0,documentSideFailureReasons:C}},dt=({runtime:e,document:t,readImage:n})=>async({image:r,timings:i})=>{let a=await e.createImageBitmap(new Blob([r]));try{let r=performance.now(),o=await t.analyzeDocument({frame:a});if(i&&(i.documentBoxDetectionMs=performance.now()-r),!o.detection)throw Error(v.DOCUMENT_NOT_FOUND);let{polygon:s,orientation:c}=o.detection,l=b({image:n({frame:a}),polygon:s,sourceOrientation:c?.rotation}),u=e.createCanvas(l.width,l.height);try{let t=u.getContext(`2d`);if(!t)throw Error(v.IMAGE_PROCESSING_FAILED);let n=e.createImageData(l.width,l.height);n.data.set(l.data),t.putImageData(n,0,0);let r=await u.convertToBlob({type:`image/png`});return new Uint8Array(await r.arrayBuffer())}finally{w({canvas:u})}}finally{a.close()}},{alignment:ft,document:G,face:K,attributes:pt,liveness:mt,text:ht,match:q,flow:gt,classify:_t,prepareOcrImage:vt,warmup:yt}=(({runtime:e,getOcr:t,faceMatcher:n})=>{let r=S({runtime:e}),i=T({runtime:e}),a=le({runtime:e}),o=D({runtime:e,imageFromImageBitmap:r}),s=ue({runtime:e}),c=se({runtime:e}),l=lt({runtime:e,getOcr:t,...i}),u=j({runtime:e,...i,...a,...o,faceDetection:o,faceMatcher:n});return{alignment:i,document:a,face:o,attributes:s,liveness:c,text:l,match:u,flow:ut({runtime:e,...i,...a,faceDetection:o,faceMatch:u,textDetection:l}),classify:nt({runtime:e,detector:a,alignment:i,text:l,readImage:r}),prepareOcrImage:dt({runtime:e,document:a,readImage:r}),warmup:async()=>{await Promise.all([o.loadFaceDetector({faceDetector:`standard`}),s.loadFaceAttributes(),c.loadFaceLiveness(),u.loadFaceMatch(),a.loadDocumentBoxDetector(),a.loadDocumentOrientationDetector(),l.loadTextDetector({engine:`tiny`,language:`latin`}),et()])}}})({runtime:d,getOcr:ze}),{classifyDocument:bt,detectDocument:xt,extractDocumentCodes:St}=_t,{detectDocumentOrientation:Ct,loadDocumentOrientationDetector:wt}=G,Tt=[`faceStraight`,`faceUp`,`faceDown`,`faceLeft`,`faceRight`],J=[`faceStraight`,`faceUp`,`faceLeft`,`faceRight`],Y=[...Tt,`faceSmile`,`faceWinkLeft`,`faceTiltLeft`,`faceTiltRight`,`faceReference`];N(Y);var Et={faceStraight:0,faceLeft:1,faceRight:1,faceUp:2,faceDown:2,faceTiltLeft:3,faceTiltRight:3,faceReference:6,faceSmile:4,faceWinkLeft:5},X={faceStraight:`face_straight`,faceUp:`face_up`,faceDown:`face_down`,faceLeft:`face_left`,faceRight:`face_right`,faceSmile:`face_smile`,faceWinkLeft:`face_wink_left`,faceTiltLeft:`face_tilt_left`,faceTiltRight:`face_tilt_right`,faceReference:`face_reference`};N(X),Tt.map(e=>X[e]),J.map(e=>X[e]),o({yaw:m().finite().min(-180).max(180),pitch:m().finite().min(-180).max(180),roll:m().finite().min(-180).max(180)});var Dt=async()=>{let e=await i({filename:`faceMeshLines.json`});return JSON.parse(new TextDecoder().decode(e))},Ot=async()=>{await Dt()},{transformPoint:kt}=ft,At=[`tessellation`,`contours`,`faceOval`,`lips`,`leftEye`,`rightEye`,`leftEyebrow`,`rightEyebrow`,`leftIris`,`rightIris`],jt=async({color:e,context:t,result:n})=>{let r=await Dt();t.beginPath();for(let e of At)for(let{start:i,end:a}of r[e]){let e=n.mesh.landmarks[i],r=n.mesh.landmarks[a];e&&r&&(t.moveTo(e.x,e.y),t.lineTo(r.x,r.y))}t.strokeStyle=e,t.lineWidth=1,t.stroke()},Mt=({backgroundColor:e,color:t,context:n,line:r,toSource:i})=>{if(!r.text)return;let{x:a,y:o,width:s,height:c}=r.box,l=[{x:a,y:o},{x:a+s,y:o},{x:a+s,y:o+c},{x:a,y:o+c}].map(e=>kt({homography:i,point:e})),u=l[0],d=l[1],f=l[3];if(!u||!d||!f)return;let p=Math.hypot(d.x-u.x,d.y-u.y),m=Math.hypot(f.x-u.x,f.y-u.y),h=Math.max(8,Math.min(16,m*.7)),g=Math.max(0,p-4),_=Math.atan2(d.y-u.y,d.x-u.x);n.beginPath(),n.moveTo(u.x,u.y);for(let e of l.slice(1))n.lineTo(e.x,e.y);n.closePath(),n.strokeStyle=t,n.lineWidth=1,n.stroke(),n.save(),n.clip(),n.translate(u.x+2,u.y+2),n.rotate(_),n.font=`${h}px sans-serif`,n.textBaseline=`top`,n.lineWidth=3,n.strokeStyle=e,n.strokeText(r.text,0,0,g),n.fillStyle=t,n.fillText(r.text,0,0,g),n.restore()},Nt=async({element:e,meshLineColor:t,overlayColor:n=`transparent`,result:r})=>{let i=e.getContext(`2d`);if(!i)throw l({code:v.IMAGE_PROCESSING_FAILED});let a=r?.mesh.width??e.width,o=r?.mesh.height??e.height;e.width!==a&&(e.width=a),e.height!==o&&(e.height=o),A({element:e}),n!==`transparent`&&(i.fillStyle=n,i.fillRect(0,0,a,o)),r&&await jt({color:t,context:i,result:r})},Pt=async({documentFaceBoxColor:e,documentFaceMeshColor:t,documentBoxColor:n,element:r,detection:i,face:a,height:o,ocrLines:s=[],ocrToSource:c=null,overlayColor:l=`transparent`,textColor:u,width:d})=>{let f=r.getContext(`2d`);if(f&&d&&o){if(r.width!==d&&(r.width=d),r.height!==o&&(r.height=o),A({element:r}),l!==`transparent`&&(f.fillStyle=l,f.fillRect(0,0,d,o)),i){f.strokeStyle=n,f.lineWidth=3,f.beginPath();for(let[e,t]of i.polygon.entries())e?f.lineTo(t.x,t.y):f.moveTo(t.x,t.y);f.closePath(),f.stroke()}if(a&&(f.strokeStyle=e,f.lineWidth=2,f.strokeRect(a.boundingRect.x,a.boundingRect.y,a.boundingRect.width,a.boundingRect.height),await jt({color:t,context:f,result:a})),c){let e=getComputedStyle(r).color;for(let t of s)Mt({backgroundColor:e,color:u,context:f,line:t,toSource:c})}}},Z={documentTargets:{front:`frameDocument`,back:`frameDocumentBack`,passport:`framePassport`},rejections:{FACE_NOT_DETECTED:`faceNotFound`,FACE_IN_POLYGON:`faceInPolygon`,FACE_TOO_SMALL:`faceTooSmall`,FACE_CENTER_MOVE_LEFT:`faceCenterMoveLeft`,FACE_CENTER_MOVE_RIGHT:`faceCenterMoveRight`,FACE_CENTER_MOVE_UP:`faceCenterMoveUp`,FACE_CENTER_MOVE_DOWN:`faceCenterMoveDown`,FACE_STABILITY_REQUIRED:`stayStill`,DOCUMENT_NOT_DETECTED:`documentNotDetected`,DOCUMENT_BOX_TOO_SMALL:`documentBoxTooSmall`,DOCUMENT_BOX_TOO_LARGE:`documentBoxTooLarge`,DOCUMENT_BOX_NEAR_EDGE:`documentBoxNearEdge`,DOCUMENT_BOX_TOUCHES_EDGES:`documentBoxTouchesEdges`,DOCUMENT_SHAPE_INVALID:`documentShapeInvalid`,DOCUMENT_NOT_SUPPORTED:`documentNotSupported`,DOCUMENT_BLURRY:`documentBlurry`,DOCUMENT_FRONT_FACE_NOT_DETECTED:`faceNotVisibleInDocument`,DOCUMENT_FRONT_FACE_NOT_CONTAINED:`faceNotVisibleInDocument`,DOCUMENT_FRONT_FACE_TOO_SMALL:`documentPhotoTooSmall`,DOCUMENT_FRONT_FACE_SIZE_INVALID:`documentAlignmentInvalid`,DOCUMENT_FRONT_LAYOUT_INVALID:`documentAlignmentInvalid`,DOCUMENT_TEXT_NOT_READABLE:`documentNotReadable`,DOCUMENT_NOT_RECOGNIZED:`invalidDocument`,DOCUMENT_CODE_NOT_READABLE:`passportMrzNotReadable`,DOCUMENT_BACK_HAS_FACE:`documentBackHasFace`,DOCUMENT_BACK_SAME_AS_FRONT:`documentBackSameAsFront`,DOCUMENT_STABILITY_REQUIRED:`holdDocumentStill`,DOCUMENT_VALIDATION_FAILED:`documentValidationFailed`}},Ft=({target:e})=>Z.documentTargets[e],It=({code:e})=>e===`FACE_CAMERA_ALIGNMENT_REQUIRED`?P():e in Z.rejections?Z.rejections[e]:I({code:e}),{detectPictureFaces:Lt}=K,Q={FACEKEY_LOWER_HEAD:`FACE_PITCH_LOOK_DOWN`,FACEKEY_LOWER_HEAD_LESS:`FACE_PITCH_LOWER_LESS`,FACEKEY_RAISE_HEAD:`FACE_PITCH_LOOK_UP`,FACEKEY_RAISE_HEAD_LESS:`FACE_PITCH_RAISE_LESS`,FACEKEY_TILT_HEAD_LEFT:`FACE_ROLL_TILT_LEFT`,FACEKEY_TILT_HEAD_LESS:`FACE_ROLL_TILT_LESS`,FACEKEY_TILT_HEAD_RIGHT:`FACE_ROLL_TILT_RIGHT`,FACEKEY_TURN_HEAD_LEFT:`FACE_YAW_TURN_LEFT`,FACEKEY_TURN_HEAD_LESS:`FACE_YAW_TURN_LESS`,FACEKEY_TURN_HEAD_RIGHT:`FACE_YAW_TURN_RIGHT`,FACEKEY_SMILE_REQUIRED:`FACE_SMILE_REQUIRED`,FACEKEY_WINK_LEFT_REQUIRED:`FACE_WINK_LEFT_REQUIRED`},Rt=({face:e,name:t})=>e.blendshapes[t]??0,zt=({face:e,frame:t})=>e.boundingRect.height/t.height<.4?`FACE_TOO_SMALL`:null,Bt=({face:e,pose:t,options:n})=>{let r=a({...e,pose:t,options:n});return r?Q[r]:null},Vt=({face:e,pose:t,options:n})=>Bt({face:e,pose:t,options:n})===null,Ht=async({capture:e,pose:t,options:n,poseOptions:i,requireEyeLevelCamera:a,referencePose:o,referencePoses:s})=>{let c=await q.imageBitmap({blob:e});try{let e=await Lt(c),u=e.length===1?e[0]:null;if(!u)return null;if(!(await mt.detectFaceLiveness({detection:u,frame:c})).live)throw l({code:v.FACE_SPOOF_DETECTED});if(t===`faceReference`){let e=s??(o?[o]:[]);if(!e.length||e.some(e=>r({alignment:u,target:e})))return null}else if(!Vt({face:u,pose:t,options:i}))return null;if(re({pitch:u.pitch,pose:t,requireEyeLevelCamera:a,options:i}))return null;let d=q.prepareFace({alignment:n.alignment,face:u,frame:c});return d?await q.preparedFaceArtifacts({face:d}):null}finally{c.close()}},{detectDocumentBox:Ut}=G,{detectFace:Wt}=K,Gt=({view:e,display:t,isActive:r,notifyCapturesChanged:i})=>{let a=e.ref,o=({state:e})=>e.faceSequence[e.poseIndex]??`faceStraight`,s=({face:e,frame:n})=>{let r=e.boundingRect.x+e.boundingRect.width/2,i=e.boundingRect.y+e.boundingRect.height/2,a=(t.cameraFacingMode.value===`user`?n.width-r:r)/n.width,o=i/n.height;return a<.4?`FACE_CENTER_MOVE_RIGHT`:a>.6?`FACE_CENTER_MOVE_LEFT`:o<.4?`FACE_CENTER_MOVE_DOWN`:o>.6?`FACE_CENTER_MOVE_UP`:null},c=async({frame:c,session:d,state:f,options:p})=>{let m=performance.now(),h=null,g=!1;try{h=await Wt(c);let e=h?await Ut(c):null;if(g=!!(h&&e&&u({face:h,polygon:e.polygon})),!r({flow:`face`,session:d,state:f}))return!1;if(p.showFaceOverlay&&await Nt({element:a.mesh,meshLineColor:p.faceMeshColor,overlayColor:p.faceOverlayColor,result:h}),!h){f.poseStableFrames=0;let e=o({state:f});return t.feedback.value={flow:`face`,code:`FACE_NOT_DETECTED`,pose:e},!1}if(g)return f.poseStableFrames=0,t.feedback.value={flow:`face`,code:`FACE_IN_POLYGON`,pose:o({state:f})},!1;let m=o({state:f}),_=zt({face:h,frame:c});if(_)return f.poseStableFrames=0,t.feedback.value={flow:`face`,code:_,pose:m},!1;let y=s({face:h,frame:c});if(y)return f.poseStableFrames=0,t.feedback.value={flow:`face`,code:y,pose:m},!1;let b=re({pitch:h.pitch,pose:m,requireEyeLevelCamera:p.requireEyeLevelCamera,options:p});if(b)return f.poseStableFrames=0,f.guidanceCodeState=ne(),f.correctiveState=E(),t.guidance.value=null,t.corrective.value=null,t.feedback.value={flow:`face`,code:b,pose:m},!1;let S={pitch:h.pitch,yaw:h.yaw,roll:h.roll},C=M({alignment:S,blendshapes:h.blendshapes,neutral:f.neutralPose,referencePose:Kt({state:f,alignment:S}),pose:m,options:p});f.guidanceCodeState=O({state:f.guidanceCodeState,code:C.code,requiredFrames:3}),t.guidance.value=C;let w=C.code?Q[C.code]:null,T=f.guidanceCodeState.published?Q[f.guidanceCodeState.published]:null,D=ee({pose:m,corrective:T?It({code:T}):null}).corrective,A=performance.now();if(f.correctiveState=ae({label:D,now:A,state:f.correctiveState}),t.corrective.value=k({label:D,now:A,state:f.correctiveState}),w)return f.poseStableFrames=0,t.feedback.value={flow:`face`,code:T,pose:m},!1;if(m===`faceStraight`&&(f.neutralPose=S),f.poseStableFrames+=1,f.poseStableFrames<p.requiredFaceStableFrames)return t.feedback.value={flow:`face`,code:`FACE_STABILITY_REQUIRED`,pose:m},!1;t.feedback.value={flow:`face`,code:null,pose:m};let j=await te({frame:c}),N;try{N=await Ht({capture:j,pose:m,options:f.matchOptions,poseOptions:p,requireEyeLevelCamera:p.requireEyeLevelCamera,referencePose:Kt({state:f}),referencePoses:qt({state:f})})}catch(e){if(x({error:e})===v.FACE_SPOOF_DETECTED&&!r({flow:`face`,session:d,state:f}))return!1;throw e}if(!r({flow:`face`,session:d,state:f}))return!1;if(!N)return f.poseStableFrames=0,t.feedback.value={flow:`face`,code:`FACE_STABILITY_REQUIRED`,pose:m},!1;let P=ot({image:q.readImage({frame:c,width:32,height:32})}),F=f.previousPoseBackgroundSignature;if(F&&!st({first:F,second:P}).matched)throw l({code:v.POSE_BACKGROUND_MISMATCH});let I=f.faceEmbeddings.faceStraight;if(I&&n({first:I,second:N.embeddings})<=f.matchOptions.threshold)throw l({code:v.POSE_IDENTITY_MISMATCH});let L=$({pose:m,index:f.poseIndex});return f.captures[L]=j,f.preparedCaptures[L]=N.images,f.faceEmbeddings[L]=N.embeddings,f.previousPoseBackgroundSignature=P,i({state:f}),t.success.value=!0,await ce({milliseconds:400}),t.success.value=!1,r({flow:`face`,session:d,state:f})?(f.poseIndex+=1,t.guidance.value=null,f.poseStableFrames=0,f.guidanceCodeState=ne(),f.correctiveState=E(),t.corrective.value=null,t.progress.value={completed:f.poseIndex,total:f.faceSequence.length},f.poseIndex===f.faceSequence.length?(t.feedback.value=null,!0):(t.feedback.value={flow:`face`,pose:o({state:f}),code:null},!1)):!1}finally{r({flow:`face`,session:d,state:f})&&e.collectFaceDebug({face:h,faceInPolygon:g,processingTimeMilliseconds:performance.now()-m,state:f}),c.close()}};return{runFaceLoop:async({session:e,state:n,options:i})=>{for(;r({flow:`face`,session:e,state:n});){if(await de({video:a.video}),!r({flow:`face`,session:e,state:n}))return;let o=await createImageBitmap(a.video);if(await c({frame:o,session:e,state:n,options:i})){n.flow=null,t.debug.value=[],t.guidance.value=null;return}}}}},$=({pose:e,index:t})=>e===`faceReference`&&t>1?`faceReference_${t-1}`:e,Kt=({state:e,alignment:t})=>{let n=qt({state:e});return(t?n?.find(e=>r({alignment:t,target:e})!==null):void 0)||(e.faceReference?.poseGroups?.[e.poseIndex-1]?.pose??e.faceReference?.pose)},qt=({state:e})=>{let t=e.faceReference,n=t?.poseGroups?.[e.poseIndex-1];if(!t?.candidates||!n)return;let r=t.candidates;return n.candidateIndices.map(e=>r[e].pose)},Jt=({captures:e,state:t})=>t.faceSequence.every((n,r)=>{let i=$({pose:n,index:r});return!!(e[i]&&t.preparedCaptures[i]&&t.faceEmbeddings[i])}),Yt=({captures:e,state:t})=>{if(!Jt({captures:e,state:t}))throw l({code:v.CAPTURES_INCOMPLETE});let n=[...t.faceSequence];return{faces:n.map((e,t)=>$({pose:e,index:t})).map(t=>e[t]).filter(e=>!!e),poses:n,embeddings:n.map((e,n)=>t.faceEmbeddings[$({pose:e,index:n})]).filter(e=>!!e)}},Xt=({sequence:e})=>{let t=[...e];for(let e=t.length-1;e>0;--e){let n=Math.floor(Math.random()*(e+1));[t[e],t[n]]=[t[n],t[e]]}return t},Zt=({sequence:e})=>[...e].sort((e,t)=>Et[e]-Et[t]),Qt=({poses:e,randomize:t})=>{let n=e===`all`?Y.filter(e=>e!==`faceReference`):e??J;if(!n.length)throw l({code:v.INVALID_POSES});let r=[...new Set(n)];if(r.includes(`faceReference`)||r.length!==n.length||r.some(e=>!Y.includes(e))||r[0]!==`faceStraight`||J.some(e=>!r.includes(e)))throw l({code:v.INVALID_POSES});let i=r.slice(1);return t?[`faceStraight`,...Xt({sequence:i})]:[`faceStraight`,...Zt({sequence:i})]},$t=()=>({reference:f(!1),stage:f(null),activity:f(null),error:f(null),retry:f(null),feedback:f(null),guidance:f(null),corrective:f(null),progress:f({completed:0,total:0}),success:f(!1),cameraSize:f(null),cameraFacingMode:f(null),debug:f([]),debugEnabled:f(!1)});export{Fe as C,z as S,mt as _,Jt as a,ht as b,It as c,X as d,Y as f,gt as g,K as h,Yt as i,Pt as l,G as m,Gt as n,Qt as o,J as p,Rt as r,Ft as s,$t as t,Ot as u,wt as v,et as x,q as y};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! Copyright (c) 2026 VOLTOM. All rights reserved. Proprietary software. See LICENSE at https://voltom.io/license. */
|
|
2
|
+
import{Jt as e}from"./requests-DW8zDX51.js";var t=()=>({operation:e(`enroll`),phase:e(`loading`),instruction:e(null),guidance:e(null),corrective:e(null),progress:e({completed:0,total:1}),feedback:e(null),failures:e(0),error:e(null),debug:e([]),debugEnabled:e(!1),match:e(null),facingMode:e(null)});export{t};
|