@incodetech/core 2.4.1-agentic → 2.4.1-agentic.2

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.
Files changed (211) hide show
  1. package/dist/BrowserNetworkStatusProvider-BrDXBEDd.esm.js +21 -0
  2. package/dist/{multipartRecordingService-DMBxHKS2.esm.js → CameraCompositor-DN7NkJzV.esm.js} +7 -734
  3. package/dist/{FaceDetectionProvider-B83VmClw.esm.js → FaceDetectionProvider-D9PlON49.esm.js} +11 -12
  4. package/dist/MultipartRecordingProvider-D9mauUdS.esm.js +146 -0
  5. package/dist/StreamCanvasProcessingSession-CBnbTnOr.esm.js +42 -0
  6. package/dist/{WasmUtilProvider-GTkoJyFY.esm.js → WasmUtilProvider-Dp2V-Uct.esm.js} +2 -2
  7. package/dist/WorkerEncoderRecordingProvider-B1ODYtgN.esm.js +80 -0
  8. package/dist/{addressSearch-41sMcnJk.esm.js → addressSearch-DzbE9Ogt.esm.js} +2 -352
  9. package/dist/ae-signature.esm.js +1 -1
  10. package/dist/antifraud.esm.js +2 -2
  11. package/dist/{antifraudManager-CQ08atTC.esm.js → antifraudManager-BObuHBjn.esm.js} +2 -2
  12. package/dist/{antifraudStateMachine-BcsUTTIr.esm.js → antifraudStateMachine-Dfrd2-26.esm.js} +1 -1
  13. package/dist/{api-BO8JA7Pf.esm.js → api-CpP4PS4S.esm.js} +2 -0
  14. package/dist/{apiError-CfuIvnUy.esm.js → apiError-gNfsp99I.esm.js} +1 -1
  15. package/dist/{attemptCarry-BjTJ6bMQ.esm.js → attemptCarry-WOkfvFMw.esm.js} +2 -2
  16. package/dist/authentication.d.ts +3 -3
  17. package/dist/authentication.esm.js +2 -2
  18. package/dist/{authenticationManager-DvmklBTE.esm.js → authenticationManager-BtN4CHOR.esm.js} +5 -5
  19. package/dist/{authenticationManager-C-cOki0Y.d.ts → authenticationManager-CWmh7aSY.d.ts} +1 -1
  20. package/dist/{authenticationStateMachine-BL2ptOA0.esm.js → authenticationStateMachine-DdcnWnBT.esm.js} +3 -3
  21. package/dist/backCameraLabel-yda5ugE4.esm.js +67 -0
  22. package/dist/{backCameraStream-C5_NNfUN.esm.js → backCameraStream-DS1oDiUq.esm.js} +10 -65
  23. package/dist/{browser-pQZA35G2-DtkAf6sn.esm.js → browser-pQZA35G2-C0fRj-ID.esm.js} +1 -1
  24. package/dist/camera.d.ts +2 -2
  25. package/dist/camera.esm.js +1 -1
  26. package/dist/certificate-issuance.esm.js +2 -2
  27. package/dist/{certificateIssuanceManager-CM0fuqDC.esm.js → certificateIssuanceManager-C1nETQos.esm.js} +2 -2
  28. package/dist/{certificateIssuanceStateMachine-kksIUOPD.esm.js → certificateIssuanceStateMachine-DThXMDqr.esm.js} +1 -1
  29. package/dist/{connectivity-HSl0diCx.esm.js → connectivity-BCuEoQ-n.esm.js} +2 -21
  30. package/dist/consent.d.ts +1 -1
  31. package/dist/consent.esm.js +2 -2
  32. package/dist/{consentManager-CBwFozhv.esm.js → consentManager-DMlSL6Ax.esm.js} +2 -2
  33. package/dist/{consentManager-_q9yJUku.d.ts → consentManager-bjfVXO7p.d.ts} +9 -9
  34. package/dist/{consentStateMachine-CpmRAcr2.esm.js → consentStateMachine-DIYSMxKQ.esm.js} +1 -1
  35. package/dist/cross-document-data-match.esm.js +1 -1
  36. package/dist/{crossDocumentDataMatchManager-64O8t10a.esm.js → crossDocumentDataMatchManager-BFTdiEDB.esm.js} +2 -2
  37. package/dist/curp-validation.d.ts +1 -1
  38. package/dist/curp-validation.esm.js +2 -2
  39. package/dist/{curpValidationManager-CLgJQcx0.esm.js → curpValidationManager-DNpC3wyf.esm.js} +2 -2
  40. package/dist/{curpValidationManager-CXpFE-Mv.d.ts → curpValidationManager-z8428oCM.d.ts} +1 -1
  41. package/dist/{curpValidationStateMachine-Bx9YhVkJ.esm.js → curpValidationStateMachine-B3iVsDyt.esm.js} +2 -2
  42. package/dist/custom-fields.esm.js +1 -1
  43. package/dist/custom-watchlist.esm.js +2 -2
  44. package/dist/{customFieldsManager-DWt_0YtJ.esm.js → customFieldsManager-CvI-pDT3.esm.js} +2 -2
  45. package/dist/{customWatchlistManager-D8o-2Nej.esm.js → customWatchlistManager-BuHtUb0y.esm.js} +2 -2
  46. package/dist/{customWatchlistStateMachine-Sbi6DIcK.esm.js → customWatchlistStateMachine-CiVD9wyF.esm.js} +1 -1
  47. package/dist/{deepsightService-twg3bXqY.esm.js → deepsightLoader-Crsj_u0c.esm.js} +34 -29
  48. package/dist/{desktopCameraElection-kHY2IDJi.esm.js → desktopCameraElection-BGMtYwk3.esm.js} +5 -5
  49. package/dist/document-capture.d.ts +3 -3
  50. package/dist/document-capture.esm.js +2 -2
  51. package/dist/{documentCaptureManager-6tnnDkMX.d.ts → documentCaptureManager-DDfviFg0.d.ts} +25 -4
  52. package/dist/{documentCaptureManager-CMSC_Mhd.esm.js → documentCaptureManager-DLPqruXJ.esm.js} +3 -2
  53. package/dist/{documentCaptureStateMachine-BCwD5Rto.esm.js → documentCaptureStateMachine-DCvWQhFG.esm.js} +67 -26
  54. package/dist/dynamic-forms.esm.js +2 -2
  55. package/dist/{dynamicFormsManager-DU6W1e20.esm.js → dynamicFormsManager-CwqgwLa5.esm.js} +2 -2
  56. package/dist/{dynamicFormsStateMachine-C8Z7k3vo.esm.js → dynamicFormsStateMachine-CBdnpD95.esm.js} +2 -2
  57. package/dist/ekyb.d.ts +4 -4
  58. package/dist/ekyb.esm.js +3 -3
  59. package/dist/{ekybManager-TB6ZG5lX.d.ts → ekybManager-BLOkwmWO.d.ts} +2 -2
  60. package/dist/{ekybManager-TGfqyjuu.esm.js → ekybManager-BVTqTHd3.esm.js} +2 -2
  61. package/dist/{ekybStateMachine-DBgFuEPK.esm.js → ekybStateMachine-BmZHuZE1.esm.js} +5 -3
  62. package/dist/ekybUtils-Cw8Ta9Qi.esm.js +140 -0
  63. package/dist/ekyc.d.ts +3 -2
  64. package/dist/ekyc.esm.js +3 -3
  65. package/dist/{ekycManager-BSQteIfC.d.ts → ekycManager-DlGIn9wA.d.ts} +2 -1
  66. package/dist/{ekycManager-C2cgG2Pl.esm.js → ekycManager-DymCvmVB.esm.js} +2 -2
  67. package/dist/{ekycStateMachine-CuNF7z4O.esm.js → ekycStateMachine-CoFCUJ2z.esm.js} +141 -68
  68. package/dist/{ekycUtils-BFncpC4F.esm.js → ekycUtils-GRuMELYr.esm.js} +80 -9
  69. package/dist/electronic-signature.esm.js +1 -1
  70. package/dist/{electronicSignatureManager-C7pqXsRm.esm.js → electronicSignatureManager-Bt_tCIdI.esm.js} +3 -3
  71. package/dist/email.esm.js +2 -2
  72. package/dist/{emailManager-FH_CP0cT.esm.js → emailManager-CGoE3CUe.esm.js} +2 -2
  73. package/dist/{emailStateMachine-Cx-uTaBV.esm.js → emailStateMachine-KgHfDNvM.esm.js} +2 -2
  74. package/dist/{events-CQteqXfy.esm.js → events-ggpBBaZ8.esm.js} +1 -1
  75. package/dist/events.esm.js +1 -1
  76. package/dist/extensibility.d.ts +15 -14
  77. package/dist/extensibility.esm.js +36 -35
  78. package/dist/face-match.esm.js +2 -2
  79. package/dist/{faceCaptureManagerFactory-CBm05KnT.esm.js → faceCaptureManagerFactory-BWOB3ZeZ.esm.js} +4 -4
  80. package/dist/{faceCaptureManagerFactory-C-xKdj-d.d.ts → faceCaptureManagerFactory-DV2ULUYS.d.ts} +3 -3
  81. package/dist/{faceCaptureSetup-BQjCbL51.esm.js → faceCaptureSetup-D0w1UBlO.esm.js} +12 -403
  82. package/dist/{faceMatchManager-B2zp7yP4.esm.js → faceMatchManager-D2xKPjjQ.esm.js} +2 -2
  83. package/dist/{faceMatchStateMachine-ByTMQCUC.esm.js → faceMatchStateMachine-CUvwiQi9.esm.js} +2 -2
  84. package/dist/{feature-management-DjAG5lsJ.esm.js → feature-management-DBh1nqp8.esm.js} +35 -21
  85. package/dist/feature-management.esm.js +1 -1
  86. package/dist/field-comparison.esm.js +1 -1
  87. package/dist/{fieldComparisonManager-CC0vKmpf.esm.js → fieldComparisonManager-DgDbEeFZ.esm.js} +2 -2
  88. package/dist/fiscal-qr.esm.js +1 -1
  89. package/dist/{fiscalQrManager-Be-r4oZj.esm.js → fiscalQrManager-BZeklojR.esm.js} +3 -3
  90. package/dist/flow-events.d.ts +1 -1
  91. package/dist/flow.d.ts +8 -8
  92. package/dist/flow.esm.js +10 -6
  93. package/dist/{flowCompletionService-ChMU2v79.esm.js → flowCompletionService-Dv7zoVWe.esm.js} +2 -2
  94. package/dist/{flowServices-g2tVWsJl.esm.js → flowServices-C5-oamoC.esm.js} +69 -143
  95. package/dist/geolocation.esm.js +2 -2
  96. package/dist/{geolocationManager-DLbvZwUB.esm.js → geolocationManager-BFTxgOZG.esm.js} +2 -2
  97. package/dist/{geolocationStateMachine-CAJVongM.esm.js → geolocationStateMachine-v729Lz_0.esm.js} +3 -3
  98. package/dist/government-validation.esm.js +2 -2
  99. package/dist/{governmentValidationManager-CkX9TEkh.esm.js → governmentValidationManager-CjChjZ3C.esm.js} +2 -2
  100. package/dist/{governmentValidationStateMachine-PTPCP26N.esm.js → governmentValidationStateMachine-AEbn3Afi.esm.js} +1 -1
  101. package/dist/home.d.ts +1 -1
  102. package/dist/home.esm.js +1 -1
  103. package/dist/http.esm.js +1 -1
  104. package/dist/id-ocr.d.ts +1 -1
  105. package/dist/id-ocr.esm.js +2 -2
  106. package/dist/id-selfie-flow.d.ts +1 -1
  107. package/dist/id-selfie-flow.esm.js +10 -9
  108. package/dist/id-verification.esm.js +2 -2
  109. package/dist/id.d.ts +3 -3
  110. package/dist/id.esm.js +4 -4
  111. package/dist/{idCaptureDefaults-MSQoqScU.esm.js → idCaptureDefaults-Dszuq9ng.esm.js} +3 -3
  112. package/dist/{idCaptureManager-zZdTcpG1.esm.js → idCaptureManager-BVfqpIjM.esm.js} +9 -8
  113. package/dist/{idCaptureManager-DzTfQ1Am.d.ts → idCaptureManager-CCA2D1Ah.d.ts} +5 -3
  114. package/dist/{idCaptureServices-8OHinO0N.esm.js → idCaptureServices-CwG9Xp_n.esm.js} +27 -196
  115. package/dist/{idCaptureStateMachine-B3G6XoDG.esm.js → idCaptureStateMachine-DUm3a_Mt.esm.js} +20 -20
  116. package/dist/{idOcrManager-DT3kPIB3.d.ts → idOcrManager-BTdHlJ9D.d.ts} +1 -1
  117. package/dist/{idOcrManager-B64-fjWg.esm.js → idOcrManager-xyEZNOBa.esm.js} +2 -2
  118. package/dist/{idOcrStateMachine-B1aZnobs.esm.js → idOcrStateMachine-DNKXh4Rn.esm.js} +1 -1
  119. package/dist/{idVerificationManager-_Kebv-Ue.esm.js → idVerificationManager-DdnvYfgN.esm.js} +2 -2
  120. package/dist/{idVerificationStateMachine-DQn6c84z.esm.js → idVerificationStateMachine-DtIBCa32.esm.js} +1 -1
  121. package/dist/identity-reuse.esm.js +2 -2
  122. package/dist/{identityReuseManager-DDXkNVZi.esm.js → identityReuseManager-CcpovlfD.esm.js} +2 -2
  123. package/dist/{identityReuseStateMachine-Bcnkbjf8.esm.js → identityReuseStateMachine-DxZFWy47.esm.js} +1 -1
  124. package/dist/{index-DEfwds5y.d.ts → index-BfSZvEHi.d.ts} +10 -2
  125. package/dist/{index-DMDAk85K.d.ts → index-DC0P2Vzw.d.ts} +1 -1
  126. package/dist/index.d.ts +1 -1
  127. package/dist/index.esm.js +1 -1
  128. package/dist/{invokeOnCaptureCallback-CXIBwBeE.esm.js → invokeOnCaptureCallback-BJ0GVHGr.esm.js} +1 -1
  129. package/dist/kyb-checks.d.ts +3 -0
  130. package/dist/kyb-checks.esm.js +3 -0
  131. package/dist/kybChecksManager-CblEL97E.d.ts +95 -0
  132. package/dist/kybChecksManager-D2BEaUzK.esm.js +89 -0
  133. package/dist/kybChecksStateMachine-Cy-MsmKZ.esm.js +718 -0
  134. package/dist/mandatory-consent.d.ts +2 -2
  135. package/dist/mandatory-consent.esm.js +2 -2
  136. package/dist/{mandatoryConsentManager-43W5d_8G.esm.js → mandatoryConsentManager-B4vCYslr.esm.js} +2 -2
  137. package/dist/{mandatoryConsentManager-xx3mY-xw.d.ts → mandatoryConsentManager-B88Sm5nd.d.ts} +6 -6
  138. package/dist/{mandatoryConsentStateMachine-CVlgdlnt.esm.js → mandatoryConsentStateMachine-DWslYPA3.esm.js} +1 -1
  139. package/dist/mediaRecorderOptions-B9-IEVtV.esm.js +70 -0
  140. package/dist/multipartRecordingService-BTqkHGG9.esm.js +407 -0
  141. package/dist/{permissionGuards-B3OPL8Si.esm.js → permissionGuards-DFV-Ws0a.esm.js} +1 -1
  142. package/dist/{permissionServices-DnBAN_hW.esm.js → permissionServices-D190ATGD.esm.js} +8 -6
  143. package/dist/phone.esm.js +2 -2
  144. package/dist/phoneFormat-JJNaWthV.esm.js +75 -0
  145. package/dist/{phoneManager-C6jut_pz.esm.js → phoneManager-Dy5tODCU.esm.js} +3 -3
  146. package/dist/phoneServices-DJgyOzU2.esm.js +77 -0
  147. package/dist/{phoneStateMachine-T1-drWfG.esm.js → phoneStateMachine-DnlPhnw7.esm.js} +20 -60
  148. package/dist/{processFaceMatch-BWme3kVV.esm.js → processFaceMatch-Bst83HaS.esm.js} +1 -1
  149. package/dist/qe-signature.esm.js +1 -1
  150. package/dist/recordingService-CTko6Cjn.esm.js +397 -0
  151. package/dist/redirect-to-mobile.esm.js +2 -2
  152. package/dist/{redirectToMobileManager-BJXC6Kx9.esm.js → redirectToMobileManager-CgGaT2NP.esm.js} +3 -3
  153. package/dist/{redirectToMobileStateMachine-BBMAc2Gb.esm.js → redirectToMobileStateMachine-CbhN8uVN.esm.js} +39 -21
  154. package/dist/resolveForm-O7-r79VA.esm.js +351 -0
  155. package/dist/{runChildModule-DPHTqSdF.esm.js → runChildModule-BG46reQE.esm.js} +2 -2
  156. package/dist/{sdkVersion-C3_P-Qbq.esm.js → sdkVersion-DJCo6uSb.esm.js} +1 -1
  157. package/dist/selfie.d.ts +3 -3
  158. package/dist/selfie.esm.js +10 -10
  159. package/dist/{selfieErrorUtils-BL0BLMnp.esm.js → selfieErrorUtils-DNbVqz2B.esm.js} +1 -1
  160. package/dist/{selfieManager-Cbliomv7.esm.js → selfieManager-1_TQP4-x.esm.js} +5 -5
  161. package/dist/{selfieManager-BMmpUii2.d.ts → selfieManager-DmZFzs1-.d.ts} +1 -1
  162. package/dist/{selfieStateMachine-B5m_Kn0O.esm.js → selfieStateMachine-BUnZmMRY.esm.js} +3 -3
  163. package/dist/{session-DAaAewMX.esm.js → session-DdnAM9fZ.esm.js} +4 -4
  164. package/dist/session.d.ts +1 -1
  165. package/dist/session.esm.js +6 -6
  166. package/dist/{sessionInitializer-CWFT4dfw.esm.js → sessionInitializer-CwJACl13.esm.js} +83 -24
  167. package/dist/{setup-D9qt8YVU.d.ts → setup-CmqnkqsR.d.ts} +1 -1
  168. package/dist/{setup-CDAKwTr7.esm.js → setup-D26WdmvA.esm.js} +28 -27
  169. package/dist/signature.esm.js +2 -2
  170. package/dist/{signatureManager-BeEVCcsC.esm.js → signatureManager-CwqjcxPg.esm.js} +2 -2
  171. package/dist/{signatureStateMachine-_1c1vSid.esm.js → signatureStateMachine-DBVDd1Eu.esm.js} +1 -1
  172. package/dist/{stats-BpMz-hTP.esm.js → stats-CatA2dea.esm.js} +1 -1
  173. package/dist/stats.esm.js +1 -1
  174. package/dist/textRules-D4NRinKY.d.ts +41 -0
  175. package/dist/{tri-BajQnjbf.esm.js → tri-C9SvtzuQ.esm.js} +24 -3
  176. package/dist/tri.d.ts +2 -2
  177. package/dist/{tri.esm-CzTNi5Q_.esm.js → tri.esm-DgTlfPhR.esm.js} +167 -155
  178. package/dist/tri.esm.js +2 -2
  179. package/dist/{trueSightService-BujtUIW6.esm.js → trueSightService-OZl8wQu7.esm.js} +4 -4
  180. package/dist/trust-graph.esm.js +1 -1
  181. package/dist/{types--3HDl2SF.d.ts → types-BEVHQbbC.d.ts} +1 -1
  182. package/dist/{types-xEEWCx1j.d.ts → types-BPm1JSu7.d.ts} +1 -1
  183. package/dist/{types-C397LhmN.d.ts → types-BgRHw-dR.d.ts} +1 -1
  184. package/dist/{types-DuD8TRJU.d.ts → types-CRaFu6wS.d.ts} +4 -2
  185. package/dist/types-CTaL0XJz.d.ts +80 -0
  186. package/dist/{types-PTZHRhGX.d.ts → types-Cd0J0F9D.d.ts} +1 -1
  187. package/dist/{types-e8fCsvvk.d.ts → types-Csh8vzPo.d.ts} +1 -1
  188. package/dist/{types-B2FK_wYb.d.ts → types-CuMJ2M7D.d.ts} +2 -41
  189. package/dist/{types-ZTZelfbM.d.ts → types-CyNndVAT.d.ts} +14 -6
  190. package/dist/types-J6g6iKe_.d.ts +6 -0
  191. package/dist/video-selfie.d.ts +1 -1
  192. package/dist/video-selfie.esm.js +9 -7
  193. package/dist/{videoSelfieCameraWarmer-DjkPpoj_.esm.js → videoSelfieCameraWarmer-Bhi70pSN.esm.js} +8 -8
  194. package/dist/{videoSelfieStepDetector-RfSmlFFW.d.ts → videoSelfieStepDetector-Dv3Mgws-.d.ts} +2 -2
  195. package/dist/virtualCameraCheck-eFOm2C9q.esm.js +27 -0
  196. package/dist/{warmup-BkfxQZsC.esm.js → warmup-DtB0DJpl.esm.js} +24 -17
  197. package/dist/wasm.d.ts +1 -1
  198. package/dist/wasm.esm.js +3 -3
  199. package/dist/{wasmDsFlagSync-BhU5H2oR.esm.js → wasmDsFlagSync-BtiR5pig.esm.js} +1 -1
  200. package/dist/{wasmWebClient-DTj9auyA.esm.js → wasmWebClient-BDrax6Eu.esm.js} +12 -9
  201. package/dist/watchlist-for-business.esm.js +2 -2
  202. package/dist/watchlist.esm.js +2 -2
  203. package/dist/{watchlistForBusinessManager-CVay6-9A.esm.js → watchlistForBusinessManager-DqUpAEj_.esm.js} +2 -2
  204. package/dist/{watchlistForBusinessStateMachine-DA6K5na4.esm.js → watchlistForBusinessStateMachine-DdaPl2PS.esm.js} +1 -1
  205. package/dist/{watchlistManager-B8gQ_rw3.esm.js → watchlistManager-CdpXzT4B.esm.js} +2 -2
  206. package/dist/{watchlistStateMachine-CSi_ZhtT.esm.js → watchlistStateMachine-ofHW_lPk.esm.js} +1 -1
  207. package/dist/workflow.d.ts +1 -1
  208. package/dist/workflow.esm.js +42 -42
  209. package/package.json +13 -7
  210. package/dist/deepsightLoader-DMxtowCm.esm.js +0 -33
  211. package/dist/types-D9r3zRfY.d.ts +0 -6
