@newgameplusinc/alpha-spatial-comms 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Position and Direction Types
3
+ *
4
+ * Coordinate system conventions:
5
+ * - Unreal Engine: X=forward, Y=right, Z=up (centimeters)
6
+ * - Standard/WebAudio: X=right, Y=up, Z=forward (meters)
7
+ */
8
+ /**
9
+ * 3D position in space
10
+ */
11
+ interface Position {
12
+ x: number;
13
+ y: number;
14
+ z: number;
15
+ }
16
+ /**
17
+ * 3D direction vector (normalized)
18
+ */
19
+ interface Direction {
20
+ x: number;
21
+ y: number;
22
+ z: number;
23
+ }
24
+
25
+ /**
26
+ * Spatial Audio Types
27
+ *
28
+ * Type definitions for spatial audio processing
29
+ */
30
+ /**
31
+ * Spatial audio distance configuration
32
+ *
33
+ * DISTANCE-BASED GAIN SPECIFICATION (CUBIC FALLOFF):
34
+ * ┌──────────────┬─────────┬────────────────────────────────┐
35
+ * │ Distance │ Gain % │ Description │
36
+ * ├──────────────┼─────────┼────────────────────────────────┤
37
+ * │ 0.0 - 0.5m │ 100% │ Full volume (intimate) │
38
+ * │ 1.0m │ ~90% │ Very close - still loud │
39
+ * │ 2.0m │ ~72% │ Normal talking - NOTICEABLE │
40
+ * │ 3.0m │ ~57% │ Across table - CLEARLY QUIETER │
41
+ * │ 5.0m │ ~33% │ Across room - MUCH QUIETER │
42
+ * │ 7.0m │ ~17% │ Far end of room - very faint │
43
+ * │ 10.0m │ ~4% │ Barely audible │
44
+ * │ ≥15.0m │ 0% │ Silent (COMPLETE CUTOFF) │
45
+ * └──────────────┴─────────┴────────────────────────────────┘
46
+ */
47
+ interface SpatialDistanceConfig {
48
+ refDistance?: number;
49
+ maxDistance?: number;
50
+ rolloffFactor?: number;
51
+ unit?: "auto" | "meters" | "centimeters";
52
+ }
53
+ /**
54
+ * Denoiser options for noise suppression
55
+ */
56
+ interface DenoiserOptions {
57
+ enabled?: boolean;
58
+ threshold?: number;
59
+ noiseFloor?: number;
60
+ release?: number;
61
+ attack?: number;
62
+ holdMs?: number;
63
+ maxReduction?: number;
64
+ hissCut?: number;
65
+ expansionRatio?: number;
66
+ learnRate?: number;
67
+ voiceBoost?: number;
68
+ voiceSensitivity?: number;
69
+ voiceEnhancement?: boolean;
70
+ silenceFloor?: number;
71
+ silenceHoldMs?: number;
72
+ silenceReleaseMs?: number;
73
+ speechBoost?: number;
74
+ highBandGate?: number;
75
+ highBandAttack?: number;
76
+ highBandRelease?: number;
77
+ }
78
+
79
+ /**
80
+ * Spatial Audio Channel
81
+ *
82
+ * Processes audio for spatial positioning using Web Audio API
83
+ */
84
+
85
+ /**
86
+ * Spatial audio configuration
87
+ */
88
+ interface SpatialAudioConfig {
89
+ distance?: SpatialDistanceConfig;
90
+ denoiser?: DenoiserOptions;
91
+ }
92
+
93
+ /**
94
+ * Participant Types
95
+ */
96
+
97
+ /**
98
+ * Media state for a participant
99
+ */
100
+ interface MediaState {
101
+ audio: boolean;
102
+ video: boolean;
103
+ sharescreen: boolean;
104
+ }
105
+ /**
106
+ * Full participant data
107
+ */
108
+ interface Participant {
109
+ participantId: string;
110
+ userId: string;
111
+ deviceId: string;
112
+ name?: string;
113
+ avatarUrl?: string;
114
+ isLocal: boolean;
115
+ audioTrack?: MediaStreamTrack;
116
+ videoTrack?: MediaStreamTrack;
117
+ producers: Map<string, any>;
118
+ consumers: Map<string, any>;
119
+ position: Position;
120
+ direction: Direction;
121
+ mediaState: MediaState;
122
+ rot?: {
123
+ x: number;
124
+ y: number;
125
+ z: number;
126
+ };
127
+ pan?: number;
128
+ dxLocal?: number;
129
+ bodyHeight?: string;
130
+ bodyShape?: string;
131
+ userName?: string;
132
+ userEmail?: string;
133
+ currentChannel?: string;
134
+ }
135
+
136
+ /**
137
+ * SDK Event Types
138
+ */
139
+
140
+ /**
141
+ * Result returned when space live broadcast starts successfully
142
+ * Contains info needed for Vue to write to Firebase
143
+ */
144
+ interface SpaceLiveBroadcastResult {
145
+ producerId: string;
146
+ roomId: string;
147
+ serverUrl: string;
148
+ timestamp: number;
149
+ }
150
+ /**
151
+ * Space Live Broadcast available event - emitted when someone starts broadcasting to space
152
+ */
153
+ interface SpaceLiveBroadcastAvailableEvent {
154
+ roomId: string;
155
+ producerId: string;
156
+ producerUserId: string;
157
+ userName: string;
158
+ }
159
+ /**
160
+ * Space Live Broadcast stopped event - emitted when broadcast ends
161
+ */
162
+ interface SpaceLiveBroadcastStoppedEvent {
163
+ roomId: string;
164
+ }
165
+ /**
166
+ * Space Live Broadcast status response
167
+ */
168
+ interface SpaceLiveBroadcastStatusResponse {
169
+ isActive: boolean;
170
+ producerId?: string;
171
+ producerUserId?: string;
172
+ userName?: string;
173
+ }
174
+ /**
175
+ * All SDK event types
176
+ */
177
+ type OdysseyEvent = "connected" | "disconnected" | "room-joined" | "all-participants-update" | "new-participant" | "participant-left" | "producer-created" | "consumer-created" | "consumer-closed" | "participant-media-state-updated" | "participant-position-updated" | "error" | "huddle-invite-received" | "private-huddle-started" | "huddle-updated" | "huddle-invite-rejected" | "huddle-ended" | "participant-channel-changed" | "mute-requested" | "space-live-broadcast-available" | "space-live-broadcast-stopped";
178
+
179
+ /**
180
+ * Room and Transport Types
181
+ */
182
+
183
+ /**
184
+ * Room joined data from server
185
+ */
186
+ interface RoomJoinedData {
187
+ participants: Participant[];
188
+ routerRtpCapabilities: any;
189
+ participantId: string;
190
+ roomId: string;
191
+ iceServers: any[];
192
+ }
193
+
194
+ interface ChatMessage {
195
+ text?: string;
196
+ notification?: any;
197
+ [key: string]: any;
198
+ }
199
+
200
+ interface OdysseySpatialCommsHandle {
201
+ room: {
202
+ id: string;
203
+ participants: Map<string, Participant>;
204
+ } | null;
205
+ on(event: OdysseyEvent, listener: (...args: any[]) => void): void;
206
+ off(event: OdysseyEvent, listener: (...args: any[]) => void): void;
207
+ initializeMLNoiseSuppression(modelPath: string, workletUrl?: string): Promise<void>;
208
+ joinRoom(data: {
209
+ roomId: string;
210
+ userId: string;
211
+ deviceId: string;
212
+ participantId?: string;
213
+ position: Position;
214
+ direction: Direction;
215
+ bodyHeight?: string;
216
+ bodyShape?: string;
217
+ userName?: string;
218
+ userEmail?: string;
219
+ }): Promise<Participant>;
220
+ leaveRoom(): void;
221
+ resumeAudio(): Promise<void>;
222
+ getAudioContextState(): AudioContextState;
223
+ enhanceOutgoingAudioTrack(track: MediaStreamTrack): Promise<MediaStreamTrack>;
224
+ isMLNoiseSuppressionActive(): boolean;
225
+ getNoiseSuppressionMode(): "ml" | "audioworklet" | "none";
226
+ setMasterMuted(muted: boolean): void;
227
+ getMasterMuted(): boolean;
228
+ produceTrack(track: MediaStreamTrack, appData?: {
229
+ isScreenshare?: boolean;
230
+ }): Promise<any>;
231
+ recreateProducers(): Promise<void>;
232
+ updatePosition(position: Position, direction: Direction, spatialData?: {
233
+ cameraDistance?: number;
234
+ screenPos?: {
235
+ x: number;
236
+ y: number;
237
+ } | null;
238
+ rot?: {
239
+ x: number;
240
+ y: number;
241
+ z: number;
242
+ };
243
+ pan?: number;
244
+ dxLocal?: number;
245
+ }): void;
246
+ updateMediaState(mediaState: MediaState): void;
247
+ stopScreenShare(): Promise<void>;
248
+ stopVideoProducer(): Promise<void>;
249
+ startSpaceLiveBroadcast(): Promise<SpaceLiveBroadcastResult>;
250
+ stopSpaceLiveBroadcast(): Promise<void>;
251
+ getSpaceLiveBroadcastStatus(callback: (info: {
252
+ isActive: boolean;
253
+ producerId?: string;
254
+ producerUserId?: string;
255
+ userName?: string;
256
+ }) => void): void;
257
+ readonly isSpaceLiveBroadcasting: boolean;
258
+ setListenerPosition(position: Position, orientation: {
259
+ forwardX: number;
260
+ forwardY: number;
261
+ forwardZ: number;
262
+ upX: number;
263
+ upY: number;
264
+ upZ: number;
265
+ }): void;
266
+ setListenerFromLSD(listenerPos: Position, cameraPos: Position, lookAtPos: Position, rot?: {
267
+ x: number;
268
+ y: number;
269
+ z: number;
270
+ }): void;
271
+ chat: {
272
+ init(data: {
273
+ userId: string;
274
+ userName?: string;
275
+ channelId: string;
276
+ channelName?: string;
277
+ }): Promise<void>;
278
+ sendMessage(message: ChatMessage): Promise<any>;
279
+ sendNotification(data: {
280
+ text: string;
281
+ participants: string[];
282
+ sender: {
283
+ deviceId: string;
284
+ name?: string;
285
+ img?: string;
286
+ };
287
+ }): Promise<any>;
288
+ leave(): Promise<void>;
289
+ onMessage(callback: (message: any) => void): void;
290
+ };
291
+ sendHuddleInvite(toParticipantId: string): Promise<{
292
+ success?: boolean;
293
+ inviteId?: string;
294
+ huddleId?: string;
295
+ error?: string;
296
+ }>;
297
+ acceptHuddleInvite(inviteId: string): Promise<{
298
+ success?: boolean;
299
+ huddleId?: string;
300
+ participants?: string[];
301
+ error?: string;
302
+ }>;
303
+ rejectHuddleInvite(inviteId: string): Promise<{
304
+ success?: boolean;
305
+ error?: string;
306
+ }>;
307
+ joinHuddle(): Promise<{
308
+ success?: boolean;
309
+ channelId?: string;
310
+ error?: string;
311
+ }>;
312
+ leaveHuddle(): Promise<{
313
+ success?: boolean;
314
+ channelId?: string;
315
+ error?: string;
316
+ }>;
317
+ getParticipantChannel(participantId: string): Promise<string>;
318
+ muteParticipant(participantId: string): Promise<{
319
+ success?: boolean;
320
+ error?: string;
321
+ }>;
322
+ getCurrentChannel(): string;
323
+ }
324
+ /**
325
+ * Create an Odyssey Spatial Comms instance (browser-only SDK).
326
+ * @param apiKey SDK API key issued by Odyssey (from payment service)
327
+ * @param userToken JWT access token for the authenticated user (from SSO)
328
+ * @param spatialOptions Optional spatial audio configuration
329
+ */
330
+ declare function createOdysseySpatialComms(apiKey: string, userToken: string, spatialOptions?: SpatialAudioConfig): OdysseySpatialCommsHandle;
331
+
332
+ declare const SpatialCommsSDK: {
333
+ /**
334
+ * Create a new SDK client instance.
335
+ * @param apiKey SDK API key issued by Odyssey (from payment service)
336
+ * @param userToken JWT access token for the authenticated user (from SSO)
337
+ * @param spatialOptions Optional spatial audio configuration
338
+ */
339
+ readonly create: (apiKey: string, userToken: string, spatialOptions?: SpatialAudioConfig) => OdysseySpatialCommsHandle;
340
+ };
341
+
342
+ export { type ChatMessage, type Direction, type MediaState, type OdysseyEvent, type OdysseyEvent as OdysseySDKEvent, type OdysseySpatialCommsHandle, type Participant, type Position, type RoomJoinedData, type SpaceLiveBroadcastAvailableEvent, type SpaceLiveBroadcastResult, type SpaceLiveBroadcastStatusResponse, type SpaceLiveBroadcastStoppedEvent, type SpatialAudioConfig as SpatialAudioOptions, SpatialCommsSDK, createOdysseySpatialComms };
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Position and Direction Types
3
+ *
4
+ * Coordinate system conventions:
5
+ * - Unreal Engine: X=forward, Y=right, Z=up (centimeters)
6
+ * - Standard/WebAudio: X=right, Y=up, Z=forward (meters)
7
+ */
8
+ /**
9
+ * 3D position in space
10
+ */
11
+ interface Position {
12
+ x: number;
13
+ y: number;
14
+ z: number;
15
+ }
16
+ /**
17
+ * 3D direction vector (normalized)
18
+ */
19
+ interface Direction {
20
+ x: number;
21
+ y: number;
22
+ z: number;
23
+ }
24
+
25
+ /**
26
+ * Spatial Audio Types
27
+ *
28
+ * Type definitions for spatial audio processing
29
+ */
30
+ /**
31
+ * Spatial audio distance configuration
32
+ *
33
+ * DISTANCE-BASED GAIN SPECIFICATION (CUBIC FALLOFF):
34
+ * ┌──────────────┬─────────┬────────────────────────────────┐
35
+ * │ Distance │ Gain % │ Description │
36
+ * ├──────────────┼─────────┼────────────────────────────────┤
37
+ * │ 0.0 - 0.5m │ 100% │ Full volume (intimate) │
38
+ * │ 1.0m │ ~90% │ Very close - still loud │
39
+ * │ 2.0m │ ~72% │ Normal talking - NOTICEABLE │
40
+ * │ 3.0m │ ~57% │ Across table - CLEARLY QUIETER │
41
+ * │ 5.0m │ ~33% │ Across room - MUCH QUIETER │
42
+ * │ 7.0m │ ~17% │ Far end of room - very faint │
43
+ * │ 10.0m │ ~4% │ Barely audible │
44
+ * │ ≥15.0m │ 0% │ Silent (COMPLETE CUTOFF) │
45
+ * └──────────────┴─────────┴────────────────────────────────┘
46
+ */
47
+ interface SpatialDistanceConfig {
48
+ refDistance?: number;
49
+ maxDistance?: number;
50
+ rolloffFactor?: number;
51
+ unit?: "auto" | "meters" | "centimeters";
52
+ }
53
+ /**
54
+ * Denoiser options for noise suppression
55
+ */
56
+ interface DenoiserOptions {
57
+ enabled?: boolean;
58
+ threshold?: number;
59
+ noiseFloor?: number;
60
+ release?: number;
61
+ attack?: number;
62
+ holdMs?: number;
63
+ maxReduction?: number;
64
+ hissCut?: number;
65
+ expansionRatio?: number;
66
+ learnRate?: number;
67
+ voiceBoost?: number;
68
+ voiceSensitivity?: number;
69
+ voiceEnhancement?: boolean;
70
+ silenceFloor?: number;
71
+ silenceHoldMs?: number;
72
+ silenceReleaseMs?: number;
73
+ speechBoost?: number;
74
+ highBandGate?: number;
75
+ highBandAttack?: number;
76
+ highBandRelease?: number;
77
+ }
78
+
79
+ /**
80
+ * Spatial Audio Channel
81
+ *
82
+ * Processes audio for spatial positioning using Web Audio API
83
+ */
84
+
85
+ /**
86
+ * Spatial audio configuration
87
+ */
88
+ interface SpatialAudioConfig {
89
+ distance?: SpatialDistanceConfig;
90
+ denoiser?: DenoiserOptions;
91
+ }
92
+
93
+ /**
94
+ * Participant Types
95
+ */
96
+
97
+ /**
98
+ * Media state for a participant
99
+ */
100
+ interface MediaState {
101
+ audio: boolean;
102
+ video: boolean;
103
+ sharescreen: boolean;
104
+ }
105
+ /**
106
+ * Full participant data
107
+ */
108
+ interface Participant {
109
+ participantId: string;
110
+ userId: string;
111
+ deviceId: string;
112
+ name?: string;
113
+ avatarUrl?: string;
114
+ isLocal: boolean;
115
+ audioTrack?: MediaStreamTrack;
116
+ videoTrack?: MediaStreamTrack;
117
+ producers: Map<string, any>;
118
+ consumers: Map<string, any>;
119
+ position: Position;
120
+ direction: Direction;
121
+ mediaState: MediaState;
122
+ rot?: {
123
+ x: number;
124
+ y: number;
125
+ z: number;
126
+ };
127
+ pan?: number;
128
+ dxLocal?: number;
129
+ bodyHeight?: string;
130
+ bodyShape?: string;
131
+ userName?: string;
132
+ userEmail?: string;
133
+ currentChannel?: string;
134
+ }
135
+
136
+ /**
137
+ * SDK Event Types
138
+ */
139
+
140
+ /**
141
+ * Result returned when space live broadcast starts successfully
142
+ * Contains info needed for Vue to write to Firebase
143
+ */
144
+ interface SpaceLiveBroadcastResult {
145
+ producerId: string;
146
+ roomId: string;
147
+ serverUrl: string;
148
+ timestamp: number;
149
+ }
150
+ /**
151
+ * Space Live Broadcast available event - emitted when someone starts broadcasting to space
152
+ */
153
+ interface SpaceLiveBroadcastAvailableEvent {
154
+ roomId: string;
155
+ producerId: string;
156
+ producerUserId: string;
157
+ userName: string;
158
+ }
159
+ /**
160
+ * Space Live Broadcast stopped event - emitted when broadcast ends
161
+ */
162
+ interface SpaceLiveBroadcastStoppedEvent {
163
+ roomId: string;
164
+ }
165
+ /**
166
+ * Space Live Broadcast status response
167
+ */
168
+ interface SpaceLiveBroadcastStatusResponse {
169
+ isActive: boolean;
170
+ producerId?: string;
171
+ producerUserId?: string;
172
+ userName?: string;
173
+ }
174
+ /**
175
+ * All SDK event types
176
+ */
177
+ type OdysseyEvent = "connected" | "disconnected" | "room-joined" | "all-participants-update" | "new-participant" | "participant-left" | "producer-created" | "consumer-created" | "consumer-closed" | "participant-media-state-updated" | "participant-position-updated" | "error" | "huddle-invite-received" | "private-huddle-started" | "huddle-updated" | "huddle-invite-rejected" | "huddle-ended" | "participant-channel-changed" | "mute-requested" | "space-live-broadcast-available" | "space-live-broadcast-stopped";
178
+
179
+ /**
180
+ * Room and Transport Types
181
+ */
182
+
183
+ /**
184
+ * Room joined data from server
185
+ */
186
+ interface RoomJoinedData {
187
+ participants: Participant[];
188
+ routerRtpCapabilities: any;
189
+ participantId: string;
190
+ roomId: string;
191
+ iceServers: any[];
192
+ }
193
+
194
+ interface ChatMessage {
195
+ text?: string;
196
+ notification?: any;
197
+ [key: string]: any;
198
+ }
199
+
200
+ interface OdysseySpatialCommsHandle {
201
+ room: {
202
+ id: string;
203
+ participants: Map<string, Participant>;
204
+ } | null;
205
+ on(event: OdysseyEvent, listener: (...args: any[]) => void): void;
206
+ off(event: OdysseyEvent, listener: (...args: any[]) => void): void;
207
+ initializeMLNoiseSuppression(modelPath: string, workletUrl?: string): Promise<void>;
208
+ joinRoom(data: {
209
+ roomId: string;
210
+ userId: string;
211
+ deviceId: string;
212
+ participantId?: string;
213
+ position: Position;
214
+ direction: Direction;
215
+ bodyHeight?: string;
216
+ bodyShape?: string;
217
+ userName?: string;
218
+ userEmail?: string;
219
+ }): Promise<Participant>;
220
+ leaveRoom(): void;
221
+ resumeAudio(): Promise<void>;
222
+ getAudioContextState(): AudioContextState;
223
+ enhanceOutgoingAudioTrack(track: MediaStreamTrack): Promise<MediaStreamTrack>;
224
+ isMLNoiseSuppressionActive(): boolean;
225
+ getNoiseSuppressionMode(): "ml" | "audioworklet" | "none";
226
+ setMasterMuted(muted: boolean): void;
227
+ getMasterMuted(): boolean;
228
+ produceTrack(track: MediaStreamTrack, appData?: {
229
+ isScreenshare?: boolean;
230
+ }): Promise<any>;
231
+ recreateProducers(): Promise<void>;
232
+ updatePosition(position: Position, direction: Direction, spatialData?: {
233
+ cameraDistance?: number;
234
+ screenPos?: {
235
+ x: number;
236
+ y: number;
237
+ } | null;
238
+ rot?: {
239
+ x: number;
240
+ y: number;
241
+ z: number;
242
+ };
243
+ pan?: number;
244
+ dxLocal?: number;
245
+ }): void;
246
+ updateMediaState(mediaState: MediaState): void;
247
+ stopScreenShare(): Promise<void>;
248
+ stopVideoProducer(): Promise<void>;
249
+ startSpaceLiveBroadcast(): Promise<SpaceLiveBroadcastResult>;
250
+ stopSpaceLiveBroadcast(): Promise<void>;
251
+ getSpaceLiveBroadcastStatus(callback: (info: {
252
+ isActive: boolean;
253
+ producerId?: string;
254
+ producerUserId?: string;
255
+ userName?: string;
256
+ }) => void): void;
257
+ readonly isSpaceLiveBroadcasting: boolean;
258
+ setListenerPosition(position: Position, orientation: {
259
+ forwardX: number;
260
+ forwardY: number;
261
+ forwardZ: number;
262
+ upX: number;
263
+ upY: number;
264
+ upZ: number;
265
+ }): void;
266
+ setListenerFromLSD(listenerPos: Position, cameraPos: Position, lookAtPos: Position, rot?: {
267
+ x: number;
268
+ y: number;
269
+ z: number;
270
+ }): void;
271
+ chat: {
272
+ init(data: {
273
+ userId: string;
274
+ userName?: string;
275
+ channelId: string;
276
+ channelName?: string;
277
+ }): Promise<void>;
278
+ sendMessage(message: ChatMessage): Promise<any>;
279
+ sendNotification(data: {
280
+ text: string;
281
+ participants: string[];
282
+ sender: {
283
+ deviceId: string;
284
+ name?: string;
285
+ img?: string;
286
+ };
287
+ }): Promise<any>;
288
+ leave(): Promise<void>;
289
+ onMessage(callback: (message: any) => void): void;
290
+ };
291
+ sendHuddleInvite(toParticipantId: string): Promise<{
292
+ success?: boolean;
293
+ inviteId?: string;
294
+ huddleId?: string;
295
+ error?: string;
296
+ }>;
297
+ acceptHuddleInvite(inviteId: string): Promise<{
298
+ success?: boolean;
299
+ huddleId?: string;
300
+ participants?: string[];
301
+ error?: string;
302
+ }>;
303
+ rejectHuddleInvite(inviteId: string): Promise<{
304
+ success?: boolean;
305
+ error?: string;
306
+ }>;
307
+ joinHuddle(): Promise<{
308
+ success?: boolean;
309
+ channelId?: string;
310
+ error?: string;
311
+ }>;
312
+ leaveHuddle(): Promise<{
313
+ success?: boolean;
314
+ channelId?: string;
315
+ error?: string;
316
+ }>;
317
+ getParticipantChannel(participantId: string): Promise<string>;
318
+ muteParticipant(participantId: string): Promise<{
319
+ success?: boolean;
320
+ error?: string;
321
+ }>;
322
+ getCurrentChannel(): string;
323
+ }
324
+ /**
325
+ * Create an Odyssey Spatial Comms instance (browser-only SDK).
326
+ * @param apiKey SDK API key issued by Odyssey (from payment service)
327
+ * @param userToken JWT access token for the authenticated user (from SSO)
328
+ * @param spatialOptions Optional spatial audio configuration
329
+ */
330
+ declare function createOdysseySpatialComms(apiKey: string, userToken: string, spatialOptions?: SpatialAudioConfig): OdysseySpatialCommsHandle;
331
+
332
+ declare const SpatialCommsSDK: {
333
+ /**
334
+ * Create a new SDK client instance.
335
+ * @param apiKey SDK API key issued by Odyssey (from payment service)
336
+ * @param userToken JWT access token for the authenticated user (from SSO)
337
+ * @param spatialOptions Optional spatial audio configuration
338
+ */
339
+ readonly create: (apiKey: string, userToken: string, spatialOptions?: SpatialAudioConfig) => OdysseySpatialCommsHandle;
340
+ };
341
+
342
+ export { type ChatMessage, type Direction, type MediaState, type OdysseyEvent, type OdysseyEvent as OdysseySDKEvent, type OdysseySpatialCommsHandle, type Participant, type Position, type RoomJoinedData, type SpaceLiveBroadcastAvailableEvent, type SpaceLiveBroadcastResult, type SpaceLiveBroadcastStatusResponse, type SpaceLiveBroadcastStoppedEvent, type SpatialAudioConfig as SpatialAudioOptions, SpatialCommsSDK, createOdysseySpatialComms };