whio-api-sdk 1.0.198-beta-staging → 1.0.199-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.
- package/WEBSOCKET_AUDIO_STREAMING.md +14 -14
- package/dist/src/sdk/modules/websocket.module.d.ts +2 -2
- package/dist/src/sdk/modules/websocket.module.js +3 -4
- package/dist/src/sdk/types/websocket.types.d.ts +1 -1
- package/examples/websocket-audio-streaming.ts +15 -16
- package/package.json +1 -1
- package/src/sdk/modules/websocket.module.ts +5 -6
- package/src/sdk/types/websocket.types.ts +1 -1
|
@@ -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
|
|
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 =
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
|
124
|
-
const
|
|
125
|
-
sdk.streamAudioChunk(session.id,
|
|
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,
|
|
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,
|
|
191
|
-
sdk.streamAudioChunk(sessionId,
|
|
190
|
+
sdk.streamAudioChunk(sessionId, base64Chunk1, false); // Buffered
|
|
191
|
+
sdk.streamAudioChunk(sessionId, base64Chunk2, false); // Buffered
|
|
192
192
|
// ... (8 more chunks buffered)
|
|
193
|
-
sdk.streamAudioChunk(sessionId,
|
|
194
|
-
sdk.streamAudioChunk(sessionId,
|
|
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
|
|
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
|
|
@@ -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:
|
|
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:
|
|
40
|
+
streamAudioChunks(sessionId: string, audioChunks: string[], options?: AudioStreamingOptions): Promise<void>;
|
|
41
41
|
/**
|
|
42
42
|
* Add event listener
|
|
43
43
|
*/
|
|
@@ -107,11 +107,10 @@ export class WebSocketModule extends BaseClient {
|
|
|
107
107
|
if (!((_a = this.socket) === null || _a === void 0 ? void 0 : _a.connected)) {
|
|
108
108
|
throw new Error('WebSocket not connected. Cannot stream audio chunks.');
|
|
109
109
|
}
|
|
110
|
-
const chunks = audioChunks;
|
|
111
110
|
const delay = options.bufferSize || 100; // ms between chunks
|
|
112
|
-
for (let i = 0; i <
|
|
113
|
-
const isLastChunk = i ===
|
|
114
|
-
this.streamAudioChunk(sessionId,
|
|
111
|
+
for (let i = 0; i < audioChunks.length; i++) {
|
|
112
|
+
const isLastChunk = i === audioChunks.length - 1;
|
|
113
|
+
this.streamAudioChunk(sessionId, audioChunks[i], isLastChunk);
|
|
115
114
|
// Small delay between chunks to prevent overwhelming the server
|
|
116
115
|
if (!isLastChunk) {
|
|
117
116
|
yield new Promise(resolve => setTimeout(resolve, delay));
|
|
@@ -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
|
|
76
|
-
const
|
|
77
|
-
const chunks:
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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 =
|
|
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
|
|
163
|
-
|
|
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,
|
|
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
|
|
177
|
-
sdk.streamAudioChunk(session.id,
|
|
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
|
@@ -113,7 +113,7 @@ export class WebSocketModule extends BaseClient {
|
|
|
113
113
|
*/
|
|
114
114
|
public streamAudioChunk(
|
|
115
115
|
sessionId: string,
|
|
116
|
-
audioChunk:
|
|
116
|
+
audioChunk: string,
|
|
117
117
|
isEnd: boolean = false
|
|
118
118
|
): void {
|
|
119
119
|
if (!this.socket?.connected) {
|
|
@@ -134,20 +134,19 @@ export class WebSocketModule extends BaseClient {
|
|
|
134
134
|
*/
|
|
135
135
|
public async streamAudioChunks(
|
|
136
136
|
sessionId: string,
|
|
137
|
-
audioChunks:
|
|
137
|
+
audioChunks: string[],
|
|
138
138
|
options: AudioStreamingOptions = {}
|
|
139
139
|
): Promise<void> {
|
|
140
140
|
if (!this.socket?.connected) {
|
|
141
141
|
throw new Error('WebSocket not connected. Cannot stream audio chunks.');
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
const chunks = audioChunks;
|
|
145
144
|
const delay = options.bufferSize || 100; // ms between chunks
|
|
146
145
|
|
|
147
|
-
for (let i = 0; i <
|
|
148
|
-
const isLastChunk = i ===
|
|
146
|
+
for (let i = 0; i < audioChunks.length; i++) {
|
|
147
|
+
const isLastChunk = i === audioChunks.length - 1;
|
|
149
148
|
|
|
150
|
-
this.streamAudioChunk(sessionId,
|
|
149
|
+
this.streamAudioChunk(sessionId, audioChunks[i], isLastChunk);
|
|
151
150
|
|
|
152
151
|
// Small delay between chunks to prevent overwhelming the server
|
|
153
152
|
if (!isLastChunk) {
|