@@ -1,116 +1,5 @@
1
- import { t as api, u as endpoints } from "./api-BO8JA7Pf.esm.js";
2
- import { t as BrowserTimerProvider } from "./BrowserTimerProvider-BXhgNxLt.esm.js";
3
- import { a as isIOS } from "./platform-aPh7gTWh.esm.js";
4
- import { o as BrowserNetworkStatusProvider } from "./connectivity-HSl0diCx.esm.js";
5
- //#region ../infra/src/media/StreamCanvasProcessingSession.ts
6
- var StreamCanvasProcessingSession = class {
7
- /**
8
- * Creates a processing session that reacts to `StreamCanvasCapture` frame events
9
- * and drives a provider's `processFrame()` method with backpressure.
10
- */
11
- constructor(params) {
12
- this.disposed = false;
13
- this.isProcessing = false;
14
- this.onFrameEvent = () => {
15
- if (this.disposed || this.isProcessing) return;
16
- const frame = this.capturer.getLatestFrame();
17
- if (!frame) return;
18
- this.onFrame?.(frame);
19
- this.isProcessing = true;
20
- this.provider.processFrame(frame).catch(() => {}).finally(() => {
21
- this.isProcessing = false;
22
- });
23
- };
24
- this.capturer = params.capturer;
25
- this.provider = params.provider;
26
- this.onFrame = params.onFrame;
27
- this.capturer.addEventListener("frame", this.onFrameEvent);
28
- }
29
- /**
30
- * Unsubscribes from frame events and resets the provider.
31
- */
32
- dispose() {
33
- if (this.disposed) return;
34
- this.disposed = true;
35
- this.capturer.removeEventListener("frame", this.onFrameEvent);
36
- this.provider.reset();
37
- }
38
- /**
39
- * Returns whether the session has been disposed.
40
- */
41
- isDisposed() {
42
- return this.disposed;
43
- }
44
- };
45
- //#endregion
46
- //#region ../infra/src/media/mediaRecorderOptions.ts
47
- /**
48
- * Picks a `MediaRecorder` mime type the current browser actually supports.
49
- * WebM avoids Safari's fragmented-MP4 unknown-duration metadata on versions
50
- * that can record it; older Safari versions fall back to MP4. Returns '' when
51
- * none match.
52
- */
53
- function getSupportedMediaRecorderMimeType() {
54
- for (const type of [
55
- "video/webm",
56
- "video/webm;codecs=vp9",
57
- "video/webm;codecs=vp8",
58
- "video/mp4"
59
- ]) if (MediaRecorder.isTypeSupported(type)) return type;
60
- return "";
61
- }
62
- /**
63
- * Multipart recordings use the same WebM-first order. Some Android devices
64
- * advertise H.264 support but fail after MediaRecorder starts (ENG-56439).
65
- */
66
- function getMultipartRecorderMimeType() {
67
- return getSupportedMediaRecorderMimeType();
68
- }
69
- /**
70
- * `MediaRecorder` options tuned per platform — a higher bitrate on iOS, lower
71
- * elsewhere — paired with the supported mime type.
72
- */
73
- function getAdaptiveMediaRecorderOptions() {
74
- const mimeType = getSupportedMediaRecorderMimeType();
75
- if (isIOS()) return {
76
- mimeType,
77
- videoBitsPerSecond: 1e6,
78
- bitsPerSecond: 1e6
79
- };
80
- return {
81
- mimeType,
82
- videoBitsPerSecond: 5e5,
83
- bitsPerSecond: 5e5
84
- };
85
- }
86
- /**
87
- * Worker-encoded multipart recording profile (ENG-55397). 2 GB-class devices
88
- * (`navigator.deviceMemory` ≤ 2) record 360p at 15 fps: on a Galaxy A01 Core,
89
- * 720p30 plus WASM detection exhausted memory (renderer swapped, GPU process
90
- * killed), and even the in-worker encoder starved the camera preview to
91
- * 6 fps. They also upload 2 s parts: every part is one request through the
92
- * WASM HTTP client on the main thread, and at 0.5 s parts the uploads fell
93
- * behind during face detection, stretching the final "processing" wait.
94
- * Other devices, and browsers without `deviceMemory`, keep 720p30 at the
95
- * MediaRecorder bitrate and 0.5 s parts.
96
- */
97
- function getWorkerRecordingProfile(deviceMemoryGb = typeof navigator !== "undefined" ? navigator.deviceMemory : void 0) {
98
- if (deviceMemoryGb !== void 0 && deviceMemoryGb <= 2) return {
99
- maxLongEdge: 640,
100
- maxShortEdge: 360,
101
- fps: 15,
102
- bitrate: 6e5,
103
- timesliceMs: 2e3
104
- };
105
- return {
106
- maxLongEdge: 1280,
107
- maxShortEdge: 720,
108
- fps: 30,
109
- bitrate: 25e5,
110
- timesliceMs: 500
111
- };
112
- }
113
- //#endregion
1
+ import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.esm.js";
2
+ import { r as getWorkerRecordingProfile } from "./mediaRecorderOptions-B9-IEVtV.esm.js";
114
3
  //#region ../infra/src/media/cameraCompositorWorker.ts
