@sorisdk/web-audio 0.6.5 → 0.6.8

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/README.md CHANGED
@@ -13,6 +13,36 @@ Public integration guide: https://docs.soriapi.com/ko/integration/web
13
13
  - An ephemeral key issued by your server
14
14
  - Microphone permission granted by the user
15
15
 
16
+ ## Unreleased: Console-resolved audio marker events
17
+
18
+ The public `audiomarker` event now contains only the marker identity managed in
19
+ SORI Console. The SDK emits it after a successful activity POST or refinement
20
+ PUT returns both a non-blank `audio_marker_id` and `audio_marker_name`:
21
+
22
+ ```ts
23
+ recognizer.on("audiomarker", ({ marker }) => {
24
+ console.log(marker.id, marker.name);
25
+ });
26
+ ```
27
+
28
+ The event is independent from campaign mapping and can be emitted when the
29
+ activity response has no campaign. Repeated responses within one continuous
30
+ material segment emit once; an intervening material, no-match, capture reset,
31
+ or expired continuity gap starts a new segment that may emit again.
32
+
33
+ Local WASM detection and labels such as `code_000` remain private inputs to the
34
+ activity request. They are no longer present on public `audiomarker` or `match`
35
+ events, `campaign.match`, the exported `DetectedMatch`, or the
36
+ `@sorisdk/web-audio` type exports. Custom request and campaign mappers receive
37
+ the public codebook-free match; the SDK adds its private `trait.marker` only to
38
+ the outgoing activity payload after request mapping.
39
+
40
+ This deliberately replaces the 0.6.7-and-earlier event shape. Migrate from
41
+ `event.marker` as a nullable string and `event.detection` as a raw detector
42
+ result to the non-null `event.marker.id` and `event.marker.name` fields above.
43
+ There is no legacy fallback: disabled activity reporting, failed transport, or
44
+ a response with a missing or malformed id/name pair emits no public marker.
45
+
16
46
  ## Standalone CDN
17
47
 
18
48
  For a browser application that does not use npm or a bundler, import the
@@ -22,7 +52,7 @@ configuration, or Node-based asset server is required:
22
52
  ```html
23
53
  <script type="module">
24
54
  import { AudioRecognizer } from
25
- "https://cdn.iplateia.com/web/sorisdk/v0.6.5/sori-web-audio.mjs";
55
+ "https://cdn.iplateia.com/web/sorisdk/v0.6.8/sori-web-audio.mjs";
26
56
 
27
57
  const recognizer = new AudioRecognizer({
28
58
  appId: "YOUR_APP_ID",
@@ -49,13 +79,39 @@ configuration, or Node-based asset server is required:
49
79
  ```
50
80
 
51
81
  Static URL imports are valid inside `<script type="module">`. Dynamic
52
- `await import("https://cdn.iplateia.com/web/sorisdk/v0.6.5/sori-web-audio.mjs")`
82
+ `await import("https://cdn.iplateia.com/web/sorisdk/v0.6.8/sori-web-audio.mjs")`
53
83
  is an optional alternative when the SDK should be loaded conditionally.
54
84
 
55
85
  Pin an exact version in production. Do not construct a mutable `latest` URL.
56
86
  The module loads its versioned WASM assets and the shared
57
87
  `https://cdn.iplateia.com/web/sorisdk/model.pack` automatically.
58
88
 
89
+ The fixed model response and caller-supplied AudioPacks use the matcher's same
90
+ 64 MiB browser transport limit by default. A valid oversized `Content-Length`
91
+ is rejected before the body is consumed, and an unknown-length response is
92
+ canceled on the first chunk that crosses the limit. The response is never
93
+ truncated; failures use the deterministic
94
+ `Pack source exceeds maximum size of <limit> bytes` error.
95
+
96
+ Set an intentional shared override through the matcher options when a larger
97
+ pack is required:
98
+
99
+ ```ts
100
+ const recognizer = new AudioRecognizer({
101
+ appId: "YOUR_APP_ID",
102
+ ephemeralKey,
103
+ wasm: {
104
+ matcher: {
105
+ maxPackBytes: 96 * 1024 * 1024
106
+ }
107
+ }
108
+ });
109
+ ```
110
+
111
+ The override applies to both the standalone fixed-model response and ordinary
112
+ pack sources. A caller-supplied `embeddedPackLoader` remains a zero-argument
113
+ callback and is not replaced by the standalone loader.
114
+
59
115
  The standalone module removes the frontend build/server requirement, but it
