whio-api-sdk 1.0.198-beta-staging → 1.0.200-beta-staging

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.
@@ -5,7 +5,7 @@ The SDK now supports real-time audio streaming via WebSocket connections, provid
5
5
  ## Features
6
6
 
7
7
  - 🔄 **Auto-reconnection** with exponential backoff
8
- - 📡 **Real-time audio streaming** with float array support
8
+ - 📡 **Real-time audio streaming** with base64 audio support
9
9
  - 🎯 **Event-driven architecture** for connection and audio events
10
10
  - 🛡️ **Automatic authentication** using existing SDK tokens
11
11
  - 📊 **Connection statistics** and monitoring
@@ -85,7 +85,7 @@ sdk.onWebSocketEvent('connection-error', (error) => {
85
85
 
86
86
  ```typescript
87
87
  // Stream individual audio chunks
88
- const audioChunk = [0.1, 0.2, -0.3, 0.4]; // Float array
88
+ const audioChunk = "SGVsbG8gV29ybGQ="; // Base64 encoded audio data
89
89
  sdk.streamAudioChunk(session.id, audioChunk, false);
90
90
 
91
91
  // Stream final chunk to trigger transcription
@@ -97,9 +97,9 @@ sdk.streamAudioChunk(session.id, finalChunk, true);
97
97
  ```typescript
98
98
  // Stream multiple chunks with automatic pacing
99
99
  const audioChunks = [
100
- [0.1, 0.2, 0.3],
101
- [0.4, 0.5, 0.6],
102
- [0.7, 0.8, 0.9]
100
+ "SGVsbG8gV29ybGQ=", // Base64 chunk 1
101
+ "QmFzZTY0IGNodW5r", // Base64 chunk 2
102
+ "QXVkaW8gZGF0YQ==" // Base64 chunk 3
103
103
  ];
104
104
 
105
105
  await sdk.streamAudioChunks(session.id, audioChunks, {
@@ -120,9 +120,9 @@ processor.onaudioprocess = (event) => {
120
120
  const inputBuffer = event.inputBuffer;
121
121
  const inputData = inputBuffer.getChannelData(0);
122
122
 
123
- // Convert to regular array and stream
124
- const audioChunk = Array.from(inputData);
125
- sdk.streamAudioChunk(session.id, audioChunk, false);
123
+ // Convert float data to base64 (you'll need your own conversion logic)
124
+ const base64Chunk = convertFloatArrayToBase64(inputData);
125
+ sdk.streamAudioChunk(session.id, base64Chunk, false);
126
126
  };
127
127
 
128
128
  source.connect(processor);
@@ -130,7 +130,7 @@ processor.connect(audioContext.destination);
130
130
 
131
131
  // Stop recording and trigger transcription
132
132
  setTimeout(() => {
133
- sdk.streamAudioChunk(session.id, [], true);
133
+ sdk.streamAudioChunk(session.id, "", true); // Empty string for end
134
134
  // Cleanup...
135
135
  }, 10000);
136
136
  ```
@@ -187,11 +187,11 @@ The server automatically buffers audio chunks and flushes them when:
187
187
 
188
188
  ```typescript
189
189
  // The server handles buffering automatically
190
- sdk.streamAudioChunk(sessionId, chunk1, false); // Buffered
191
- sdk.streamAudioChunk(sessionId, chunk2, false); // Buffered
190
+ sdk.streamAudioChunk(sessionId, base64Chunk1, false); // Buffered
191
+ sdk.streamAudioChunk(sessionId, base64Chunk2, false); // Buffered
192
192
  // ... (8 more chunks buffered)
193
- sdk.streamAudioChunk(sessionId, chunk10, false); // Auto-flush triggered
194
- sdk.streamAudioChunk(sessionId, chunk11, true); // End flag triggers transcription
193
+ sdk.streamAudioChunk(sessionId, base64Chunk10, false); // Auto-flush triggered
194
+ sdk.streamAudioChunk(sessionId, base64Chunk11, true); // End flag triggers transcription
195
195
  ```
196
196
 
197
197
  ## Error Handling
@@ -253,6 +253,6 @@ for (const chunk of audioChunks) {
253
253
  ## Troubleshooting
254
254
 
255
255
  - **Connection Issues**: Check network connectivity and authentication
256
- - **Audio Not Processing**: Ensure chunks are valid float arrays
256
+ - **Audio Not Processing**: Ensure chunks are valid base64 strings
257
257
  - **Transcription Not Starting**: Verify end flag is sent
258
258
  - **Reconnection Problems**: Check server availability and token validity
@@ -17,7 +17,7 @@ export declare class WebSocketModule extends BaseClient {
17
17
  /**
18
18
  * Connect to WebSocket server
19
19
  */
20
- connect(): void;
20
+ connect(): Promise<void>;
21
21
  /**
22
22
  * Disconnect from WebSocket server
23
23
  */
@@ -33,11 +33,11 @@ export declare class WebSocketModule extends BaseClient {
33
33
  /**
34
34
  * Stream audio chunk to server
35
35
  */
36
- streamAudioChunk(sessionId: string, audioChunk: number[] | number[][], isEnd?: boolean): void;
36
+ streamAudioChunk(sessionId: string, audioChunk: string, isEnd?: boolean): void;
37
37
  /**
38
38
  * Stream multiple audio chunks with automatic end detection
39
39
  */
40
- streamAudioChunks(sessionId: string, audioChunks: number[], options?: AudioStreamingOptions): Promise<void>;
40
+ streamAudioChunks(sessionId: string, audioChunks: string[], options?: AudioStreamingOptions): Promise<void>;
41
41
  /**
42
42
  * Add event listener
43
43
  */
@@ -29,7 +29,9 @@ export class WebSocketModule extends BaseClient {
29
29
  reconnectAttempts: 0
30
30
  };
31
31
  if (this.config.autoConnect) {
32
- this.connect();
32
+ this.connect().catch(error => {
33
+ console.error('Failed to auto-connect WebSocket:', error);
34
+ });
33
35
  }
34
36
  }
35
37
  /**
@@ -37,23 +39,32 @@ export class WebSocketModule extends BaseClient {
37
39
  */
38
40
  connect() {
39
41
  var _a;
40
- if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected) {
41
- return;
42
- }
43
- const wsUrl = this.getWebSocketUrl();
44
- const token = this.getAccessToken();
45
- if (!token) {
46
- this.emit('connection-error', new Error('No access token available for WebSocket connection'));
47
- return;
48
- }
49
- this.socket = io(wsUrl, {
50
- auth: {
51
- token: token
52
- },
53
- forceNew: true,
54
- timeout: 10000
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected) {
44
+ return;
45
+ }
46
+ const wsUrl = this.getWebSocketUrl();
47
+ try {
48
+ // Ensure we have a fresh token before connecting
49
+ yield this.getToken();
50
+ const token = this.getAccessToken();
51
+ if (!token) {
52
+ this.emit('connection-error', new Error('No access token available for WebSocket connection'));
53
+ return;
54
+ }
55
+ this.socket = io(wsUrl, {
56
+ auth: {
57
+ token: token
58
+ },
59
+ forceNew: true,
60
+ timeout: 10000
61
+ });
62
+ this.setupEventHandlers();
63
+ }
64
+ catch (error) {
65
+ this.emit('connection-error', error);
66
+ }
55
67
  });
56
- this.setupEventHandlers();
57
68
  }
58
69
  /**
59
70
  * Disconnect from WebSocket server
@@ -107,11 +118,10 @@ export class WebSocketModule extends BaseClient {
107
118
  if (!((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected)) {
108
119
  throw new Error('WebSocket not connected. Cannot stream audio chunks.');
109
120
  }
110
- const chunks = audioChunks;
111
121
  const delay = options.bufferSize || 100; // ms between chunks
112
- for (let i = 0; i < chunks.length; i++) {
113
- const isLastChunk = i === chunks.length - 1;
114
- this.streamAudioChunk(sessionId, chunks, isLastChunk);
122
+ for (let i = 0; i < audioChunks.length; i++) {
123
+ const isLastChunk = i === audioChunks.length - 1;
124
+ this.streamAudioChunk(sessionId, audioChunks[i], isLastChunk);
115
125
  // Small delay between chunks to prevent overwhelming the server
116
126
  if (!isLastChunk) {
117
127
  yield new Promise(resolve => setTimeout(resolve, delay));
@@ -231,9 +241,9 @@ export class WebSocketModule extends BaseClient {
231
241
  // Calculate exponential backoff delay
232
242
  const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), this.maxReconnectDelay);
233
243
  this.emit('reconnecting', this.reconnectAttempts);
234
- this.reconnectTimeout = setTimeout(() => {
235
- this.connect();
236
- }, delay);
244
+ this.reconnectTimeout = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
245
+ yield this.connect();
246
+ }), delay);
237
247
  }
238
248
  /**
239
249
  * Get WebSocket URL
@@ -183,7 +183,7 @@ export declare class ApiSDK extends BaseClient {
183
183
  getExternalIntegration(...args: Parameters<ExternalIntegrationModule['getExternalIntegration']>): Promise<import("./types").ExternalIntegration>;
184
184
  updateExternalIntegration(...args: Parameters<ExternalIntegrationModule['updateExternalIntegration']>): Promise<import("./types").ExternalIntegration>;
185
185
  deleteExternalIntegration(...args: Parameters<ExternalIntegrationModule['deleteExternalIntegration']>): Promise<void>;
186
- connectWebSocket(): void;
186
+ connectWebSocket(): Promise<void>;
187
187
  disconnectWebSocket(): void;
188
188
  isWebSocketConnected(): boolean;
189
189
  streamAudioChunk(...args: Parameters<WebSocketModule['streamAudioChunk']>): void;
@@ -1,6 +1,6 @@
1
1
  export interface AudioChunkPayload {
2
2
  sessionId: string;
3
- audioChunk: number[] | number[][];
3
+ audioChunk: string;
4
4
  flag: 'end' | null;
5
5
  }
6
6
  export interface WebSocketConfig {
@@ -72,21 +72,19 @@ async function exampleWebSocketAudioStreaming() {
72
72
 
73
73
  console.log('WebSocket connected, starting audio streaming...');
74
74
 
75
- // Simulate audio data (in a real app, this would come from microphone)
76
- const simulateAudioChunks = (): number[][] => {
77
- const chunks: number[][] = [];
75
+ // Simulate base64 audio data (in a real app, this would come from your audio processing)
76
+ const simulateBase64AudioChunks = (): string[] => {
77
+ const chunks: string[] = [];
78
78
  for (let i = 0; i < 15; i++) {
79
- const chunk: number[] = [];
80
- for (let j = 0; j < 1024; j++) {
81
- // Generate random audio samples between -1 and 1
82
- chunk.push((Math.random() - 0.5) * 2);
83
- }
84
- chunks.push(chunk);
79
+ // Simulate different sized base64 chunks (this would be your actual audio data)
80
+ const mockData = `mock-audio-chunk-${i}-${Date.now()}`;
81
+ const base64Chunk = btoa(mockData);
82
+ chunks.push(base64Chunk);
85
83
  }
86
84
  return chunks;
87
85
  };
88
86
 
89
- const audioChunks = simulateAudioChunks();
87
+ const audioChunks = simulateBase64AudioChunks();
90
88
 
91
89
  // Stream audio chunks one by one
92
90
  for (let i = 0; i < audioChunks.length; i++) {
@@ -159,11 +157,12 @@ async function exampleMicrophoneStreaming() {
159
157
  const inputBuffer = event.inputBuffer;
160
158
  const inputData = inputBuffer.getChannelData(0);
161
159
 
162
- // Convert Float32Array to regular array
163
- const audioChunk = Array.from(inputData);
160
+ // Convert Float32Array to base64 (you'll need your own conversion logic)
161
+ // This is just a placeholder - replace with your actual conversion
162
+ const mockBase64 = btoa(String.fromCharCode(...Array.from(inputData.slice(0, 100))));
164
163
 
165
- // Stream the audio chunk
166
- sdk.streamAudioChunk(session.id, audioChunk, false);
164
+ // Stream the base64 audio chunk
165
+ sdk.streamAudioChunk(session.id, mockBase64, false);
167
166
  };
168
167
 
169
168
  source.connect(processor);
@@ -173,8 +172,8 @@ async function exampleMicrophoneStreaming() {
173
172
 
174
173
  // Stop after 10 seconds and trigger transcription
175
174
  setTimeout(() => {
176
- // Send empty chunk with end flag to trigger transcription
177
- sdk.streamAudioChunk(session.id, [], true);
175
+ // Send empty base64 string with end flag to trigger transcription
176
+ sdk.streamAudioChunk(session.id, "", true);
178
177
 
179
178
  // Clean up
180
179
  processor.disconnect();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whio-api-sdk",
3
- "version": "1.0.198-beta-staging",
3
+ "version": "1.0.200-beta-staging",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -45,35 +45,44 @@ export class WebSocketModule extends BaseClient {
45
45
  };
46
46
 
47
47
  if (this.config.autoConnect) {
48
- this.connect();
48
+ this.connect().catch(error => {
49
+ console.error('Failed to auto-connect WebSocket:', error);
50
+ });
49
51
  }
50
52
  }
51
53
 
52
54
  /**
53
55
  * Connect to WebSocket server
54
56
  */
55
- public connect(): void {
57
+ public async connect(): Promise<void> {
56
58
  if (this.socket?.connected) {
57
59
  return;
58
60
  }
59
61
 
60
62
  const wsUrl = this.getWebSocketUrl();
61
- const token = this.getAccessToken();
62
-
63
- if (!token) {
64
- this.emit('connection-error', new Error('No access token available for WebSocket connection'));
65
- return;
66
- }
63
+
64
+ try {
65
+ // Ensure we have a fresh token before connecting
66
+ await this.getToken();
67
+ const token = this.getAccessToken();
68
+
69
+ if (!token) {
70
+ this.emit('connection-error', new Error('No access token available for WebSocket connection'));
71
+ return;
72
+ }
67
73
 
68
- this.socket = io(wsUrl, {
69
- auth: {
70
- token: token
71
- },
72
- forceNew: true,
73
- timeout: 10000
74
- });
74
+ this.socket = io(wsUrl, {
75
+ auth: {
76
+ token: token
77
+ },
78
+ forceNew: true,
79
+ timeout: 10000
80
+ });
75
81
 
76
- this.setupEventHandlers();
82
+ this.setupEventHandlers();
83
+ } catch (error) {
84
+ this.emit('connection-error', error as Error);
85
+ }
77
86
  }
78
87
 
79
88
  /**
@@ -113,7 +122,7 @@ export class WebSocketModule extends BaseClient {
113
122
  */
114
123
  public streamAudioChunk(
115
124
  sessionId: string,
116
- audioChunk: number[] | number[][],
125
+ audioChunk: string,
117
126
  isEnd: boolean = false
118
127
  ): void {
119
128
  if (!this.socket?.connected) {
@@ -134,20 +143,19 @@ export class WebSocketModule extends BaseClient {
134
143
  */
135
144
  public async streamAudioChunks(
136
145
  sessionId: string,
137
- audioChunks: number[],
146
+ audioChunks: string[],
138
147
  options: AudioStreamingOptions = {}
139
148
  ): Promise<void> {
140
149
  if (!this.socket?.connected) {
141
150
  throw new Error('WebSocket not connected. Cannot stream audio chunks.');
142
151
  }
143
152
 
144
- const chunks = audioChunks;
145
153
  const delay = options.bufferSize || 100; // ms between chunks
146
154
 
147
- for (let i = 0; i < chunks.length; i++) {
148
- const isLastChunk = i === chunks.length - 1;
155
+ for (let i = 0; i < audioChunks.length; i++) {
156
+ const isLastChunk = i === audioChunks.length - 1;
149
157
 
150
- this.streamAudioChunk(sessionId, chunks, isLastChunk);
158
+ this.streamAudioChunk(sessionId, audioChunks[i], isLastChunk);
151
159
 
152
160
  // Small delay between chunks to prevent overwhelming the server
153
161
  if (!isLastChunk) {
@@ -301,8 +309,8 @@ export class WebSocketModule extends BaseClient {
301
309
 
302
310
  this.emit('reconnecting', this.reconnectAttempts);
303
311
 
304
- this.reconnectTimeout = setTimeout(() => {
305
- this.connect();
312
+ this.reconnectTimeout = setTimeout(async () => {
313
+ await this.connect();
306
314
  }, delay);
307
315
  }
308
316
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  export interface AudioChunkPayload {
4
4
  sessionId: string;
5
- audioChunk: number[] | number[][];
5
+ audioChunk: string; // Base64 encoded audio data
6
6
  flag: 'end' | null;
7
7
  }
8
8