115
4
  /**
116
5
  * Whether the worker transport is available here. Every probe must hold;
@@ -698,6 +587,10 @@ function buildCameraCompositorWorkerSource() {
698
587
  }
699
588
  //#endregion
700
589
  //#region ../infra/src/media/CameraCompositor.ts
590
+ var CameraCompositor_exports = /* @__PURE__ */ __exportAll({
591
+ CameraCompositor: () => CameraCompositor,
592
+ createRecordingCompositor: () => createRecordingCompositor
593
+ });
701
594
  const MAX_COMPOSITE_LONG_EDGE = 1280;
702
595
  const MAX_COMPOSITE_SHORT_EDGE = 720;
703
596
  const FRAME_INTERVAL_TOLERANCE_RATIO = .9;
@@ -1134,624 +1027,4 @@ var CameraCompositor = class {
1134
1027
  }
1135
1028
  };
1136
1029
  //#endregion
1137
- //#region ../infra/src/providers/browser/MultipartRecordingProvider.ts
1138
- /**
1139
- * How often `MediaRecorder` hands us buffered data (incremental blobs).
1140
- * 500 ms keeps each blob — and therefore each upload chunk — small: less
1141
- * tail lost when a session is interrupted, and a smaller first blob (init
1142
- * header + keyframe), which is the largest and most timeout-prone chunk.
1143
- * Not lower: request rate doubles per halving, and browsers stop honoring
1144
- * very small timeslices reliably.
1145
- */
1146
- const TIMESLICE_MS = 500;
1147
- /**
1148
- * Encoder target for the full video-selfie session. Higher than the
1149
- * short-clip liveness path (0.5–1 Mbps) so a multi-minute session keeps
1150
- * usable quality. It's a ceiling — a still scene still encodes well below it.
1151
- */
1152
- const VIDEO_BITS_PER_SECOND = 25e5;
1153
- /**
1154
- * Records a stream and emits every `MediaRecorder` timeslice blob as its own
1155
- * part, in order. Each blob is a whole container fragment (WebM cluster /
1156
- * fMP4 `moof`+`mdat`), which is the property the video-selfie-service's
1157
- * gap-splicing depends on — parts must never cut a fragment at a byte
1158
- * offset. The service stages sub-5 MiB chunks and combines them server-side,
1159
- * so emitting the smallest whole-fragment unit (~0.5 s of video) maximizes
1160
- * what an interrupted session can salvage.
1161
- *
1162
- * Page-lifecycle orchestration lives in Core: it pauses this recorder before a
1163
- * backgrounded camera can stall, restores the camera/compositor, and only then
1164
- * resumes this same media container.
1165
- */
1166
- var MultipartRecordingProvider = class {
1167
- constructor() {
1168
- this.mediaRecorder = null;
1169
- this._isRecording = false;
1170
- this._hasError = false;
1171
- this._error = null;
1172
- this.mimeType = "";
1173
- this.partNumber = 0;
1174
- this.onPart = null;
1175
- }
1176
- get isRecording() {
1177
- return this._isRecording;
1178
- }
1179
- get hasError() {
1180
- return this._hasError;
1181
- }
1182
- get error() {
1183
- return this._error;
1184
- }
1185
- startRecording(stream, onPart) {
1186
- this.reset();
1187
- this.partNumber = 0;
1188
- this.onPart = onPart;
1189
- try {
1190
- this.mimeType = getMultipartRecorderMimeType();
1191
- const recorder = new MediaRecorder(stream.clone(), {
1192
- mimeType: this.mimeType,
1193
- videoBitsPerSecond: VIDEO_BITS_PER_SECOND
1194
- });
1195
- recorder.ondataavailable = (event) => {
1196
- if (event.data.size > 0 && this.onPart) {
1197
- this.partNumber += 1;
1198
- this.onPart({
1199
- chunk: event.data,
1200
- partNumber: this.partNumber
1201
- });
1202
- }
1203
- };
1204
- recorder.onerror = (event) => {
1205
- const detail = event instanceof ErrorEvent && event.error instanceof Error ? event.error.message : event.type;
1206
- this._error = `Recording error: ${detail}`;
1207
- this._isRecording = false;
1208
- this._hasError = true;
1209
- };
1210
- recorder.start(TIMESLICE_MS);
1211
- this.mediaRecorder = recorder;
1212
- this._isRecording = true;
1213
- this._error = null;
1214
- this._hasError = false;
1215
- } catch (err) {
1216
- const detail = err instanceof Error ? err.message : String(err);
1217
- this._error = `Failed to start recording: ${detail}`;
1218
- this._hasError = true;
1219
- }
1220
- }
1221
- pauseRecording() {
1222
- const recorder = this.mediaRecorder;
1223
- if (!recorder || !this._isRecording || this._hasError) return false;
1224
- if (recorder.state === "paused") return true;
1225
- if (recorder.state !== "recording") return false;
1226
- try {
1227
- recorder.pause();
1228
- return true;
1229
- } catch (err) {
1230
- const detail = err instanceof Error ? err.message : String(err);
1231
- this._error = `Failed to pause recording: ${detail}`;
1232
- this._hasError = true;
1233
- return false;
1234
- }
1235
- }
1236
- resumeRecording() {
1237
- const recorder = this.mediaRecorder;
1238
- if (!recorder || !this._isRecording || this._hasError) return false;
1239
- if (recorder.state === "recording") return true;
1240
- if (recorder.state !== "paused") return false;
1241
- try {
1242
- recorder.resume();
1243
- return true;
1244
- } catch (err) {
1245
- const detail = err instanceof Error ? err.message : String(err);
1246
- this._error = `Failed to resume recording: ${detail}`;
1247
- this._hasError = true;
1248
- return false;
1249
- }
1250
- }
1251
- stopRecording() {
1252
- const recorder = this.mediaRecorder;
1253
- return new Promise((resolve) => {
1254
- if (recorder && this._isRecording) {
1255
- recorder.onstop = () => {
1256
- resolve();
1257
- };
1258
- recorder.stop();
1259
- this._isRecording = false;
1260
- } else resolve();
1261
- recorder?.stream?.getTracks().forEach((track) => track.stop());
1262
- });
1263
- }
1264
- reset() {
1265
- const recorder = this.mediaRecorder;
1266
- if (recorder) {
1267
- recorder.ondataavailable = null;
1268
- recorder.onerror = null;
1269
- recorder.onstop = null;
1270
- if (recorder.state !== "inactive") recorder.stop();
1271
- recorder.stream.getTracks().forEach((track) => track.stop());
1272
- this.mediaRecorder = null;
1273
- }
1274
- this.onPart = null;
1275
- this._isRecording = false;
1276
- this._error = null;
1277
- this._hasError = false;
1278
- }
1279
- };
1280
- //#endregion
1281
- //#region ../infra/src/providers/browser/WorkerEncoderRecordingProvider.ts
1282
- /**
1283
- * Multipart recorder for a `CameraCompositor` that encodes inside its worker
1284
- * (ENG-55397): emits the worker's WebM clusters as parts, in order. When the
1285
- * compositor could not start in-worker encoding (no insertable streams or
1286
- * WebCodecs, strict CSP), it records the composite stream with
1287
- * `MediaRecorder` instead, so callers wire it unconditionally.
1288
- *
1289
- * Why not always `MediaRecorder`: Chrome hands every recorded frame through
1290
- * the page main thread and drops frames while it is blocked. On a Galaxy A01
1291
- * Core the ID flow blocks it for 3–5 s (WASM + 1080p readbacks); a
1292
- * `MediaRecorder` fed by the worker kept 74 of 149 frames under 1.5 s
1293
- * freezes, the in-worker encoder 150 of 151.
1294
- */
1295
- var WorkerEncoderRecordingProvider = class {
1296
- constructor(compositor) {
1297
- this.compositor = compositor;
1298
- this._isRecording = false;
1299
- this._error = null;
1300
- this.partNumber = 0;
1301
- this.fallback = null;
1302
- }
1303
- get isRecording() {
1304
- return this.fallback ? this.fallback.isRecording : this._isRecording;
1305
- }
1306
- get hasError() {
1307
- return this.error !== null;
1308
- }
1309
- get error() {
1310
- if (this.fallback) return this.fallback.error;
1311
- return this._error ?? this.compositor.workerRecordingErrorMessage;
1312
- }
1313
- startRecording(stream, onPart) {
1314
- this.reset();
1315
- if (!this.compositor.encodesInWorker) {
1316
- this.fallback = new MultipartRecordingProvider();
1317
- this.fallback.startRecording(stream, onPart);
1318
- return;
1319
- }
1320
- this.partNumber = 0;
1321
- const started = this.compositor.startWorkerRecording((chunk) => {
1322
- this.partNumber += 1;
1323
- onPart({
1324
- chunk,
1325
- partNumber: this.partNumber
1326
- });
1327
- });
1328
- this._isRecording = started;
1329
- this._error = started ? null : "Failed to start recording: no encoder";
1330
- }
1331
- pauseRecording() {
1332
- if (this.fallback) return this.fallback.pauseRecording();
1333
- return this._isRecording && this.compositor.pauseWorkerRecording();
1334
- }
1335
- resumeRecording() {
1336
- if (this.fallback) return this.fallback.resumeRecording();
1337
- return this._isRecording && this.compositor.resumeWorkerRecording();
1338
- }
1339
- async stopRecording() {
1340
- if (this.fallback) {
1341
- await this.fallback.stopRecording();
1342
- return;
1343
- }
1344
- if (!this._isRecording) return;
1345
- this._isRecording = false;
1346
- await this.compositor.stopWorkerRecording();
1347
- }
1348
- reset() {
1349
- this.fallback?.reset();
1350
- this.fallback = null;
1351
- this.compositor.cancelWorkerRecording();
1352
- this._isRecording = false;
1353
- this._error = null;
1354
- }
1355
- };
1356
- //#endregion
1357
- //#region src/internal/recordings/videoSelfieUploadService.ts
1358
- /**
1359
- * Opens a scoped multipart video upload session. Idempotent server-side: if
1360
- * an upload is already in progress for the `(session, scope)` pair, the same `uploadId`
1361
- * comes back along with the parts already stored (`parts` non-empty) — but
1362
- * always with a fresh `epoch` that locks out whoever held the previous one.
1363
- */
1364
- async function initiateVideoSelfieUpload(scope = "videoselfie") {
1365
- const response = await api.post(endpoints.videoSelfieUploadInitiate, void 0, { query: { scope } });
1366
- return {
1367
- uploadId: response.data.uploadId,
1368
- epoch: response.data.epoch,
1369
- scope,
1370
- parts: response.data.parts ?? []
1371
- };
1372
- }
1373
- /**
1374
- * Uploads a single chunk as a multipart part. The body is the raw video bytes
1375
- * (no base64, no client-side encryption — encryption at rest is server-side
1376
- * S3 SSE). Every part except the last must be >= 5 MiB (enforced
1377
- * server-side). Returns the part number + `etag` needed to complete the
1378
- * upload. Rejects with a `409` status when a newer initiate fenced this
1379
- * session out.
1380
- */
1381
- async function uploadVideoSelfiePart(session, partNumber, chunk) {
1382
- const response = await api.post(endpoints.videoSelfieUploadPart, chunk, {
1383
- query: {
1384
- uploadId: session.uploadId,
1385
- epoch: session.epoch,
1386
- partNumber,
1387
- scope: session.scope
1388
- },
1389
- headers: { "Content-Type": "application/octet-stream" }
1390
- });
1391
- return {
1392
- partNumber: response.data.partNumber,
1393
- etag: response.data.etag
1394
- };
1395
- }
1396
- /**
1397
- * Finalizes the upload. The service assembles from the parts it stored; the
1398
- * optional `parts` list is deliberately NOT sent — chunks staged below the
1399
- * S3 minimum are combined and renumbered server-side, so a client-side list
1400
- * could contradict the authoritative one. Safe to repeat if the response
1401
- * was lost. Returns the server-reported status. Rejects with `400` naming a
1402
- * missing part when the sequence has a hole.
1403
- */
1404
- async function completeVideoSelfieUpload(session) {
1405
- return (await api.post(endpoints.videoSelfieUploadComplete, {
1406
- uploadId: session.uploadId,
1407
- epoch: session.epoch
1408
- }, { query: { scope: session.scope } })).data.status;
1409
- }
1410
- /**
1411
- * Discards an in-progress upload and everything already sent for it, so the
1412
- * backend fails the upload straight away instead of waiting for its expiry.
1413
- * Call when a recording is abandoned or its upload can no longer complete.
1414
- */
1415
- async function abortVideoSelfieUpload(session) {
1416
- return (await api.post(endpoints.videoSelfieUploadAbort, {
1417
- uploadId: session.uploadId,
1418
- epoch: session.epoch
1419
- }, { query: { scope: session.scope } })).data.status;
1420
- }
1421
- //#endregion
1422
- //#region src/internal/recordings/videoSelfieChunkUploader.ts
1423
- /**
1424
- * How many part uploads run concurrently. The service allows 10 rps with a
1425
- * burst of 30 per session; a real recorder emits ~2 chunks/s, so this cap
1426
- * only matters when a backlog is draining after a network stall.
1427
- */
1428
- const MAX_IN_FLIGHT = 3;
1429
- /** Attempts per chunk in the live round (first try + retries). */
1430
- const MAX_ATTEMPTS = 4;
1431
- /** Extra attempts per parked chunk during the final drain() round. */
1432
- const DRAIN_ATTEMPTS = 2;
1433
- const BACKOFF_BASE_MS = 500;
1434
- const BACKOFF_CAP_MS = 8e3;
1435
- /** Upper bound honored for a server-sent `Retry-After` (seconds). */
1436
- const RETRY_AFTER_CAP_MS = 3e4;
1437
- /**
1438
- * Ceiling on un-acknowledged chunk bytes held in memory. On a network slower
1439
- * than the encoder the backlog grows without bound; past this the upload
1440
- * cannot realistically catch up, so the uploader fails instead of eating
1441
- * memory on a low-end device. ~48 MiB ≈ 2.5 minutes of video at our bitrate.
1442
- */
1443
- const MAX_BUFFERED_BYTES = 48 * 1024 * 1024;
1444
- function httpStatusOf$1(error) {
1445
- if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") return error.status;
1446
- return null;
1447
- }
1448
- function retryAfterMsOf(error) {
1449
- if (typeof error === "object" && error !== null && "headers" in error && typeof error.headers === "object") {
1450
- const headers = error.headers;
1451
- const seconds = Number(headers?.["retry-after"]);
1452
- if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, RETRY_AFTER_CAP_MS);
1453
- }
1454
- return null;
1455
- }
1456
- /**
1457
- * Uploads video-selfie chunks with the client-side half of the service's
1458
- * resilience contract (`video-selfie-service` README, "What a client can
1459
- * rely on"):
1460
- *
1461
- * - **Keep-until-ack** — every chunk is held in memory until its upload
1462
- * returns 200 (a hole in the sequence can only be filled by that exact
1463
- * data). Acked bytes are durable in S3 (stored as a part or staged), so
1464
- * the blob is released the moment the ack lands.
1465
- * - **Retry with backoff** — transient failures (network error/timeout,
1466
- * 408, 429, 5xx) retry the same bytes under the same partNumber with
1467
- * exponential backoff + full jitter; 429 honors the server's
1468
- * `Retry-After`. Chunks may land out of order — the service stages them.
1469
- * - **Park, then drain** — a chunk that exhausts its live retries is parked
1470
- * (blob kept) without failing the recording; {@link drain} gives every
1471
- * parked chunk a final round once recording stops, so a mid-recording
1472
- * network outage only fails the upload if it persists to the end. A
1473
- * browser `online` event un-parks early: parked chunks get a fresh live
1474
- * round as soon as connectivity returns instead of waiting for stop.
1475
- * - **409 is fatal** — a newer initiate fenced this session out ("latest
1476
- * initiate wins"); no retry can succeed, so the uploader stops.
1477
- * - **Bounded memory** — when un-acked bytes exceed the ceiling the
1478
- * uploader fails rather than buffering a runaway backlog.
1479
- */
1480
- var VideoSelfieChunkUploader = class {
1481
- constructor(session, dependencies = {}) {
1482
- this.queue = [];
1483
- this.parked = [];
1484
- this.inFlight = 0;
1485
- this.bufferedBytes = 0;
1486
- this.fatal = false;
1487
- this.disposed = false;
1488
- this.tasks = [];
1489
- this.session = session;
1490
- this.timer = dependencies.timer ?? BrowserTimerProvider.getInstance();
1491
- this.jitter = dependencies.jitter ?? Math.random;
1492
- const networkStatus = dependencies.networkStatus ?? new BrowserNetworkStatusProvider();
1493
- this.unsubscribeOnline = networkStatus.onOnline(() => this.unparkEarly());
1494
- }
1495
- /** True once the upload cannot complete (fenced out or over the memory cap). */
1496
- get failed() {
1497
- return this.fatal;
1498
- }
1499
- /**
1500
- * Accepts the next chunk for upload. Non-blocking: the upload (and any
1501
- * retries) run in the background; failures surface through {@link failed}
1502
- * and {@link drain}.
1503
- */
1504
- enqueue(partNumber, chunk) {
1505
- if (this.fatal || this.disposed) return;
1506
- this.bufferedBytes += chunk.size;
1507
- if (this.bufferedBytes > MAX_BUFFERED_BYTES) {
1508
- this.fatal = true;
1509
- return;
1510
- }
1511
- this.queue.push({
1512
- partNumber,
1513
- chunk,
1514
- attempts: 0
1515
- });
1516
- this.pump();
1517
- }
1518
- /**
1519
- * Waits for every accepted chunk to be acknowledged, giving parked chunks
1520
- * one final retry round. Returns `true` when all chunks landed and the
1521
- * upload can be completed.
1522
- */
1523
- async drain() {
1524
- this.unsubscribeOnline();
1525
- await this.settleLiveRound();
1526
- while (!this.fatal && this.parked.length > 0) {
1527
- const chunk = this.parked.shift();
1528
- chunk.attempts = MAX_ATTEMPTS - DRAIN_ATTEMPTS;
1529
- this.queue.push(chunk);
1530
- this.pump();
1531
- await this.settleLiveRound();
1532
- if (this.parked.some((p) => p.partNumber === chunk.partNumber)) return false;
1533
- }
1534
- return !this.disposed && !this.fatal && this.parked.length === 0;
1535
- }
1536
- /** Cancels all pending work; held blobs are released. */
1537
- dispose() {
1538
- this.disposed = true;
1539
- this.queue = [];
1540
- this.parked = [];
1541
- this.unsubscribeOnline();
1542
- }
1543
- /**
1544
- * Connectivity is back (browser `online` event) — give parked chunks a
1545
- * fresh live round right away instead of holding them until {@link drain}.
1546
- * The event is only a hint: chunks that still fail simply park again.
1547
- */
1548
- unparkEarly() {
1549
- if (this.fatal || this.disposed || this.parked.length === 0) return;
1550
- for (const chunk of this.parked.splice(0)) {
1551
- chunk.attempts = 0;
1552
- this.queue.push(chunk);
1553
- }
1554
- this.pump();
1555
- }
1556
- async settleLiveRound() {
1557
- while (this.tasks.length > 0) {
1558
- const snapshot = [...this.tasks];
1559
- await Promise.all(snapshot);
1560
- this.tasks = this.tasks.filter((task) => !snapshot.includes(task));
1561
- }
1562
- }
1563
- pump() {
1564
- while (!this.fatal && !this.disposed && this.inFlight < MAX_IN_FLIGHT && this.queue.length > 0) {
1565
- const chunk = this.queue.shift();
1566
- this.inFlight += 1;
1567
- const task = this.uploadWithRetry(chunk).finally(() => {
1568
- this.inFlight -= 1;
1569
- this.pump();
1570
- });
1571
- this.tasks.push(task);
1572
- }
1573
- }
1574
- async uploadWithRetry(pending) {
1575
- while (!this.disposed) {
1576
- pending.attempts += 1;
1577
- try {
1578
- await uploadVideoSelfiePart(this.session, pending.partNumber, pending.chunk);
1579
- this.bufferedBytes -= pending.chunk.size;
1580
- return;
1581
- } catch (error) {
1582
- const status = httpStatusOf$1(error);
1583
- if (status === 409) {
1584
- this.fatal = true;
1585
- return;
1586
- }
1587
- if (status !== null && status >= 400 && status < 500 && status !== 408 && status !== 429 || pending.attempts >= MAX_ATTEMPTS) {
1588
- this.parked.push(pending);
1589
- return;
1590
- }
1591
- await this.delayBeforeRetry(pending.attempts, error);
1592
- }
1593
- }
1594
- }
1595
- delayBeforeRetry(attempt, error) {
1596
- const retryAfterMs = retryAfterMsOf(error);
1597
- const backoffCeiling = Math.min(BACKOFF_BASE_MS * 2 ** (attempt - 1), BACKOFF_CAP_MS);
1598
- const waitMs = retryAfterMs ?? backoffCeiling / 2 + this.jitter() * (backoffCeiling / 2);
1599
- return new Promise((resolve) => {
1600
- this.timer.setTimeout(resolve, waitMs);
1601
- });
1602
- }
1603
- };
1604
- //#endregion
1605
- //#region src/internal/recordings/multipartRecordingService.ts
1606
- /** Attempts for `complete` — documented safe to repeat if the response was lost. */
1607
- const COMPLETE_ATTEMPTS = 3;
1608
- const COMPLETE_BACKOFF_MS = 500;
1609
- function httpStatusOf(error) {
1610
- if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") return error.status;
1611
- return null;
1612
- }
1613
- /**
1614
- * Records the camera on-device and streams it to the backend as it is
1615
- * captured, using the video-selfie-service multipart upload protocol
1616
- * (`/v1/video-upload/*`).
1617
- *
1618
- * This is the client-side recorder for Video Selfie and for scoped regular
1619
- * Selfie and ID recordings. It replaces the former server-side recording path.
1620
- *
1621
- * Every ~0.5 s recorder blob uploads as its own chunk, concurrently with
1622
- * recording, through {@link VideoSelfieChunkUploader} (keep-until-ack +
1623
- * retry with backoff — see its doc for the full policy). The service stages
1624
- * sub-5 MiB chunks and combines them server-side, so `stop()` only drains
1625
- * the stragglers and finalizes; client memory holds un-acked chunks only.
1626
- * No client-side encryption: video is encrypted at rest server-side
1627
- * (S3 SSE-AES-256).
1628
- */
1629
- var MultipartRecordingService = class {
1630
- constructor(scope = "videoselfie", recorder = new MultipartRecordingProvider()) {
1631
- this.scope = scope;
1632
- this.timer = BrowserTimerProvider.getInstance();
1633
- this.session = null;
1634
- this.uploader = null;
1635
- this.chunksEmitted = 0;
1636
- this.stopPromise = null;
1637
- this.abandonRequested = false;
1638
- this.recorder = recorder;
1639
- }
1640
- get isRecording() {
1641
- return this.recorder.isRecording;
1642
- }
1643
- async start(stream) {
1644
- if (this.recorder.isRecording) return;
1645
- let initiated = await initiateVideoSelfieUpload(this.scope);
1646
- if (initiated.parts.length > 0) {
1647
- await abortVideoSelfieUpload(initiated).catch(() => {});
1648
- initiated = await initiateVideoSelfieUpload(this.scope);
1649
- }
1650
- this.session = {
1651
- uploadId: initiated.uploadId,
1652
- epoch: initiated.epoch,
1653
- scope: this.scope
1654
- };
1655
- this.uploader = new VideoSelfieChunkUploader(this.session);
1656
- this.chunksEmitted = 0;
1657
- this.abandonRequested = false;
1658
- this.recorder.startRecording(stream, ({ chunk, partNumber }) => {
1659
- this.chunksEmitted += 1;
1660
- this.uploader?.enqueue(partNumber, chunk);
1661
- });
1662
- }
1663
- /** Pause the current media container without finalizing its upload. */
1664
- pause() {
1665
- return this.recorder.pauseRecording?.() ?? false;
1666
- }
1667
- /** Resume the same media container after its video source has recovered. */
1668
- resume() {
1669
- return this.recorder.resumeRecording?.() ?? false;
1670
- }
1671
- stop() {
1672
- if (this.stopPromise) return this.stopPromise;
1673
- const stopPromise = this.finalizeRecording();
1674
- this.stopPromise = stopPromise;
1675
- const clearStopPromise = () => {
1676
- if (this.stopPromise === stopPromise) {
1677
- this.stopPromise = null;
1678
- this.abandonRequested = false;
1679
- }
1680
- };
1681
- stopPromise.then(clearStopPromise, clearStopPromise);
1682
- return stopPromise;
1683
- }
1684
- async finalizeRecording() {
1685
- const session = this.session;
1686
- const uploader = this.uploader;
1687
- if (!this.recorder.isRecording || !session || !uploader) return { recordingId: null };
1688
- try {
1689
- await this.recorder.stopRecording();
1690
- if (this.abandonRequested) {
1691
- this.abandonUpload(session);
1692
- return { recordingId: null };
1693
- }
1694
- const delivered = await uploader.drain();
1695
- if (this.abandonRequested || !delivered || uploader.failed || this.chunksEmitted === 0) {
1696
- this.abandonUpload(session);
1697
- return { recordingId: null };
1698
- }
1699
- } catch (error) {
1700
- this.abandonUpload(session);
1701
- throw error;
1702
- }
1703
- try {
1704
- await this.completeWithRetry(session);
1705
- this.session = null;
1706
- this.uploader = null;
1707
- return { recordingId: session.uploadId };
1708
- } catch {
1709
- this.abandonUpload(session);
1710
- return { recordingId: null };
1711
- }
1712
- }
1713
- cleanup() {
1714
- if (this.session) if (this.stopPromise) {
1715
- this.abandonRequested = true;
1716
- this.uploader?.dispose();
1717
- } else this.abandonUpload(this.session);
1718
- this.recorder.reset();
1719
- }
1720
- /**
1721
- * `complete` is idempotent server-side ("safe to repeat if the response
1722
- * was lost"), so transient failures — network errors, 5xx, 429 — retry a
1723
- * couple of times before the recording is declared failed. A 4xx (e.g.
1724
- * `400` naming a missing part) is permanent: after a clean drain every
1725
- * chunk was acked, so a reported hole cannot be filled from here.
1726
- */
1727
- async completeWithRetry(session) {
1728
- for (let attempt = 1;; attempt += 1) {
1729
- if (this.abandonRequested) throw new Error("Video upload abandoned");
1730
- try {
1731
- await completeVideoSelfieUpload(session);
1732
- return;
1733
- } catch (error) {
1734
- const status = httpStatusOf(error);
1735
- if (status !== null && status >= 400 && status < 500 && status !== 408 && status !== 429 || attempt >= COMPLETE_ATTEMPTS) throw error;
1736
- await new Promise((resolve) => {
1737
- this.timer.setTimeout(resolve, COMPLETE_BACKOFF_MS * attempt);
1738
- });
1739
- }
1740
- }
1741
- }
1742
- /**
1743
- * Fire-and-forget abort: the upload can no longer complete, so tell the
1744
- * backend to fail it immediately rather than at its expiry. Best-effort —
1745
- * an abort that doesn't land (including a 409 from a newer epoch having
1746
- * taken over) just means the server falls back to expiry or salvage.
1747
- */
1748
- abandonUpload(session) {
1749
- if (this.session !== session) return;
1750
- this.session = null;
1751
- this.uploader?.dispose();
1752
- this.uploader = null;
1753
- abortVideoSelfieUpload(session).catch(() => {});
1754
- }
1755
- };
1756
- //#endregion
1757
- export { getAdaptiveMediaRecorderOptions as a, createRecordingCompositor as i, WorkerEncoderRecordingProvider as n, StreamCanvasProcessingSession as o, CameraCompositor as r, MultipartRecordingService as t };
1030
+ export { CameraCompositor_exports as n, createRecordingCompositor as r, CameraCompositor as t };