60
116
  does not remove the trusted server requirement for ephemeral credentials.
61
117
  Provide a backend or serverless endpoint for the `ephemeralKey` callback, and
@@ -93,7 +149,7 @@ An import map can give the standalone URL the npm package name:
93
149
  <script type="importmap">
94
150
  {
95
151
  "imports": {
96
- "@sorisdk/web-audio": "https://cdn.iplateia.com/web/sorisdk/v0.6.5/sori-web-audio.mjs"
152
+ "@sorisdk/web-audio": "https://cdn.iplateia.com/web/sorisdk/v0.6.8/sori-web-audio.mjs"
97
153
  }
98
154
  }
99
155
  </script>
@@ -145,6 +201,10 @@ recognizer.on("campaign", (event) => {
145
201
  console.log(event.activityId, event.campaign);
146
202
  });
147
203
 
204
+ recognizer.on("audiomarker", ({ marker }) => {
205
+ console.log(marker.id, marker.name);
206
+ });
207
+
148
208
  recognizer.on("error", ({ error }) => {
149
209
  console.error(error);
150
210
  });
@@ -161,23 +221,63 @@ await recognizer.destroy();
161
221
 
162
222
  ## Activity refinement
163
223
 
164
- The default `AudioRecognizer` activity reporter represents one fingerprint
165
- recognition and its later audio-marker enrichment as one server activity:
166
-
167
- 1. A marker-free match with an active marker-scan request is created with
168
- `POST /api/activity/` and top-level `refinement_expected: true`.
169
- 2. The returned `activity_id` is retained for 30 seconds.
170
- 3. If the same recognition gains `audioMarker.code`, the SDK sends
224
+ The default `AudioRecognizer` activity reporter represents one ordered,
225
+ continuous material segment and its later audio-marker enrichment as one
226
+ server activity:
227
+
228
+ 1. When the coordinator accepts a successful material match, it captures one
229
+ UTC RFC 3339 `recognized_at` value before any asynchronous request mapping,
230
+ header, token, or fetch work.
231
+ 2. The initial `POST /api/activity/` includes that timestamp and the exact
232
+ `DetectedMatch.position` integer in milliseconds. With valid
233
+ `matcherSegments` metadata, the position is local to the matched segment.
234
+ 3. A marker-free match with an active marker-scan request also includes
235
+ top-level `refinement_expected: true`.
236
+ 4. The returned `activity_id` is retained for 30 seconds.
237
+ 5. If the same recognition gains a private local marker detection, the SDK sends
171
238
  `PUT /api/activity/{activity_id}` with the same material and
172
239
  `trait.marker`.
173
- 4. The refined `campaign` event keeps the same non-empty `activityId`, so an
240
+ 6. A valid response marker id/name pair emits one public structured
241
+ `audiomarker` event, even when the response has no campaign.
242
+ 7. The refined `campaign` event keeps the same non-empty `activityId`, so an
174
243
  application can replace the earlier campaign row deterministically.
175
244
 
245
+ A consecutive match for the same material and fingerprint type renews a local
246
+ 30-second continuity lease without another POST or campaign event. That local
247
+ lease can keep one segment alive beyond the initial server refinement window,
248
+ but it never extends the original PUT deadline. A marker confirmed anywhere
249
+ inside the segment is sticky: the first confirmation can issue at most one PUT,
250
+ and later marker misses or repeated marker evidence issue no mutation or
251
+ downgrade.
252
+
176
253
  A marker present on the first match is included in the POST and does not cause
