whisper.rn 0.5.0-rc.0 → 0.5.0-rc.10
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 +128 -50
- package/android/build.gradle +1 -0
- package/android/src/main/CMakeLists.txt +1 -0
- package/android/src/main/java/com/rnwhisper/RNWhisper.java +35 -0
- package/android/src/main/java/com/rnwhisper/WhisperContext.java +33 -0
- package/android/src/main/jni.cpp +81 -0
- package/android/src/newarch/java/com/rnwhisper/RNWhisperModule.java +5 -0
- package/android/src/oldarch/java/com/rnwhisper/RNWhisperModule.java +5 -0
- package/cpp/jsi/RNWhisperJSI.cpp +42 -6
- package/ios/RNWhisper.mm +11 -0
- package/ios/RNWhisperContext.h +1 -0
- package/ios/RNWhisperContext.mm +46 -0
- package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Info.plist +0 -0
- package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Info.plist +0 -0
- package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/_CodeSignature/CodeResources +1 -1
- package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/rnwhisper +0 -0
- package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Info.plist +0 -0
- package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Info.plist +0 -0
- package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/_CodeSignature/CodeResources +1 -1
- package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/rnwhisper +0 -0
- package/lib/commonjs/AudioSessionIos.js +2 -1
- package/lib/commonjs/AudioSessionIos.js.map +1 -1
- package/lib/commonjs/NativeRNWhisper.js.map +1 -1
- package/lib/commonjs/index.js +50 -10
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/jest-mock.js +126 -0
- package/lib/commonjs/jest-mock.js.map +1 -0
- package/lib/commonjs/realtime-transcription/RealtimeTranscriber.js +857 -0
- package/lib/commonjs/realtime-transcription/RealtimeTranscriber.js.map +1 -0
- package/lib/commonjs/realtime-transcription/SliceManager.js +233 -0
- package/lib/commonjs/realtime-transcription/SliceManager.js.map +1 -0
- package/lib/commonjs/realtime-transcription/adapters/AudioPcmStreamAdapter.js +133 -0
- package/lib/commonjs/realtime-transcription/adapters/AudioPcmStreamAdapter.js.map +1 -0
- package/lib/commonjs/realtime-transcription/adapters/JestAudioStreamAdapter.js +201 -0
- package/lib/commonjs/realtime-transcription/adapters/JestAudioStreamAdapter.js.map +1 -0
- package/lib/commonjs/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.js +309 -0
- package/lib/commonjs/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.js.map +1 -0
- package/lib/commonjs/realtime-transcription/index.js +27 -0
- package/lib/commonjs/realtime-transcription/index.js.map +1 -0
- package/lib/commonjs/realtime-transcription/types.js +114 -0
- package/lib/commonjs/realtime-transcription/types.js.map +1 -0
- package/lib/commonjs/utils/WavFileReader.js +158 -0
- package/lib/commonjs/utils/WavFileReader.js.map +1 -0
- package/lib/commonjs/utils/WavFileWriter.js +181 -0
- package/lib/commonjs/utils/WavFileWriter.js.map +1 -0
- package/lib/commonjs/utils/common.js +25 -0
- package/lib/commonjs/utils/common.js.map +1 -0
- package/lib/module/AudioSessionIos.js +2 -1
- package/lib/module/AudioSessionIos.js.map +1 -1
- package/lib/module/NativeRNWhisper.js.map +1 -1
- package/lib/module/index.js +48 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest-mock.js +124 -0
- package/lib/module/jest-mock.js.map +1 -0
- package/lib/module/realtime-transcription/RealtimeTranscriber.js +851 -0
- package/lib/module/realtime-transcription/RealtimeTranscriber.js.map +1 -0
- package/lib/module/realtime-transcription/SliceManager.js +226 -0
- package/lib/module/realtime-transcription/SliceManager.js.map +1 -0
- package/lib/module/realtime-transcription/adapters/AudioPcmStreamAdapter.js +124 -0
- package/lib/module/realtime-transcription/adapters/AudioPcmStreamAdapter.js.map +1 -0
- package/lib/module/realtime-transcription/adapters/JestAudioStreamAdapter.js +194 -0
- package/lib/module/realtime-transcription/adapters/JestAudioStreamAdapter.js.map +1 -0
- package/lib/module/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.js +302 -0
- package/lib/module/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.js.map +1 -0
- package/lib/module/realtime-transcription/index.js +8 -0
- package/lib/module/realtime-transcription/index.js.map +1 -0
- package/lib/module/realtime-transcription/types.js +107 -0
- package/lib/module/realtime-transcription/types.js.map +1 -0
- package/lib/module/utils/WavFileReader.js +151 -0
- package/lib/module/utils/WavFileReader.js.map +1 -0
- package/lib/module/utils/WavFileWriter.js +174 -0
- package/lib/module/utils/WavFileWriter.js.map +1 -0
- package/lib/module/utils/common.js +18 -0
- package/lib/module/utils/common.js.map +1 -0
- package/lib/typescript/AudioSessionIos.d.ts +1 -1
- package/lib/typescript/AudioSessionIos.d.ts.map +1 -1
- package/lib/typescript/NativeRNWhisper.d.ts +1 -0
- package/lib/typescript/NativeRNWhisper.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +8 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/jest-mock.d.ts +2 -0
- package/lib/typescript/jest-mock.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/RealtimeTranscriber.d.ts +166 -0
- package/lib/typescript/realtime-transcription/RealtimeTranscriber.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/SliceManager.d.ts +72 -0
- package/lib/typescript/realtime-transcription/SliceManager.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/adapters/AudioPcmStreamAdapter.d.ts +22 -0
- package/lib/typescript/realtime-transcription/adapters/AudioPcmStreamAdapter.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/adapters/JestAudioStreamAdapter.d.ts +44 -0
- package/lib/typescript/realtime-transcription/adapters/JestAudioStreamAdapter.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.d.ts +75 -0
- package/lib/typescript/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/index.d.ts +6 -0
- package/lib/typescript/realtime-transcription/index.d.ts.map +1 -0
- package/lib/typescript/realtime-transcription/types.d.ts +222 -0
- package/lib/typescript/realtime-transcription/types.d.ts.map +1 -0
- package/lib/typescript/utils/WavFileReader.d.ts +61 -0
- package/lib/typescript/utils/WavFileReader.d.ts.map +1 -0
- package/lib/typescript/utils/WavFileWriter.d.ts +57 -0
- package/lib/typescript/utils/WavFileWriter.d.ts.map +1 -0
- package/lib/typescript/utils/common.d.ts +9 -0
- package/lib/typescript/utils/common.d.ts.map +1 -0
- package/package.json +23 -11
- package/src/AudioSessionIos.ts +3 -2
- package/src/NativeRNWhisper.ts +2 -0
- package/src/index.ts +74 -22
- package/{jest/mock.js → src/jest-mock.ts} +2 -2
- package/src/realtime-transcription/RealtimeTranscriber.ts +1015 -0
- package/src/realtime-transcription/SliceManager.ts +252 -0
- package/src/realtime-transcription/adapters/AudioPcmStreamAdapter.ts +143 -0
- package/src/realtime-transcription/adapters/JestAudioStreamAdapter.ts +251 -0
- package/src/realtime-transcription/adapters/SimulateFileAudioStreamAdapter.ts +378 -0
- package/src/realtime-transcription/index.ts +34 -0
- package/src/realtime-transcription/types.ts +283 -0
- package/src/utils/WavFileReader.ts +202 -0
- package/src/utils/WavFileWriter.ts +206 -0
- package/src/utils/common.ts +17 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { WavFileReader } from '../../utils/WavFileReader';
|
|
2
|
+
export class SimulateFileAudioStreamAdapter {
|
|
3
|
+
config = null;
|
|
4
|
+
isInitialized = false;
|
|
5
|
+
recording = false;
|
|
6
|
+
currentBytePosition = 0;
|
|
7
|
+
startTime = 0;
|
|
8
|
+
pausedTime = 0;
|
|
9
|
+
hasReachedEnd = false;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = {
|
|
12
|
+
playbackSpeed: 1.0,
|
|
13
|
+
chunkDurationMs: 100,
|
|
14
|
+
loop: false,
|
|
15
|
+
logger: () => {},
|
|
16
|
+
...options
|
|
17
|
+
};
|
|
18
|
+
this.fileReader = new WavFileReader(this.options.fs, this.options.filePath);
|
|
19
|
+
}
|
|
20
|
+
async initialize(config) {
|
|
21
|
+
if (this.isInitialized) {
|
|
22
|
+
await this.release();
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
this.config = config;
|
|
26
|
+
|
|
27
|
+
// Initialize the WAV file reader
|
|
28
|
+
await this.fileReader.initialize();
|
|
29
|
+
|
|
30
|
+
// Validate file format matches config
|
|
31
|
+
const header = this.fileReader.getHeader();
|
|
32
|
+
if (!header) {
|
|
33
|
+
throw new Error('Failed to read WAV file header');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Warn about mismatched formats but allow processing
|
|
37
|
+
if (header.sampleRate !== config.sampleRate) {
|
|
38
|
+
this.log(`WAV file sample rate (${header.sampleRate}Hz) differs from config (${config.sampleRate}Hz)`);
|
|
39
|
+
}
|
|
40
|
+
if (header.channels !== config.channels) {
|
|
41
|
+
this.log(`WAV file channels (${header.channels}) differs from config (${config.channels})`);
|
|
42
|
+
}
|
|
43
|
+
if (header.bitsPerSample !== config.bitsPerSample) {
|
|
44
|
+
this.log(`WAV file bits per sample (${header.bitsPerSample}) differs from config (${config.bitsPerSample})`);
|
|
45
|
+
}
|
|
46
|
+
this.isInitialized = true;
|
|
47
|
+
this.log(`Simulate audio stream initialized: ${header.duration.toFixed(2)}s at ${this.options.playbackSpeed}x speed`);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
var _this$errorCallback;
|
|
50
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown initialization error';
|
|
51
|
+
(_this$errorCallback = this.errorCallback) === null || _this$errorCallback === void 0 ? void 0 : _this$errorCallback.call(this, errorMessage);
|
|
52
|
+
throw new Error(`Failed to initialize SimulateFileAudioStreamAdapter: ${errorMessage}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async start() {
|
|
56
|
+
if (!this.isInitialized || !this.config) {
|
|
57
|
+
throw new Error('Adapter not initialized');
|
|
58
|
+
}
|
|
59
|
+
if (this.recording) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
var _this$statusCallback;
|
|
64
|
+
this.recording = true;
|
|
65
|
+
this.hasReachedEnd = false;
|
|
66
|
+
this.startTime = Date.now() - this.pausedTime;
|
|
67
|
+
(_this$statusCallback = this.statusCallback) === null || _this$statusCallback === void 0 ? void 0 : _this$statusCallback.call(this, true);
|
|
68
|
+
|
|
69
|
+
// Start streaming chunks
|
|
70
|
+
this.startStreaming();
|
|
71
|
+
this.log('File audio simulation started');
|
|
72
|
+
} catch (error) {
|
|
73
|
+
var _this$statusCallback2, _this$errorCallback2;
|
|
74
|
+
this.recording = false;
|
|
75
|
+
(_this$statusCallback2 = this.statusCallback) === null || _this$statusCallback2 === void 0 ? void 0 : _this$statusCallback2.call(this, false);
|
|
76
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown start error';
|
|
77
|
+
(_this$errorCallback2 = this.errorCallback) === null || _this$errorCallback2 === void 0 ? void 0 : _this$errorCallback2.call(this, errorMessage);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async stop() {
|
|
82
|
+
if (!this.recording) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
var _this$statusCallback3;
|
|
87
|
+
this.recording = false;
|
|
88
|
+
this.pausedTime = Date.now() - this.startTime;
|
|
89
|
+
|
|
90
|
+
// Stop the streaming interval
|
|
91
|
+
if (this.streamInterval) {
|
|
92
|
+
clearInterval(this.streamInterval);
|
|
93
|
+
this.streamInterval = undefined;
|
|
94
|
+
}
|
|
95
|
+
(_this$statusCallback3 = this.statusCallback) === null || _this$statusCallback3 === void 0 ? void 0 : _this$statusCallback3.call(this, false);
|
|
96
|
+
this.log('File audio simulation stopped');
|
|
97
|
+
} catch (error) {
|
|
98
|
+
var _this$errorCallback3;
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown stop error';
|
|
100
|
+
(_this$errorCallback3 = this.errorCallback) === null || _this$errorCallback3 === void 0 ? void 0 : _this$errorCallback3.call(this, errorMessage);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
isRecording() {
|
|
104
|
+
return this.recording;
|
|
105
|
+
}
|
|
106
|
+
onData(callback) {
|
|
107
|
+
this.dataCallback = callback;
|
|
108
|
+
}
|
|
109
|
+
onError(callback) {
|
|
110
|
+
this.errorCallback = callback;
|
|
111
|
+
}
|
|
112
|
+
onStatusChange(callback) {
|
|
113
|
+
this.statusCallback = callback;
|
|
114
|
+
}
|
|
115
|
+
async release() {
|
|
116
|
+
await this.stop();
|
|
117
|
+
this.isInitialized = false;
|
|
118
|
+
this.currentBytePosition = 0;
|
|
119
|
+
this.pausedTime = 0;
|
|
120
|
+
this.log('SimulateFileAudioStreamAdapter released');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Start the streaming process
|
|
125
|
+
*/
|
|
126
|
+
startStreaming() {
|
|
127
|
+
if (!this.config || !this.isInitialized) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const header = this.fileReader.getHeader();
|
|
131
|
+
if (!header) {
|
|
132
|
+
var _this$errorCallback4;
|
|
133
|
+
(_this$errorCallback4 = this.errorCallback) === null || _this$errorCallback4 === void 0 ? void 0 : _this$errorCallback4.call(this, 'WAV file header not available');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Calculate chunk size based on desired duration
|
|
138
|
+
const chunkDurationSec = (this.options.chunkDurationMs || 100) / 1000;
|
|
139
|
+
const bytesPerSecond = header.sampleRate * header.channels * (header.bitsPerSample / 8);
|
|
140
|
+
const chunkSizeBytes = Math.floor(chunkDurationSec * bytesPerSecond);
|
|
141
|
+
|
|
142
|
+
// Adjust interval timing based on playback speed
|
|
143
|
+
const intervalMs = (this.options.chunkDurationMs || 100) / (this.options.playbackSpeed || 1.0);
|
|
144
|
+
this.streamInterval = setInterval(() => {
|
|
145
|
+
if (!this.recording) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
this.streamNextChunk(chunkSizeBytes);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
var _this$errorCallback5;
|
|
152
|
+
const errorMessage = error instanceof Error ? error.message : 'Streaming error';
|
|
153
|
+
(_this$errorCallback5 = this.errorCallback) === null || _this$errorCallback5 === void 0 ? void 0 : _this$errorCallback5.call(this, errorMessage);
|
|
154
|
+
this.stop();
|
|
155
|
+
}
|
|
156
|
+
}, intervalMs);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Stream the next audio chunk
|
|
161
|
+
*/
|
|
162
|
+
streamNextChunk(chunkSizeBytes) {
|
|
163
|
+
if (!this.dataCallback || !this.config) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const header = this.fileReader.getHeader();
|
|
167
|
+
if (!header) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Get the next chunk of audio data
|
|
172
|
+
const audioChunk = this.fileReader.getAudioSlice(this.currentBytePosition, chunkSizeBytes);
|
|
173
|
+
if (!audioChunk || audioChunk.length === 0) {
|
|
174
|
+
// End of file reached
|
|
175
|
+
if (this.options.loop) {
|
|
176
|
+
// Reset to beginning for looping
|
|
177
|
+
this.currentBytePosition = 0;
|
|
178
|
+
this.startTime = Date.now();
|
|
179
|
+
this.pausedTime = 0;
|
|
180
|
+
this.hasReachedEnd = false;
|
|
181
|
+
this.log('Looping audio file simulation');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Stop streaming due to no new buffer
|
|
186
|
+
this.log('Audio file simulation completed - no new buffer available');
|
|
187
|
+
this.hasReachedEnd = true;
|
|
188
|
+
|
|
189
|
+
// Call the end-of-file callback if provided
|
|
190
|
+
if (this.options.onEndOfFile) {
|
|
191
|
+
this.log('Calling onEndOfFile callback');
|
|
192
|
+
this.options.onEndOfFile();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Stop the stream
|
|
196
|
+
this.stop();
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Update position
|
|
201
|
+
this.currentBytePosition += audioChunk.length;
|
|
202
|
+
|
|
203
|
+
// Create stream data using the original file's format
|
|
204
|
+
const streamData = {
|
|
205
|
+
data: audioChunk,
|
|
206
|
+
sampleRate: header.sampleRate,
|
|
207
|
+
channels: header.channels,
|
|
208
|
+
timestamp: Date.now()
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Send the chunk
|
|
212
|
+
this.dataCallback(streamData);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get current playback statistics
|
|
217
|
+
*/
|
|
218
|
+
getStatistics() {
|
|
219
|
+
const header = this.fileReader.getHeader();
|
|
220
|
+
const currentTime = this.fileReader.byteToTime(this.currentBytePosition);
|
|
221
|
+
return {
|
|
222
|
+
filePath: this.options.filePath,
|
|
223
|
+
isRecording: this.recording,
|
|
224
|
+
currentTime,
|
|
225
|
+
totalDuration: (header === null || header === void 0 ? void 0 : header.duration) || 0,
|
|
226
|
+
progress: header ? currentTime / header.duration : 0,
|
|
227
|
+
playbackSpeed: this.options.playbackSpeed,
|
|
228
|
+
currentBytePosition: this.currentBytePosition,
|
|
229
|
+
totalBytes: this.fileReader.getTotalDataSize(),
|
|
230
|
+
hasReachedEnd: this.hasReachedEnd,
|
|
231
|
+
header
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Seek to a specific time position
|
|
237
|
+
*/
|
|
238
|
+
seekToTime(timeSeconds) {
|
|
239
|
+
const header = this.fileReader.getHeader();
|
|
240
|
+
if (!header) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const clampedTime = Math.max(0, Math.min(timeSeconds, header.duration));
|
|
244
|
+
this.currentBytePosition = this.fileReader.timeToByte(clampedTime);
|
|
245
|
+
|
|
246
|
+
// Reset timing if we're currently playing
|
|
247
|
+
if (this.recording) {
|
|
248
|
+
this.startTime = Date.now() - clampedTime * 1000 / (this.options.playbackSpeed || 1.0);
|
|
249
|
+
this.pausedTime = 0;
|
|
250
|
+
}
|
|
251
|
+
this.log(`Seeked to ${clampedTime.toFixed(2)}s`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Set playback speed
|
|
256
|
+
*/
|
|
257
|
+
setPlaybackSpeed(speed) {
|
|
258
|
+
if (speed <= 0) {
|
|
259
|
+
throw new Error('Playback speed must be greater than 0');
|
|
260
|
+
}
|
|
261
|
+
this.options.playbackSpeed = speed;
|
|
262
|
+
|
|
263
|
+
// If currently playing, restart streaming with new speed
|
|
264
|
+
if (this.recording) {
|
|
265
|
+
this.stop().then(() => {
|
|
266
|
+
this.start();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
this.log(`Playback speed set to ${speed}x`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Reset file buffer to beginning
|
|
274
|
+
*/
|
|
275
|
+
resetBuffer() {
|
|
276
|
+
this.log('Resetting file buffer to beginning');
|
|
277
|
+
|
|
278
|
+
// Reset position and timing
|
|
279
|
+
this.currentBytePosition = 0;
|
|
280
|
+
this.startTime = Date.now();
|
|
281
|
+
this.pausedTime = 0;
|
|
282
|
+
this.hasReachedEnd = false;
|
|
283
|
+
|
|
284
|
+
// If currently playing, restart streaming from beginning
|
|
285
|
+
if (this.recording) {
|
|
286
|
+
this.log('Restarting streaming from beginning');
|
|
287
|
+
// Stop and restart to apply the reset
|
|
288
|
+
this.stop().then(() => {
|
|
289
|
+
this.start();
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Logger function
|
|
296
|
+
*/
|
|
297
|
+
log(message) {
|
|
298
|
+
var _this$options$logger, _this$options;
|
|
299
|
+
(_this$options$logger = (_this$options = this.options).logger) === null || _this$options$logger === void 0 ? void 0 : _this$options$logger.call(_this$options, `[SimulateFileAudioStreamAdapter] ${message}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=SimulateFileAudioStreamAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["WavFileReader","SimulateFileAudioStreamAdapter","config","isInitialized","recording","currentBytePosition","startTime","pausedTime","hasReachedEnd","constructor","options","playbackSpeed","chunkDurationMs","loop","logger","fileReader","fs","filePath","initialize","release","header","getHeader","Error","sampleRate","log","channels","bitsPerSample","duration","toFixed","error","_this$errorCallback","errorMessage","message","errorCallback","call","start","_this$statusCallback","Date","now","statusCallback","startStreaming","_this$statusCallback2","_this$errorCallback2","stop","_this$statusCallback3","streamInterval","clearInterval","undefined","_this$errorCallback3","isRecording","onData","callback","dataCallback","onError","onStatusChange","_this$errorCallback4","chunkDurationSec","bytesPerSecond","chunkSizeBytes","Math","floor","intervalMs","setInterval","streamNextChunk","_this$errorCallback5","audioChunk","getAudioSlice","length","onEndOfFile","streamData","data","timestamp","getStatistics","currentTime","byteToTime","totalDuration","progress","totalBytes","getTotalDataSize","seekToTime","timeSeconds","clampedTime","max","min","timeToByte","setPlaybackSpeed","speed","then","resetBuffer","_this$options$logger","_this$options"],"sourceRoot":"../../../../src","sources":["realtime-transcription/adapters/SimulateFileAudioStreamAdapter.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Main transcriber class
|
|
2
|
+
export { RealtimeTranscriber } from './RealtimeTranscriber';
|
|
3
|
+
|
|
4
|
+
// Slice manager (for advanced use cases)
|
|
5
|
+
export { SliceManager } from './SliceManager';
|
|
6
|
+
// VAD presets constant
|
|
7
|
+
export { VAD_PRESETS } from './types';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["RealtimeTranscriber","SliceManager","VAD_PRESETS"],"sourceRoot":"../../../src","sources":["realtime-transcription/index.ts"],"mappings":"AAAA;AACA,SAASA,mBAAmB,QAAQ,uBAAuB;;AAE3D;AACA,SAASC,YAAY,QAAQ,gBAAgB;AA4B7C;AACA,SAASC,WAAW,QAAQ,SAAS"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// === Audio Stream Interfaces ===
|
|
2
|
+
|
|
3
|
+
// === Enhanced VAD Options ===
|
|
4
|
+
|
|
5
|
+
// Pre-defined VAD configurations for different use cases
|
|
6
|
+
/**
|
|
7
|
+
* VAD Presets Overview:
|
|
8
|
+
*
|
|
9
|
+
* VAD Presets
|
|
10
|
+
* / | \
|
|
11
|
+
* Conservative Default Sensitive
|
|
12
|
+
* / | | \
|
|
13
|
+
* conservative very-conservative sensitive very-sensitive
|
|
14
|
+
* (0.7 thresh) (0.8 thresh) (0.3 thresh) (0.2 thresh)
|
|
15
|
+
* 500ms min 750ms min 100ms min 100ms min
|
|
16
|
+
* Clear speech Very clear Quiet env Catches whispers
|
|
17
|
+
*
|
|
18
|
+
* Specialized Presets
|
|
19
|
+
* / | \
|
|
20
|
+
* continuous meeting noisy
|
|
21
|
+
* (60s max) (45s max) (0.75 thresh)
|
|
22
|
+
* Lectures Multi-spk Strict for noise
|
|
23
|
+
*
|
|
24
|
+
* Key Parameters:
|
|
25
|
+
* - threshold: 0.0-1.0 (lower = more sensitive)
|
|
26
|
+
* - minSpeechDurationMs: Min duration to consider speech
|
|
27
|
+
* - minSilenceDurationMs: Min silence before ending speech
|
|
28
|
+
* - maxSpeechDurationS: Max continuous speech duration
|
|
29
|
+
* - speechPadMs: Padding around detected speech
|
|
30
|
+
* - samplesOverlap: Analysis window overlap (0.0-1.0)
|
|
31
|
+
*/
|
|
32
|
+
export const VAD_PRESETS = {
|
|
33
|
+
// Default - balanced performance
|
|
34
|
+
default: {
|
|
35
|
+
threshold: 0.5,
|
|
36
|
+
minSpeechDurationMs: 250,
|
|
37
|
+
minSilenceDurationMs: 100,
|
|
38
|
+
maxSpeechDurationS: 30,
|
|
39
|
+
speechPadMs: 30,
|
|
40
|
+
samplesOverlap: 0.1
|
|
41
|
+
},
|
|
42
|
+
// Sensitive - good for quiet environments
|
|
43
|
+
sensitive: {
|
|
44
|
+
threshold: 0.3,
|
|
45
|
+
minSpeechDurationMs: 100,
|
|
46
|
+
minSilenceDurationMs: 50,
|
|
47
|
+
maxSpeechDurationS: 15,
|
|
48
|
+
speechPadMs: 50,
|
|
49
|
+
samplesOverlap: 0.2
|
|
50
|
+
},
|
|
51
|
+
// Very sensitive - catches even quiet speech
|
|
52
|
+
'very-sensitive': {
|
|
53
|
+
threshold: 0.2,
|
|
54
|
+
minSpeechDurationMs: 100,
|
|
55
|
+
minSilenceDurationMs: 50,
|
|
56
|
+
maxSpeechDurationS: 15,
|
|
57
|
+
speechPadMs: 100,
|
|
58
|
+
samplesOverlap: 0.3
|
|
59
|
+
},
|
|
60
|
+
// Conservative - avoids false positives
|
|
61
|
+
conservative: {
|
|
62
|
+
threshold: 0.7,
|
|
63
|
+
minSpeechDurationMs: 500,
|
|
64
|
+
minSilenceDurationMs: 200,
|
|
65
|
+
maxSpeechDurationS: 25,
|
|
66
|
+
speechPadMs: 20,
|
|
67
|
+
samplesOverlap: 0.05
|
|
68
|
+
},
|
|
69
|
+
// Very conservative - only clear speech
|
|
70
|
+
'very-conservative': {
|
|
71
|
+
threshold: 0.8,
|
|
72
|
+
minSpeechDurationMs: 750,
|
|
73
|
+
minSilenceDurationMs: 300,
|
|
74
|
+
maxSpeechDurationS: 20,
|
|
75
|
+
speechPadMs: 10,
|
|
76
|
+
samplesOverlap: 0.05
|
|
77
|
+
},
|
|
78
|
+
// Continuous speech - for presentations/lectures
|
|
79
|
+
continuous: {
|
|
80
|
+
threshold: 0.4,
|
|
81
|
+
minSpeechDurationMs: 200,
|
|
82
|
+
minSilenceDurationMs: 300,
|
|
83
|
+
maxSpeechDurationS: 60,
|
|
84
|
+
// Longer segments
|
|
85
|
+
speechPadMs: 50,
|
|
86
|
+
samplesOverlap: 0.15
|
|
87
|
+
},
|
|
88
|
+
// Meeting mode - handles multiple speakers
|
|
89
|
+
meeting: {
|
|
90
|
+
threshold: 0.45,
|
|
91
|
+
minSpeechDurationMs: 300,
|
|
92
|
+
minSilenceDurationMs: 150,
|
|
93
|
+
maxSpeechDurationS: 45,
|
|
94
|
+
speechPadMs: 75,
|
|
95
|
+
samplesOverlap: 0.2
|
|
96
|
+
},
|
|
97
|
+
// Noisy environment - more strict thresholds
|
|
98
|
+
noisy: {
|
|
99
|
+
threshold: 0.75,
|
|
100
|
+
minSpeechDurationMs: 400,
|
|
101
|
+
minSilenceDurationMs: 100,
|
|
102
|
+
maxSpeechDurationS: 25,
|
|
103
|
+
speechPadMs: 40,
|
|
104
|
+
samplesOverlap: 0.1
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["VAD_PRESETS","default","threshold","minSpeechDurationMs","minSilenceDurationMs","maxSpeechDurationS","speechPadMs","samplesOverlap","sensitive","conservative","continuous","meeting","noisy"],"sourceRoot":"../../../src","sources":["realtime-transcription/types.ts"],"mappings":"AAGA;;AA4BA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,WAAW,GAAG;EACzB;EACAC,OAAO,EAAE;IACPC,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACAC,SAAS,EAAE;IACTN,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,EAAE;IACxBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACA,gBAAgB,EAAE;IAChBL,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,EAAE;IACxBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,GAAG;IAChBC,cAAc,EAAE;EAClB,CAAC;EAED;EACAE,YAAY,EAAE;IACZP,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACA,mBAAmB,EAAE;IACnBL,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACAG,UAAU,EAAE;IACVR,SAAS,EAAE,GAAG;IACdC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IAAE;IACxBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACAI,OAAO,EAAE;IACPT,SAAS,EAAE,IAAI;IACfC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB,CAAC;EAED;EACAK,KAAK,EAAE;IACLV,SAAS,EAAE,IAAI;IACfC,mBAAmB,EAAE,GAAG;IACxBC,oBAAoB,EAAE,GAAG;IACzBC,kBAAkB,EAAE,EAAE;IACtBC,WAAW,EAAE,EAAE;IACfC,cAAc,EAAE;EAClB;AACF,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { base64ToUint8Array } from './common';
|
|
2
|
+
export class WavFileReader {
|
|
3
|
+
header = null;
|
|
4
|
+
audioData = null;
|
|
5
|
+
constructor(fs, filePath) {
|
|
6
|
+
this.fs = fs;
|
|
7
|
+
this.filePath = filePath;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Read and parse the WAV file
|
|
12
|
+
*/
|
|
13
|
+
async initialize() {
|
|
14
|
+
try {
|
|
15
|
+
// Check if file exists
|
|
16
|
+
const exists = await this.fs.exists(this.filePath);
|
|
17
|
+
if (!exists) {
|
|
18
|
+
throw new Error(`WAV file not found: ${this.filePath}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Read the entire file
|
|
22
|
+
const fileContent = await this.fs.readFile(this.filePath, 'base64');
|
|
23
|
+
const fileData = base64ToUint8Array(fileContent);
|
|
24
|
+
|
|
25
|
+
// Parse WAV header
|
|
26
|
+
this.header = WavFileReader.parseWavHeader(fileData);
|
|
27
|
+
|
|
28
|
+
// Extract audio data (skip the 44-byte header)
|
|
29
|
+
this.audioData = fileData.slice(44, 44 + this.header.dataSize);
|
|
30
|
+
console.log(`WAV file loaded: ${this.header.duration.toFixed(2)}s, ${this.header.sampleRate}Hz, ${this.header.channels}ch`);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new Error(`Failed to initialize WAV file reader: ${error}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Parse WAV file header
|
|
38
|
+
*/
|
|
39
|
+
static parseWavHeader(data) {
|
|
40
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
41
|
+
|
|
42
|
+
// Verify RIFF header
|
|
43
|
+
const riffHeader = String.fromCharCode(...data.slice(0, 4));
|
|
44
|
+
if (riffHeader !== 'RIFF') {
|
|
45
|
+
throw new Error('Invalid WAV file: Missing RIFF header');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Verify WAVE format
|
|
49
|
+
const waveHeader = String.fromCharCode(...data.slice(8, 12));
|
|
50
|
+
if (waveHeader !== 'WAVE') {
|
|
51
|
+
throw new Error('Invalid WAV file: Missing WAVE header');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Read format chunk
|
|
55
|
+
const fmtHeader = String.fromCharCode(...data.slice(12, 16));
|
|
56
|
+
if (fmtHeader !== 'fmt ') {
|
|
57
|
+
throw new Error('Invalid WAV file: Missing fmt chunk');
|
|
58
|
+
}
|
|
59
|
+
const audioFormat = view.getUint16(20, true);
|
|
60
|
+
if (audioFormat !== 1) {
|
|
61
|
+
throw new Error('Unsupported WAV format: Only PCM is supported');
|
|
62
|
+
}
|
|
63
|
+
const channels = view.getUint16(22, true);
|
|
64
|
+
const sampleRate = view.getUint32(24, true);
|
|
65
|
+
const bitsPerSample = view.getUint16(34, true);
|
|
66
|
+
|
|
67
|
+
// Find data chunk
|
|
68
|
+
let dataOffset = 36;
|
|
69
|
+
while (dataOffset < data.length - 8) {
|
|
70
|
+
const chunkId = String.fromCharCode(...data.slice(dataOffset, dataOffset + 4));
|
|
71
|
+
const chunkSize = view.getUint32(dataOffset + 4, true);
|
|
72
|
+
if (chunkId === 'data') {
|
|
73
|
+
const dataSize = chunkSize;
|
|
74
|
+
const duration = dataSize / (sampleRate * channels * (bitsPerSample / 8));
|
|
75
|
+
return {
|
|
76
|
+
sampleRate,
|
|
77
|
+
channels,
|
|
78
|
+
bitsPerSample,
|
|
79
|
+
dataSize,
|
|
80
|
+
duration
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
dataOffset += 8 + chunkSize;
|
|
84
|
+
}
|
|
85
|
+
throw new Error('Invalid WAV file: Missing data chunk');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get audio data slice
|
|
90
|
+
*/
|
|
91
|
+
getAudioSlice(startByte, lengthBytes) {
|
|
92
|
+
if (!this.audioData) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const start = Math.max(0, startByte);
|
|
96
|
+
const end = Math.min(this.audioData.length, startByte + lengthBytes);
|
|
97
|
+
if (start >= end) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return this.audioData.slice(start, end);
|
|
101
|
+
}
|
|
102
|
+
getAudioData() {
|
|
103
|
+
return this.audioData;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get WAV file header information
|
|
108
|
+
*/
|
|
109
|
+
getHeader() {
|
|
110
|
+
return this.header;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get total audio data size
|
|
115
|
+
*/
|
|
116
|
+
getTotalDataSize() {
|
|
117
|
+
var _this$header;
|
|
118
|
+
return ((_this$header = this.header) === null || _this$header === void 0 ? void 0 : _this$header.dataSize) || 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Convert byte position to time in seconds
|
|
123
|
+
*/
|
|
124
|
+
byteToTime(bytePosition) {
|
|
125
|
+
if (!this.header) return 0;
|
|
126
|
+
const bytesPerSecond = this.header.sampleRate * this.header.channels * (this.header.bitsPerSample / 8);
|
|
127
|
+
return bytePosition / bytesPerSecond;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Convert time in seconds to byte position
|
|
132
|
+
*/
|
|
133
|
+
timeToByte(timeSeconds) {
|
|
134
|
+
if (!this.header) return 0;
|
|
135
|
+
const bytesPerSecond = this.header.sampleRate * this.header.channels * (this.header.bitsPerSample / 8);
|
|
136
|
+
return Math.floor(timeSeconds * bytesPerSecond);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get file statistics
|
|
141
|
+
*/
|
|
142
|
+
getStatistics() {
|
|
143
|
+
return {
|
|
144
|
+
filePath: this.filePath,
|
|
145
|
+
header: this.header,
|
|
146
|
+
totalDataSize: this.getTotalDataSize(),
|
|
147
|
+
isInitialized: !!this.header
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=WavFileReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["base64ToUint8Array","WavFileReader","header","audioData","constructor","fs","filePath","initialize","exists","Error","fileContent","readFile","fileData","parseWavHeader","slice","dataSize","console","log","duration","toFixed","sampleRate","channels","error","data","view","DataView","buffer","byteOffset","byteLength","riffHeader","String","fromCharCode","waveHeader","fmtHeader","audioFormat","getUint16","getUint32","bitsPerSample","dataOffset","length","chunkId","chunkSize","getAudioSlice","startByte","lengthBytes","start","Math","max","end","min","getAudioData","getHeader","getTotalDataSize","_this$header","byteToTime","bytePosition","bytesPerSecond","timeToByte","timeSeconds","floor","getStatistics","totalDataSize","isInitialized"],"sourceRoot":"../../../src","sources":["utils/WavFileReader.ts"],"mappings":"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"}
|