@newgameplusinc/odyssey-audio-video-sdk-dev 1.0.258 → 1.0.260
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 +45 -1
- package/dist/audio/AudioNodeFactory.d.ts +130 -0
- package/dist/audio/AudioNodeFactory.js +158 -0
- package/dist/audio/AudioPipeline.d.ts +89 -0
- package/dist/audio/AudioPipeline.js +138 -0
- package/dist/{MLNoiseSuppressor.d.ts → audio/MLNoiseSuppressor.d.ts} +7 -7
- package/dist/{MLNoiseSuppressor.js → audio/MLNoiseSuppressor.js} +19 -52
- package/dist/audio/index.d.ts +6 -0
- package/dist/audio/index.js +22 -0
- package/dist/channels/huddle/HuddleChannel.d.ts +87 -0
- package/dist/channels/huddle/HuddleChannel.js +152 -0
- package/dist/channels/huddle/HuddleTypes.d.ts +85 -0
- package/dist/channels/huddle/HuddleTypes.js +25 -0
- package/dist/channels/huddle/index.d.ts +5 -0
- package/dist/channels/huddle/index.js +21 -0
- package/dist/channels/index.d.ts +5 -0
- package/dist/channels/index.js +21 -0
- package/dist/channels/spatial/SpatialAudioChannel.d.ts +144 -0
- package/dist/channels/spatial/SpatialAudioChannel.js +476 -0
- package/dist/channels/spatial/SpatialAudioTypes.d.ts +85 -0
- package/dist/channels/spatial/SpatialAudioTypes.js +42 -0
- package/dist/channels/spatial/index.d.ts +5 -0
- package/dist/channels/spatial/index.js +21 -0
- package/dist/{EventManager.d.ts → core/EventManager.d.ts} +4 -2
- package/dist/{EventManager.js → core/EventManager.js} +5 -3
- package/dist/{MediasoupManager.d.ts → core/MediasoupManager.d.ts} +10 -4
- package/dist/{MediasoupManager.js → core/MediasoupManager.js} +56 -44
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +21 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +43 -9
- package/dist/sdk/index.d.ts +36 -0
- package/dist/sdk/index.js +121 -0
- package/dist/types/events.d.ts +154 -0
- package/dist/{types.js → types/events.js} +3 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.js +23 -0
- package/dist/types/participant.d.ts +65 -0
- package/dist/types/participant.js +5 -0
- package/dist/types/position.d.ts +47 -0
- package/dist/types/position.js +9 -0
- package/dist/types/room.d.ts +82 -0
- package/dist/types/room.js +5 -0
- package/dist/utils/audio/clarity-score.d.ts +33 -0
- package/dist/utils/audio/clarity-score.js +81 -0
- package/dist/utils/audio/index.d.ts +5 -0
- package/dist/utils/audio/index.js +21 -0
- package/dist/utils/audio/voice-filter.d.ts +30 -0
- package/dist/utils/audio/voice-filter.js +70 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/position/coordinates.d.ts +37 -0
- package/dist/utils/position/coordinates.js +61 -0
- package/dist/utils/position/index.d.ts +6 -0
- package/dist/utils/position/index.js +22 -0
- package/dist/utils/position/normalize.d.ts +37 -0
- package/dist/utils/position/normalize.js +78 -0
- package/dist/utils/position/snap.d.ts +51 -0
- package/dist/utils/position/snap.js +81 -0
- package/dist/utils/smoothing/gain-smoothing.d.ts +45 -0
- package/dist/utils/smoothing/gain-smoothing.js +77 -0
- package/dist/utils/smoothing/index.d.ts +5 -0
- package/dist/utils/smoothing/index.js +21 -0
- package/dist/utils/smoothing/pan-smoothing.d.ts +43 -0
- package/dist/utils/smoothing/pan-smoothing.js +85 -0
- package/dist/utils/spatial/angle-calc.d.ts +24 -0
- package/dist/utils/spatial/angle-calc.js +69 -0
- package/dist/utils/spatial/distance-calc.d.ts +33 -0
- package/dist/utils/spatial/distance-calc.js +48 -0
- package/dist/utils/spatial/gain-calc.d.ts +37 -0
- package/dist/utils/spatial/gain-calc.js +52 -0
- package/dist/utils/spatial/head-position.d.ts +32 -0
- package/dist/utils/spatial/head-position.js +76 -0
- package/dist/utils/spatial/index.d.ts +9 -0
- package/dist/utils/spatial/index.js +25 -0
- package/dist/utils/spatial/listener-calc.d.ts +28 -0
- package/dist/utils/spatial/listener-calc.js +74 -0
- package/dist/utils/spatial/pan-calc.d.ts +48 -0
- package/dist/utils/spatial/pan-calc.js +80 -0
- package/package.json +1 -1
- package/dist/SpatialAudioManager.d.ts +0 -271
- package/dist/SpatialAudioManager.js +0 -1512
- package/dist/types.d.ts +0 -73
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Spatial Audio Types
|
|
4
|
+
*
|
|
5
|
+
* Type definitions for spatial audio processing
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DEFAULT_DENOISER_OPTIONS = exports.DEFAULT_SPATIAL_CONFIG = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Default spatial distance configuration
|
|
11
|
+
*/
|
|
12
|
+
exports.DEFAULT_SPATIAL_CONFIG = {
|
|
13
|
+
refDistance: 1.2,
|
|
14
|
+
maxDistance: 15,
|
|
15
|
+
rolloffFactor: 1.35,
|
|
16
|
+
unit: 'auto',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Default denoiser configuration
|
|
20
|
+
*/
|
|
21
|
+
exports.DEFAULT_DENOISER_OPTIONS = {
|
|
22
|
+
enabled: false,
|
|
23
|
+
threshold: 0.002,
|
|
24
|
+
noiseFloor: 0.0005,
|
|
25
|
+
release: 0.4,
|
|
26
|
+
attack: 0.1,
|
|
27
|
+
holdMs: 200,
|
|
28
|
+
maxReduction: 0.15,
|
|
29
|
+
hissCut: 0.15,
|
|
30
|
+
expansionRatio: 1.05,
|
|
31
|
+
learnRate: 0.03,
|
|
32
|
+
voiceBoost: 0.35,
|
|
33
|
+
voiceSensitivity: 0.1,
|
|
34
|
+
voiceEnhancement: false,
|
|
35
|
+
silenceFloor: 0.0002,
|
|
36
|
+
silenceHoldMs: 400,
|
|
37
|
+
silenceReleaseMs: 200,
|
|
38
|
+
speechBoost: 0.25,
|
|
39
|
+
highBandGate: 0.15,
|
|
40
|
+
highBandAttack: 0.08,
|
|
41
|
+
highBandRelease: 0.03,
|
|
42
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Spatial module - Re-exports spatial audio channel functionality
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./SpatialAudioTypes"), exports);
|
|
21
|
+
__exportStar(require("./SpatialAudioChannel"), exports);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
2
|
-
import { OdysseyEvent } from "./types";
|
|
3
1
|
/**
|
|
2
|
+
* Event Manager
|
|
3
|
+
*
|
|
4
4
|
* A clean, standalone event bus for the SDK, completely decoupled from the socket.
|
|
5
5
|
* This ensures that only processed, structured SDK events are emitted to the application.
|
|
6
6
|
* It extends the Node.js EventEmitter to provide a standard and reliable event API.
|
|
7
7
|
*/
|
|
8
|
+
import { EventEmitter } from 'events';
|
|
9
|
+
import { OdysseyEvent } from '../types/events';
|
|
8
10
|
export declare class EventManager extends EventEmitter {
|
|
9
11
|
constructor();
|
|
10
12
|
on(event: OdysseyEvent, listener: (...args: any[]) => void): this;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EventManager = void 0;
|
|
4
|
-
const events_1 = require("events");
|
|
5
2
|
/**
|
|
3
|
+
* Event Manager
|
|
4
|
+
*
|
|
6
5
|
* A clean, standalone event bus for the SDK, completely decoupled from the socket.
|
|
7
6
|
* This ensures that only processed, structured SDK events are emitted to the application.
|
|
8
7
|
* It extends the Node.js EventEmitter to provide a standard and reliable event API.
|
|
9
8
|
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EventManager = void 0;
|
|
11
|
+
const events_1 = require("events");
|
|
10
12
|
class EventManager extends events_1.EventEmitter {
|
|
11
13
|
constructor() {
|
|
12
14
|
super();
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Mediasoup Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles WebRTC transport, producer, and consumer management
|
|
5
|
+
* using the mediasoup-client library
|
|
6
|
+
*/
|
|
7
|
+
import * as mediasoupClient from 'mediasoup-client';
|
|
8
|
+
import { types } from 'mediasoup-client';
|
|
9
|
+
import { Socket } from 'socket.io-client';
|
|
4
10
|
export declare class MediasoupManager {
|
|
5
11
|
private device;
|
|
6
12
|
private socket;
|
|
@@ -20,7 +26,7 @@ export declare class MediasoupManager {
|
|
|
20
26
|
consume(data: {
|
|
21
27
|
consumerId: string;
|
|
22
28
|
producerId: string;
|
|
23
|
-
kind:
|
|
29
|
+
kind: 'audio' | 'video';
|
|
24
30
|
rtpParameters: any;
|
|
25
31
|
participantId: string;
|
|
26
32
|
}): Promise<{
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mediasoup Manager
|
|
4
|
+
*
|
|
5
|
+
* Handles WebRTC transport, producer, and consumer management
|
|
6
|
+
* using the mediasoup-client library
|
|
7
|
+
*/
|
|
2
8
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
9
|
if (k2 === undefined) k2 = k;
|
|
4
10
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -53,32 +59,32 @@ class MediasoupManager {
|
|
|
53
59
|
}
|
|
54
60
|
sendDeviceRtpCapabilities(participantId) {
|
|
55
61
|
this.participantId = participantId;
|
|
56
|
-
this.socket.emit(
|
|
62
|
+
this.socket.emit('device-rtp-capabilities', {
|
|
57
63
|
participantId,
|
|
58
64
|
rtpCapabilities: this.device.rtpCapabilities,
|
|
59
65
|
});
|
|
60
66
|
}
|
|
61
67
|
async createSendTransport(participantId) {
|
|
62
|
-
const params = await this.createWebRtcTransport(
|
|
68
|
+
const params = await this.createWebRtcTransport('send', participantId);
|
|
63
69
|
this.sendTransport = this.device.createSendTransport(params);
|
|
64
70
|
this.connectSendTransport();
|
|
65
71
|
}
|
|
66
72
|
async createRecvTransport(participantId) {
|
|
67
|
-
const params = await this.createWebRtcTransport(
|
|
73
|
+
const params = await this.createWebRtcTransport('recv', participantId);
|
|
68
74
|
this.recvTransport = this.device.createRecvTransport(params);
|
|
69
75
|
this.connectRecvTransport();
|
|
70
76
|
}
|
|
71
77
|
connectSendTransport() {
|
|
72
|
-
this.sendTransport?.on(
|
|
73
|
-
this.socket.emit(
|
|
78
|
+
this.sendTransport?.on('connect', async ({ dtlsParameters }, callback, errback) => {
|
|
79
|
+
this.socket.emit('connect-transport', { transportId: this.sendTransport.id, dtlsParameters }, (response) => {
|
|
74
80
|
if (response.error)
|
|
75
81
|
errback(new Error(response.error));
|
|
76
82
|
else
|
|
77
83
|
callback();
|
|
78
84
|
});
|
|
79
85
|
});
|
|
80
|
-
this.sendTransport?.on(
|
|
81
|
-
this.socket.emit(
|
|
86
|
+
this.sendTransport?.on('produce', async ({ kind, rtpParameters, appData, }, callback, errback) => {
|
|
87
|
+
this.socket.emit('produce', {
|
|
82
88
|
transportId: this.sendTransport.id,
|
|
83
89
|
kind,
|
|
84
90
|
rtpParameters,
|
|
@@ -90,59 +96,56 @@ class MediasoupManager {
|
|
|
90
96
|
callback({ id: response.producerId });
|
|
91
97
|
});
|
|
92
98
|
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (state === "failed" || state === "closed") {
|
|
96
|
-
// Clear all producers since transport is dead
|
|
99
|
+
this.sendTransport?.on('connectionstatechange', (state) => {
|
|
100
|
+
if (state === 'failed' || state === 'closed') {
|
|
97
101
|
this.producers.clear();
|
|
98
|
-
|
|
99
|
-
this.socket.emit("transport-failed", {
|
|
102
|
+
this.socket.emit('transport-failed', {
|
|
100
103
|
participantId: this.participantId,
|
|
101
|
-
direction:
|
|
104
|
+
direction: 'send',
|
|
102
105
|
});
|
|
103
106
|
}
|
|
104
107
|
});
|
|
105
108
|
}
|
|
106
109
|
connectRecvTransport() {
|
|
107
|
-
this.recvTransport?.on(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
this.recvTransport?.on('connect', async ({ dtlsParameters }, callback, errback) => {
|
|
111
|
+
console.log(`🎧 [MediasoupManager] Recv transport connecting, DTLS params:`, {
|
|
112
|
+
transportId: this.recvTransport.id.substring(0, 8),
|
|
113
|
+
});
|
|
114
|
+
this.socket.emit('connect-transport', { transportId: this.recvTransport.id, dtlsParameters }, (response) => {
|
|
115
|
+
if (response.error) {
|
|
116
|
+
console.error(`🎧 [MediasoupManager] ❌ Recv transport connect failed:`, response.error);
|
|
110
117
|
errback(new Error(response.error));
|
|
111
|
-
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.log(`🎧 [MediasoupManager] ✅ Recv transport connected`);
|
|
112
121
|
callback();
|
|
122
|
+
}
|
|
113
123
|
});
|
|
114
124
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (state ===
|
|
118
|
-
|
|
125
|
+
this.recvTransport?.on('connectionstatechange', (state) => {
|
|
126
|
+
console.log(`🎧 [MediasoupManager] Recv transport connection state changed: ${state}`);
|
|
127
|
+
if (state === 'failed' || state === 'closed') {
|
|
128
|
+
console.error(`🎧 [MediasoupManager] ❌ Recv transport ${state}`);
|
|
119
129
|
}
|
|
120
130
|
});
|
|
121
131
|
}
|
|
122
132
|
async produce(track, appData) {
|
|
123
133
|
if (!this.sendTransport)
|
|
124
|
-
throw new Error(
|
|
125
|
-
// Configure simulcast for video tracks for adaptive bitrate
|
|
134
|
+
throw new Error('Send transport not initialized');
|
|
126
135
|
const produceOptions = { track, appData };
|
|
127
136
|
if (track.kind === 'video') {
|
|
128
137
|
produceOptions.encodings = [
|
|
129
|
-
// Low quality layer - 100 kbps, good for poor connections
|
|
130
138
|
{ rid: 'r0', active: true, maxBitrate: 100000, scaleResolutionDownBy: 4 },
|
|
131
|
-
// Medium quality layer - 300 kbps, balanced
|
|
132
139
|
{ rid: 'r1', active: true, maxBitrate: 300000, scaleResolutionDownBy: 2 },
|
|
133
|
-
|
|
134
|
-
{ rid: 'r2', active: true, maxBitrate: 900000, scaleResolutionDownBy: 1 }
|
|
140
|
+
{ rid: 'r2', active: true, maxBitrate: 900000, scaleResolutionDownBy: 1 },
|
|
135
141
|
];
|
|
136
|
-
// VP8 codec for simulcast support
|
|
137
142
|
produceOptions.codecOptions = {
|
|
138
|
-
videoGoogleStartBitrate: 1000
|
|
143
|
+
videoGoogleStartBitrate: 1000,
|
|
139
144
|
};
|
|
140
145
|
}
|
|
141
146
|
const producer = await this.sendTransport.produce(produceOptions);
|
|
142
|
-
// Handle producer events
|
|
143
147
|
producer.on('transportclose', () => {
|
|
144
148
|
this.producers.delete(producer.id);
|
|
145
|
-
// The main SDK (index.ts) should handle recreation
|
|
146
149
|
});
|
|
147
150
|
producer.on('trackended', () => {
|
|
148
151
|
producer.close();
|
|
@@ -153,17 +156,30 @@ class MediasoupManager {
|
|
|
153
156
|
}
|
|
154
157
|
async consume(data) {
|
|
155
158
|
if (!this.recvTransport)
|
|
156
|
-
throw new Error(
|
|
159
|
+
throw new Error('Receive transport not set up');
|
|
160
|
+
console.log(`🎧 [MediasoupManager] Creating consumer for ${data.participantId.substring(0, 8)}`, {
|
|
161
|
+
consumerId: data.consumerId.substring(0, 8),
|
|
162
|
+
producerId: data.producerId.substring(0, 8),
|
|
163
|
+
kind: data.kind,
|
|
164
|
+
recvTransportId: this.recvTransport.id.substring(0, 8),
|
|
165
|
+
recvTransportConnectionState: this.recvTransport.connectionState,
|
|
166
|
+
});
|
|
157
167
|
const consumer = await this.recvTransport.consume({
|
|
158
168
|
id: data.consumerId,
|
|
159
169
|
producerId: data.producerId,
|
|
160
170
|
kind: data.kind,
|
|
161
171
|
rtpParameters: data.rtpParameters,
|
|
162
172
|
});
|
|
163
|
-
|
|
173
|
+
console.log(`🎧 [MediasoupManager] Consumer created for ${data.participantId.substring(0, 8)}`, {
|
|
174
|
+
consumerId: consumer.id.substring(0, 8),
|
|
175
|
+
trackKind: consumer.track.kind,
|
|
176
|
+
trackEnabled: consumer.track.enabled,
|
|
177
|
+
trackMuted: consumer.track.muted,
|
|
178
|
+
trackReadyState: consumer.track.readyState,
|
|
179
|
+
consumerPaused: consumer.paused,
|
|
180
|
+
});
|
|
164
181
|
consumer.on('transportclose', () => {
|
|
165
182
|
this.consumers.delete(consumer.id);
|
|
166
|
-
// The main SDK (index.ts) should handle recreation
|
|
167
183
|
});
|
|
168
184
|
consumer.on('trackended', () => {
|
|
169
185
|
consumer.close();
|
|
@@ -174,7 +190,7 @@ class MediasoupManager {
|
|
|
174
190
|
}
|
|
175
191
|
async resumeConsumer(consumerId) {
|
|
176
192
|
return new Promise((resolve, reject) => {
|
|
177
|
-
this.socket.emit(
|
|
193
|
+
this.socket.emit('resume-consumer', { consumerId, participantId: this.participantId }, (response) => {
|
|
178
194
|
if (response.error) {
|
|
179
195
|
reject(new Error(response.error));
|
|
180
196
|
}
|
|
@@ -186,23 +202,19 @@ class MediasoupManager {
|
|
|
186
202
|
}
|
|
187
203
|
async createWebRtcTransport(direction, participantId) {
|
|
188
204
|
return new Promise((resolve, reject) => {
|
|
189
|
-
// Set up listener for transport-created event
|
|
190
205
|
const handleTransportCreated = (data) => {
|
|
191
206
|
if (data.type === direction) {
|
|
192
|
-
|
|
193
|
-
this.socket.off("transport-created", handleTransportCreated);
|
|
207
|
+
this.socket.off('transport-created', handleTransportCreated);
|
|
194
208
|
if (data.error) {
|
|
195
209
|
return reject(new Error(data.error));
|
|
196
210
|
}
|
|
197
211
|
resolve(data.params);
|
|
198
212
|
}
|
|
199
213
|
};
|
|
200
|
-
this.socket.on(
|
|
201
|
-
|
|
202
|
-
this.socket.emit("create-transport", { direction, participantId });
|
|
203
|
-
// Add timeout to prevent hanging forever
|
|
214
|
+
this.socket.on('transport-created', handleTransportCreated);
|
|
215
|
+
this.socket.emit('create-transport', { direction, participantId });
|
|
204
216
|
setTimeout(() => {
|
|
205
|
-
this.socket.off(
|
|
217
|
+
this.socket.off('transport-created', handleTransportCreated);
|
|
206
218
|
reject(new Error(`Timeout waiting for ${direction} transport`));
|
|
207
219
|
}, 10000);
|
|
208
220
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Core module - Re-exports core SDK components
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./EventManager"), exports);
|
|
21
|
+
__exportStar(require("./MediasoupManager"), exports);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EventManager } from "./EventManager";
|
|
2
|
-
import { SpatialAudioOptions } from "./
|
|
1
|
+
import { EventManager } from "./core/EventManager";
|
|
2
|
+
import { SpatialAudioOptions } from "./channels/spatial/SpatialAudioChannel";
|
|
3
3
|
import { Direction, MediaState, OdysseyEvent, Participant, Position, RoomJoinedData } from "./types";
|
|
4
4
|
export declare class OdysseySpatialComms extends EventManager {
|
|
5
5
|
private socket;
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OdysseySpatialComms = void 0;
|
|
4
4
|
const socket_io_client_1 = require("socket.io-client");
|
|
5
|
-
const EventManager_1 = require("./EventManager");
|
|
6
|
-
const MediasoupManager_1 = require("./MediasoupManager");
|
|
7
|
-
const
|
|
5
|
+
const EventManager_1 = require("./core/EventManager");
|
|
6
|
+
const MediasoupManager_1 = require("./core/MediasoupManager");
|
|
7
|
+
const SpatialAudioChannel_1 = require("./channels/spatial/SpatialAudioChannel");
|
|
8
8
|
class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
9
9
|
constructor(serverUrl, spatialOptions) {
|
|
10
10
|
super(); // Initialize the EventEmitter base class
|
|
@@ -14,7 +14,7 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
14
14
|
transports: ["websocket"],
|
|
15
15
|
});
|
|
16
16
|
this.mediasoupManager = new MediasoupManager_1.MediasoupManager(this.socket);
|
|
17
|
-
this.spatialAudioManager = new
|
|
17
|
+
this.spatialAudioManager = new SpatialAudioChannel_1.SpatialAudioManager(spatialOptions);
|
|
18
18
|
// Set max listeners to prevent warning
|
|
19
19
|
this.setMaxListeners(50);
|
|
20
20
|
this.listenForEvents();
|
|
@@ -211,6 +211,15 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
211
211
|
pan: spatialData?.pan,
|
|
212
212
|
dxLocal: spatialData?.dxLocal,
|
|
213
213
|
};
|
|
214
|
+
// ========== DEBUG: SDK SENDING TO SERVER ==========
|
|
215
|
+
console.log("📤 [SDK->Server] updatePosition:", {
|
|
216
|
+
participantId: updateData.participantId,
|
|
217
|
+
position: updateData.position,
|
|
218
|
+
direction: updateData.direction,
|
|
219
|
+
rot: updateData.rot,
|
|
220
|
+
pan: updateData.pan,
|
|
221
|
+
dxLocal: updateData.dxLocal,
|
|
222
|
+
});
|
|
214
223
|
this.socket.emit("update-position", updateData);
|
|
215
224
|
}
|
|
216
225
|
}
|
|
@@ -229,6 +238,13 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
229
238
|
this.spatialAudioManager.setListenerPosition(position, orientation);
|
|
230
239
|
}
|
|
231
240
|
setListenerFromLSD(listenerPos, cameraPos, lookAtPos, rot) {
|
|
241
|
+
// ========== DEBUG: LISTENER POSITION UPDATE ==========
|
|
242
|
+
console.log("🎧 [SDK] setListenerFromLSD:", {
|
|
243
|
+
listenerPos,
|
|
244
|
+
cameraPos,
|
|
245
|
+
lookAtPos,
|
|
246
|
+
rot,
|
|
247
|
+
});
|
|
232
248
|
this.spatialAudioManager.setListenerFromLSD(listenerPos, cameraPos, lookAtPos, rot);
|
|
233
249
|
}
|
|
234
250
|
listenForEvents() {
|
|
@@ -383,11 +399,19 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
383
399
|
participant.consumers.set(consumer.id, consumer);
|
|
384
400
|
if (track.kind === "audio") {
|
|
385
401
|
participant.audioTrack = track;
|
|
402
|
+
console.log(`🎧 [SDK] Received audio consumer for ${participant.participantId.substring(0, 8)}`, {
|
|
403
|
+
consumerId: consumer.id.substring(0, 8),
|
|
404
|
+
trackEnabled: track.enabled,
|
|
405
|
+
trackMuted: track.muted,
|
|
406
|
+
trackReadyState: track.readyState,
|
|
407
|
+
consumerPaused: consumer.paused,
|
|
408
|
+
});
|
|
386
409
|
// CRITICAL: Do NOT setup spatial audio for local participant (yourself)
|
|
387
410
|
// This prevents hearing your own microphone (loopback)
|
|
388
411
|
const isLocalParticipant = participant.participantId ===
|
|
389
412
|
this.localParticipant?.participantId;
|
|
390
413
|
if (isLocalParticipant) {
|
|
414
|
+
console.log(`🎧 [SDK] Skipping audio setup for local participant (prevent loopback)`);
|
|
391
415
|
// Do NOT connect this audio to Web Audio API
|
|
392
416
|
return; // Exit early to prevent any audio processing
|
|
393
417
|
}
|
|
@@ -395,18 +419,20 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
395
419
|
// Check if participant is in a huddle (non-spatial channel)
|
|
396
420
|
const participantChannel = participant.currentChannel || "spatial";
|
|
397
421
|
const isInHuddle = participantChannel !== "spatial";
|
|
422
|
+
console.log(`🎧 [SDK] Setting up spatial audio for ${participant.participantId.substring(0, 8)}, huddle: ${isInHuddle}`);
|
|
398
423
|
// Setup spatial audio - bypass 3D positioning for huddle members
|
|
399
424
|
await this.spatialAudioManager.setupSpatialAudioForParticipant(participant.participantId, track, isInHuddle // Bypass spatialization if in huddle
|
|
400
425
|
);
|
|
401
426
|
}
|
|
402
427
|
// NOW resume the consumer after audio pipeline is ready
|
|
428
|
+
console.log(`🎧 [SDK] Resuming consumer ${consumer.id.substring(0, 8)}...`);
|
|
403
429
|
this.mediasoupManager
|
|
404
430
|
.resumeConsumer(consumer.id)
|
|
405
431
|
.then(() => {
|
|
406
|
-
|
|
432
|
+
console.log(`🎧 [SDK] ✅ Consumer ${consumer.id.substring(0, 8)} resumed successfully`);
|
|
407
433
|
})
|
|
408
|
-
.catch(() => {
|
|
409
|
-
|
|
434
|
+
.catch((err) => {
|
|
435
|
+
console.error(`🎧 [SDK] ❌ Failed to resume consumer ${consumer.id.substring(0, 8)}:`, err);
|
|
410
436
|
});
|
|
411
437
|
}
|
|
412
438
|
else if (track.kind === "video") {
|
|
@@ -436,8 +462,16 @@ class OdysseySpatialComms extends EventManager_1.EventManager {
|
|
|
436
462
|
}
|
|
437
463
|
});
|
|
438
464
|
this.socket.on("participant-position-updated", (data) => {
|
|
439
|
-
// DEBUG:
|
|
440
|
-
console.log(
|
|
465
|
+
// ========== DEBUG: SDK RECEIVED FROM SERVER ==========
|
|
466
|
+
console.log("📥 [SDK<-Server] participant-position-updated:", {
|
|
467
|
+
participantId: data.participantId,
|
|
468
|
+
position: data.position,
|
|
469
|
+
direction: data.direction,
|
|
470
|
+
rot: data.rot,
|
|
471
|
+
pan: data.pan,
|
|
472
|
+
dxLocal: data.dxLocal,
|
|
473
|
+
currentChannel: data.currentChannel,
|
|
474
|
+
});
|
|
441
475
|
const participant = this.room?.participants.get(data.participantId);
|
|
442
476
|
if (participant) {
|
|
443
477
|
participant.position = data.position;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Odyssey Mediasoup SDK - Main Entry Point
|
|
3
|
+
*
|
|
4
|
+
* A comprehensive WebRTC SDK for real-time audio/video communication
|
|
5
|
+
* with spatial audio and ML-powered noise suppression.
|
|
6
|
+
*
|
|
7
|
+
* @module @odyssey/mediasoup-sdk
|
|
8
|
+
*/
|
|
9
|
+
export type { Position, Direction, Rotation, ListenerRight, UnrealPosition, StandardPosition, } from '../types/position';
|
|
10
|
+
export type { Participant, MediaState, ParticipantSnapshot, } from '../types/participant';
|
|
11
|
+
export type { RoomJoinedEvent, ConsumerCreatedEvent, ConsumerClosedEvent, ConsumerPausedEvent, ConsumerResumedEvent, ParticipantJoinedEvent, ParticipantLeftEvent, ParticipantPositionEvent, MuteStateChangedEvent, HuddleInviteReceivedEvent, HuddleResponseEvent, OdysseyEvent, OdysseyEventMap, } from '../types/events';
|
|
12
|
+
export type { Room, RoomJoinedData, JoinRoomData, ConsumerCreatedData, TransportOptions, ProducerOptions, } from '../types/room';
|
|
13
|
+
export { getDistanceBetween, getHorizontalDistance, isWithinRange, } from '../utils/spatial/distance-calc';
|
|
14
|
+
export { calculateLogarithmicGain, DEFAULT_GAIN_CONFIG, type GainConfig, } from '../utils/spatial/gain-calc';
|
|
15
|
+
export { calculateListenerRight, calculatePanFromPositions, panValueToPanning, type Panning, } from '../utils/spatial/pan-calc';
|
|
16
|
+
export { computeHeadPosition, parseBodyHeight, getVectorFromListener, } from '../utils/spatial/head-position';
|
|
17
|
+
export { getListenerRightFromRotation, calculateListenerOrientation, type ListenerOrientation, } from '../utils/spatial/listener-calc';
|
|
18
|
+
export { computeAzimuthFromPositions, calculateAngleToSource, } from '../utils/spatial/angle-calc';
|
|
19
|
+
export { normalizePositionUnits, metersToCentimeters, centimetersToMeters, isLikelyCentimeters, } from '../utils/position/normalize';
|
|
20
|
+
export { PositionSnapCache, snapPositionSimple, SNAP_CONFIG, type SnapConfig, } from '../utils/position/snap';
|
|
21
|
+
export { unrealToStandard, standardToUnreal, autoConvertToStandard, } from '../utils/position/coordinates';
|
|
22
|
+
export { PanSmoother, DEFAULT_PAN_SMOOTHER_OPTIONS, type PanSmootherOptions, } from '../utils/smoothing/pan-smoothing';
|
|
23
|
+
export { applyGainSmooth, applyStereoPanSmooth, GainTracker, } from '../utils/smoothing/gain-smoothing';
|
|
24
|
+
export { calculateClarityScore, calculateProximityWeight, normalizeVector, } from '../utils/audio/clarity-score';
|
|
25
|
+
export { calculateAdaptiveHighpass, createVoiceFilterChain, } from '../utils/audio/voice-filter';
|
|
26
|
+
export { HuddleChannel, type HuddleChannelConfig, } from '../channels/huddle/HuddleChannel';
|
|
27
|
+
export { SPATIAL_CHANNEL_ID, isHuddleChannel, type HuddleInvite, type HuddleResponse, type HuddleAcceptResponse, type HuddleRejectResponse, } from '../channels/huddle/HuddleTypes';
|
|
28
|
+
export { SpatialAudioChannel, type SpatialAudioConfig, } from '../channels/spatial/SpatialAudioChannel';
|
|
29
|
+
export { DEFAULT_SPATIAL_CONFIG, DEFAULT_DENOISER_OPTIONS, type SpatialDistanceConfig, type DenoiserOptions, type ParticipantAudioNodes, type ListenerState, } from '../channels/spatial/SpatialAudioTypes';
|
|
30
|
+
export { createMasterChain, createFilterChain, connectFilterChain, createLimiter, createMonoDownmixChain, connectMonoDownmixChain, DEFAULT_PIPELINE_CONFIG, type AudioPipelineConfig, type MasterAudioChain, type ParticipantFilterChain, type MonoDownmixChain, } from '../audio/AudioPipeline';
|
|
31
|
+
export { createPanner, createStereoPanner, createGain, createAnalyser, createHighpassFilter, createLowpassFilter, createPeakingFilter, createCompressor, createMediaStreamSource, DEFAULT_PANNER_CONFIG, type PannerConfig, type HighpassConfig, type LowpassConfig, type PeakingConfig, type CompressorConfig, } from '../audio/AudioNodeFactory';
|
|
32
|
+
export { MLNoiseSuppressor } from '../audio/MLNoiseSuppressor';
|
|
33
|
+
export { EventManager } from '../core/EventManager';
|
|
34
|
+
export { MediasoupManager } from '../core/MediasoupManager';
|
|
35
|
+
export declare const SDK_VERSION = "2.0.0";
|
|
36
|
+
export declare const SDK_NAME = "Odyssey Mediasoup SDK";
|