177
- a PUT or include `refinement_expected`. Recognition without an active marker
178
- scan, plus legacy/custom POST-only reporters, also omit the opt-in flag.
179
- Marker-state `audiomarker` events remain independently observable; they do not
180
- mean that server activity refinement completed.
254
+ a PUT or include `refinement_expected`; that marker-first segment is still
255
+ retained for continuity. Recognition without an active marker scan, plus
256
+ legacy/custom POST-only reporters, also omit the opt-in flag. Custom reporters
257
+ enable segment coalescing only when `refinement` is enabled, preserving legacy
258
+ POST-only behavior otherwise.
259
+
260
+ A different material, an emitted `nomatch`, a gap beyond the continuity lease,
261
+ or stop, clear, destroy, authentication/capture replacement, or reset seals the
262
+ segment. Returning to A after B always creates a new A activity and can never
263
+ refine the earlier A. Marker evidence arriving after a segment is sealed is
264
+ ignored for that segment; create or PUT transport that already started may
265
+ finish under the existing capture, deadline, and cancellation guards.
266
+
267
+ Ordinary fingerprint `match` events remain independently observable and never
268
+ contain the private detector result. Public `audiomarker` delivery is sourced
269
+ only from a completed activity response. It is independent from campaign
270
+ availability but does prove that the server resolved the marker id and name.
271
+
272
+ Recognition timing belongs only to the segment's first material POST. Later
273
+ same-material observations update only the internal `lastObservedAt` lease;
274
+ they never replace the first `recognized_at` or `position`. A later marker PUT
275
+ does not include either field, and marker-only events do not create timing
276
+ metadata. `recognized_at` identifies first SDK match acceptance rather than
277
+ HTTP receipt, marker confirmation, refinement, or webhook delivery time. Do not
278
+ derive playback start as `recognized_at - position`: the match is accepted
279
+ after its query window was collected, so that calculation lacks the query
280
+ window's wall-clock anchor.
181
281
 
182
282
  Network and 5xx PUT failures are retried at most twice within the original
183
283
  30-second deadline. Server responses 404, 409, and 410 are terminal. An
@@ -209,7 +309,35 @@ Existing `mapMatchToRequest` and `mapResponseToCampaign` hooks continue to
209
309
  handle POST. Additive refinement hooks can override the PUT payload, response
210
310
  mapping, endpoint, headers, fetcher, and retry policy. The stable terminal
211
311
  statuses 404, 409, and 410 are never retried even if a custom policy returns
212
- `true`.
312
+ `true`. Match arguments passed to these hooks omit private detector state. When
313
+ local detection succeeds, the SDK injects its private marker into the outgoing
314
+ `trait.marker` after request mapping, while resolved public identity is parsed
315
+ directly from the unmodified activity response before campaign delivery.
316
+
317
+ `recognized_at` and `position` are optional public request properties for
318
+ source compatibility, but they are SDK-owned transport values. After a custom
319
+ POST mapper returns an eligible material payload, the SDK overwrites any
320
+ conflicting values with the captured recognition timestamp and exact matcher
321
+ position. The SDK removes both properties from all refinement PUT payloads,
322
+ including custom refinement mappings. Existing one-argument POST mappers and
323
+ POST-only transports require no signature changes. Activity responses and
324
+ `campaign` events do not gain timing properties from this request contract.
325
+
326
+ ## API endpoint normalization
327
+
328
+ `apiEndpoint` continues to accept a `string` or `URL`. When the SDK derives the
329
+ default authentication and activity URLs, it removes all trailing ASCII `/`
330
+ characters and appends `/auth` or `/activity/` with the existing URL shapes.
331
+
332
+ The endpoint is limited to `MAX_API_ENDPOINT_LENGTH` (32,768 UTF-16 code units).
333
+ The first code unit over that limit throws
334
+ `AudioRecognizer apiEndpoint exceeds maximum length of 32768 UTF-16 code units`
335
+ before trailing-slash scanning or endpoint joining. The SDK rejects the input;
336
+ it never truncates it. An explicitly supplied `apiEndpoint` is length-validated
337
+ during construction even when custom `authEndpoint` and `activityEndpoint`
338
+ values mean its prefix is not used for either join. This resource bound limits
339
+ construction work only. It is not an authentication, authorization, quota, or
340
+ abuse-prevention control.
213
341
 
214
342
  ## Session identifiers
215
343
 
@@ -296,11 +424,27 @@ const recognizer = new AudioRecognizer({
296
424
  });
297
425
  ```
298
426
 
427
+ Advanced callers that import `@sorisdk/web-audio/generated/window.js`
428
+ directly still use `appendFingerprint(bytes: Uint8Array): void`. Each generated
429
+ window exposes `maxAppendFingerprintByteLength()`, which is the byte length of
430
+ one complete query for that instance. An append exactly at that limit is
431
+ accepted. A larger append throws a `RangeError` before the JavaScript array is
432
+ copied into WASM, with this deterministic message:
433
+
434
+ ```text
435
+ Fingerprint append byteLength <actual> exceeds the per-instance limit of <limit> bytes
436
+ ```
437
+
438
+ The high-level SDK enforces the same boundary before it invokes the generated
439
+ class. Oversized input is rejected, never truncated or split; normal microphone
440
+ fingerprint chunks and the existing match-window cadence are unchanged.
441
+
299
442
  ## Integration flow
300
443
 
301
444
  1. Prepare your `appId` and ephemeral key flow.
302
445
  2. Create an `AudioRecognizer`.
303
- 3. Subscribe to the events you need, such as `campaign`, `match`, and `error`.
446
+ 3. Subscribe to the events you need, such as `campaign`, `audiomarker`, `match`,
447
+ and `error`.
304
448
  4. Call `start()` to begin recognition.
305
449
  5. Call `stop()` or `destroy()` when leaving the page or stopping capture.
306
450
 
@@ -6,6 +6,7 @@ export class WasmFingerprintMatchWindow {
6
6
  [Symbol.dispose](): void;
7
7
  appendFingerprint(bytes: Uint8Array): void;
8
8
  hasReadyQuery(): boolean;
9
+ maxAppendFingerprintByteLength(): number;
9
10
  constructor(sample_rate: number, afpgen_config: any | null | undefined, match_window_ms: number, match_stride_ms: number);
10
11
  reset(): void;
11
12
  takeReadyQuery(): any;
@@ -13,9 +13,10 @@ export class WasmFingerprintMatchWindow {
13
13
  * @param {Uint8Array} bytes
14
14
  */
15
15
  appendFingerprint(bytes) {
16
- const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
17
- const len0 = WASM_VECTOR_LEN;
18
- wasm.wasmfingerprintmatchwindow_appendFingerprint(this.__wbg_ptr, ptr0, len0);
16
+ const ret = wasm.wasmfingerprintmatchwindow_appendFingerprint(this.__wbg_ptr, bytes);
17
+ if (ret[1]) {
18
+ throw takeFromExternrefTable0(ret[0]);
19
+ }
19
20
  }
20
21
  /**
21
22
  * @returns {boolean}
@@ -24,6 +25,13 @@ export class WasmFingerprintMatchWindow {
24
25
  const ret = wasm.wasmfingerprintmatchwindow_hasReadyQuery(this.__wbg_ptr);
25
26
  return ret !== 0;
26
27
  }
28
+ /**
29
+ * @returns {number}
30
+ */
31
+ maxAppendFingerprintByteLength() {
32
+ const ret = wasm.wasmfingerprintmatchwindow_maxAppendFingerprintByteLength(this.__wbg_ptr);
33
+ return ret >>> 0;
34
+ }
27
35
  /**
28
36
  * @param {number} sample_rate
29
37
  * @param {any | null | undefined} afpgen_config
@@ -47,7 +55,10 @@ export class WasmFingerprintMatchWindow {
47
55
  */
48
56
  takeReadyQuery() {
49
57
  const ret = wasm.wasmfingerprintmatchwindow_takeReadyQuery(this.__wbg_ptr);
50
- return ret;
58
+ if (ret[2]) {
59
+ throw takeFromExternrefTable0(ret[1]);
60
+ }
61
+ return takeFromExternrefTable0(ret[0]);
51
62
  }
52
63
  }
53
64
  if (Symbol.dispose) WasmFingerprintMatchWindow.prototype[Symbol.dispose] = WasmFingerprintMatchWindow.prototype.free;
@@ -82,6 +93,10 @@ export function __wbg___wbindgen_in_a5d8b22e52b24dd1(arg0, arg1) {
82
93
  const ret = arg0 in arg1;
83
94
  return ret;
84
95
  }
96
+ export function __wbg___wbindgen_is_function_3baa9db1a987f47d(arg0) {
97
+ const ret = typeof(arg0) === 'function';
98
+ return ret;
99
+ }
85
100
  export function __wbg___wbindgen_is_null_52ff4ec04186736f(arg0) {
86
101
  const ret = arg0 === null;
87
102
  return ret;
@@ -116,6 +131,26 @@ export function __wbg___wbindgen_string_get_7ed5322991caaec5(arg0, arg1) {
116
131
  export function __wbg___wbindgen_throw_6b64449b9b9ed33c(arg0, arg1) {
117
132
  throw new Error(getStringFromWasm0(arg0, arg1));
118
133
  }
134
+ export function __wbg_call_14b169f759b26747() { return handleError(function (arg0, arg1) {
135
+ const ret = arg0.call(arg1);
136
+ return ret;
137
+ }, arguments); }
138
+ export function __wbg_call_a24592a6f349a97e() { return handleError(function (arg0, arg1, arg2) {
139
+ const ret = arg0.call(arg1, arg2);
140
+ return ret;
141
+ }, arguments); }
142
+ export function __wbg_getOwnPropertyDescriptor_131bd582a45a6f5d(arg0, arg1) {
143
+ const ret = Object.getOwnPropertyDescriptor(arg0, arg1);
144
+ return ret;
145
+ }
146
+ export function __wbg_getPrototypeOf_a56da9261bbd1e5b(arg0) {
147
+ const ret = Object.getPrototypeOf(arg0);
148
+ return ret;
149
+ }
150
+ export function __wbg_get_6011fa3a58f61074() { return handleError(function (arg0, arg1) {
151
+ const ret = Reflect.get(arg0, arg1);
152
+ return ret;
153
+ }, arguments); }
119
154
  export function __wbg_get_with_ref_key_6412cf3094599694(arg0, arg1) {
120
155
  const ret = arg0[arg1];
121
156
  return ret;
@@ -152,6 +187,10 @@ export function __wbg_new_0c7403db6e782f19(arg0) {
152
187
  const ret = new Uint8Array(arg0);
153
188
  return ret;
154
189
  }
190
+ export function __wbg_new_191521fecb171639(arg0, arg1) {
191
+ const ret = new RangeError(getStringFromWasm0(arg0, arg1));
192
+ return ret;
193
+ }
155
194
  export function __wbg_new_from_slice_b5ea43e23f6008c0(arg0, arg1) {
156
195
  const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
157
196
  return ret;
@@ -159,7 +198,28 @@ export function __wbg_new_from_slice_b5ea43e23f6008c0(arg0, arg1) {
159
198
  export function __wbg_prototypesetcall_a6b02eb00b0f4ce2(arg0, arg1, arg2) {
160
199
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
161
200
  }
201
+ export function __wbg_static_accessor_GLOBAL_8cfadc87a297ca02() {
202
+ const ret = typeof global === 'undefined' ? null : global;
203
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
204
+ }
205
+ export function __wbg_static_accessor_GLOBAL_THIS_602256ae5c8f42cf() {
206
+ const ret = typeof globalThis === 'undefined' ? null : globalThis;
207
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
208
+ }
209
+ export function __wbg_static_accessor_SELF_e445c1c7484aecc3() {
210
+ const ret = typeof self === 'undefined' ? null : self;
211
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
212
+ }
213
+ export function __wbg_static_accessor_WINDOW_f20e8576ef1e0f17() {
214
+ const ret = typeof window === 'undefined' ? null : window;
215
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
216
+ }
162
217
  export function __wbindgen_cast_0000000000000001(arg0, arg1) {
218
+ // Cast intrinsic for `Ref(Slice(U8)) -> NamedExternref("Uint8Array")`.
219
+ const ret = getArrayU8FromWasm0(arg0, arg1);
220
+ return ret;
221
+ }
222
+ export function __wbindgen_cast_0000000000000002(arg0, arg1) {
163
223
  // Cast intrinsic for `Ref(String) -> Externref`.
164
224
  const ret = getStringFromWasm0(arg0, arg1);
165
225
  return ret;
@@ -274,15 +334,17 @@ function getUint8ArrayMemory0() {
274
334
  return cachedUint8ArrayMemory0;
275
335
  }
276
336
 
277
- function isLikeNone(x) {
278
- return x === undefined || x === null;
337
+ function handleError(f, args) {
338
+ try {
339
+ return f.apply(this, args);
340
+ } catch (e) {
341
+ const idx = addToExternrefTable0(e);
342
+ wasm.__wbindgen_exn_store(idx);
343
+ }
279
344
  }
280
345
 
281
- function passArray8ToWasm0(arg, malloc) {
282
- const ptr = malloc(arg.length * 1, 1) >>> 0;
283
- getUint8ArrayMemory0().set(arg, ptr / 1);
284
- WASM_VECTOR_LEN = arg.length;
285
- return ptr;
346
+ function isLikeNone(x) {
347
+ return x === undefined || x === null;
286
348
  }
287
349
 
288
350
  function passStringToWasm0(arg, malloc, realloc) {
Binary file
@@ -2,14 +2,16 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const __wbg_wasmfingerprintmatchwindow_free: (a: number, b: number) => void;
5
- export const wasmfingerprintmatchwindow_appendFingerprint: (a: number, b: number, c: number) => void;
5
+ export const wasmfingerprintmatchwindow_appendFingerprint: (a: number, b: any) => [number, number];
6
6
  export const wasmfingerprintmatchwindow_hasReadyQuery: (a: number) => number;
7
+ export const wasmfingerprintmatchwindow_maxAppendFingerprintByteLength: (a: number) => number;
7
8
  export const wasmfingerprintmatchwindow_new: (a: number, b: number, c: number, d: number) => [number, number, number];
8
9
  export const wasmfingerprintmatchwindow_reset: (a: number) => void;
9
- export const wasmfingerprintmatchwindow_takeReadyQuery: (a: number) => any;
10
+ export const wasmfingerprintmatchwindow_takeReadyQuery: (a: number) => [number, number, number];
10
11
  export const __wbindgen_malloc: (a: number, b: number) => number;
11
12
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
12
- export const __wbindgen_externrefs: WebAssembly.Table;
13
+ export const __wbindgen_exn_store: (a: number) => void;
13
14
  export const __externref_table_alloc: () => number;
15
+ export const __wbindgen_externrefs: WebAssembly.Table;
14
16
  export const __externref_table_dealloc: (a: number) => void;
15
17
  export const __wbindgen_start: () => void;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { MatcherEphemeralAuthOptions, InitMatcherOptions, MatcherEphemeralAuthResult, AudioMarkerDetection, PackSource, MatchResult, AudioFingerprintType } from '@sorisdk/matcher';
2
- export { AudioFingerprintType, AudioMarkerConfig, AudioMarkerDetection, PackSource } from '@sorisdk/matcher';
1
+ import { MatcherEphemeralAuthOptions, InitMatcherOptions, MatcherEphemeralAuthResult, PackSource, MatchResult, MatcherSessionOptions, AudioFingerprintType } from '@sorisdk/matcher';
2
+ export { AudioFingerprintType, AudioMarkerConfig, PackSource } from '@sorisdk/matcher';
3
3
  import { InitAfpgenOptions } from '@sorisdk/afpgen';
4
4
 
5
5
  declare const DEFAULT_BROWSER_AUDIOPACK_VERSION = "20220401000000";
@@ -53,15 +53,22 @@ interface InitMatchWindowWasmOptions {
53
53
  }
54
54
 
55
55
  interface DetectedMatch extends Pick<MatchResult, "afpType" | "durationMillis" | "name" | "position" | "score"> {
56
- audioMarker?: AudioMarkerDetection | null;
56
+ }
57
+ /** SORI Console-managed identity resolved from a successful activity response. */
58
+ interface AudioMarkerIdentity {
59
+ readonly id: string;
60
+ readonly name: string;
57
61
  }
58
62
  interface AudioMarkerEvent {
59
- marker: string | null;
60
- detection: AudioMarkerDetection;
63
+ readonly marker: AudioMarkerIdentity;
61
64
  }
62
65
  interface MaterialActivityRequestPayload {
63
66
  type: "material";
64
67
  material_id: string;
68
+ /** SDK-owned UTC recognition timestamp. Custom mapper values are overwritten on POST. */
69
+ recognized_at?: string;
70
+ /** SDK-owned matcher position in milliseconds. Custom mapper values are overwritten on POST. */
71
+ position?: number;
65
72
  refinement_expected?: true;
66
73
  trait?: {
67
74
  marker?: string;
@@ -107,7 +114,7 @@ interface MicrophoneMatcherActivityReporterOptions {
107
114
  }
108
115
  interface CreateMicrophoneMatcherWasmOptions {
109
116
  afpgen?: InitAfpgenOptions;
110
- matcher?: Omit<InitMatcherOptions, "auth">;
117
+ matcher?: Omit<MatcherSessionOptions, "auth">;
111
118
  matchWindow?: InitMatchWindowWasmOptions;
112
119
  }
113
120
  interface CreateMicrophoneMatcherOptions {
@@ -147,6 +154,7 @@ type MicrophoneMatcherListener<T extends MicrophoneMatcherEventName> = (payload:
147
154
  type Awaitable<T> = T | Promise<T>;
148
155
  type AudioRecognizerMatcherOptions = Omit<CreateMicrophoneMatcherOptions, "activityReporter" | "packSource">;
149
156
  declare const DEFAULT_SORI_API_ENDPOINT = "https://console.soriapi.com/api";
157
+ declare const MAX_API_ENDPOINT_LENGTH: number;
150
158
  interface AudioRecognizerAuthOptions {
151
159
  endpoint: string | URL;
152
160
  appId: string;
@@ -238,7 +246,6 @@ declare class MicrophoneMatcher {
238
246
  private markerPcmBuffer;
239
247
  private resampleBuffer;
240
248
  private resampleOffset;
241
- private latestAudioMarker;
242
249
  private latestAudioMarkerDetection;
243
250
  private audioMarkerRequestId;
244
251
  private activityRecognitionId;
@@ -276,7 +283,6 @@ declare class MicrophoneMatcher {
276
283
  private detectAudioMarkerForRequest;
277
284
  private matchConfig;
278
285
  private withAudioMarkerForRequest;
279
- private emitAudioMarkerIfChanged;
280
286
  private normalizeInputSamples;
281
287
  private resampleToTargetRate;
282
288
  private cleanupAfterStartFailure;
@@ -291,4 +297,4 @@ declare function requestMicrophoneStream(mediaDevices: MediaDevices, mediaConstr
291
297
  preferredSampleRate?: number;
292
298
  }): Promise<MediaStream>;
293
299
 
294
- export { ACTIVITY_REFINEMENT_WINDOW_MS, type ActivityRefinementFailureContext, type ActivityRefinementRequestContext, type AudioMarkerEvent, AudioRecognizer, type AudioRecognizerAuthOptions, type AudioRecognizerOptions, type AuthenticateAndLoadAudioPackOptions, type AuthenticateAndLoadAudioPackResult, type BrowserAudioPackLoader, type BrowserAudioPackState, type BrowserAudioPackStateStore, type BrowserSessionManager, type CreateLocalStorageAudioPackStoreOptions, type CreateLocalStorageSessionManagerOptions, type CreateMicrophoneMatcherOptions, type CreateMicrophoneMatcherWasmOptions, DEFAULT_BROWSER_AUDIOPACK_VERSION, DEFAULT_SORI_API_ENDPOINT, type DetectedMatch, type MaterialActivityRequestPayload, MicrophoneMatcher, type MicrophoneMatcherActivityRefinementOptions, type MicrophoneMatcherActivityReporterOptions, type MicrophoneMatcherCampaignEvent, type MicrophoneMatcherEventMap, type MicrophoneMatcherEventName, type MicrophoneMatcherListener, authenticateAndLoadAudioPack, createLocalStorageAudioPackStore, createLocalStorageSessionManager, createMicrophoneMatcher, requestMicrophoneStream };
300
+ export { ACTIVITY_REFINEMENT_WINDOW_MS, type ActivityRefinementFailureContext, type ActivityRefinementRequestContext, type AudioMarkerEvent, type AudioMarkerIdentity, AudioRecognizer, type AudioRecognizerAuthOptions, type AudioRecognizerOptions, type AuthenticateAndLoadAudioPackOptions, type AuthenticateAndLoadAudioPackResult, type BrowserAudioPackLoader, type BrowserAudioPackState, type BrowserAudioPackStateStore, type BrowserSessionManager, type CreateLocalStorageAudioPackStoreOptions, type CreateLocalStorageSessionManagerOptions, type CreateMicrophoneMatcherOptions, type CreateMicrophoneMatcherWasmOptions, DEFAULT_BROWSER_AUDIOPACK_VERSION, DEFAULT_SORI_API_ENDPOINT, type DetectedMatch, MAX_API_ENDPOINT_LENGTH, type MaterialActivityRequestPayload, MicrophoneMatcher, type MicrophoneMatcherActivityRefinementOptions, type MicrophoneMatcherActivityReporterOptions, type MicrophoneMatcherCampaignEvent, type MicrophoneMatcherEventMap, type MicrophoneMatcherEventName, type MicrophoneMatcherListener, authenticateAndLoadAudioPack, createLocalStorageAudioPackStore, createLocalStorageSessionManager, createMicrophoneMatcher, requestMicrophoneStream };