UNPKG

whisper.rn

Version:

React Native binding of whisper.cpp

233 lines (206 loc) 6.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SliceManager = void 0; class SliceManager { slices = []; currentSliceIndex = 0; transcribeSliceIndex = 0; constructor() { let sliceDurationSec = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30; let maxSlicesInMemory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; let sampleRate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 16000; this.sliceDurationSec = sliceDurationSec; this.maxSlicesInMemory = maxSlicesInMemory; this.sampleRate = sampleRate; } /** * Add audio data to the current slice */ addAudioData(audioData) { // Get or create current slice const currentSlice = this.getCurrentSlice(); // Calculate bytes per slice (2 bytes per sample for 16-bit PCM) const bytesPerSlice = this.sliceDurationSec * this.sampleRate * 2; // Check if adding this data would exceed slice capacity if (currentSlice.sampleCount + audioData.length > bytesPerSlice) { // Finalize current slice and create new one this.finalizeCurrentSlice(); this.currentSliceIndex += 1; return this.addAudioData(audioData); // Recursively add to new slice } // Append data to current slice const newData = new Uint8Array(currentSlice.sampleCount + audioData.length); newData.set(currentSlice.data.subarray(0, currentSlice.sampleCount)); newData.set(audioData, currentSlice.sampleCount); currentSlice.data = newData; currentSlice.sampleCount += audioData.length; currentSlice.endTime = Date.now(); // Check if slice is complete const isSliceComplete = currentSlice.sampleCount >= bytesPerSlice * 0.8; // 80% full if (isSliceComplete) { this.finalizeCurrentSlice(); } return { slice: currentSlice }; } /** * Get the current slice being built */ getCurrentSlice() { let slice = this.slices.find(s => s.index === this.currentSliceIndex); if (!slice) { const bytesPerSlice = this.sliceDurationSec * this.sampleRate * 2; // 2 bytes per sample slice = { index: this.currentSliceIndex, data: new Uint8Array(bytesPerSlice), sampleCount: 0, startTime: Date.now(), endTime: Date.now(), isProcessed: false, isReleased: false }; this.slices.push(slice); // Clean up old slices if we have too many this.cleanupOldSlices(); } return slice; } /** * Finalize the current slice */ finalizeCurrentSlice() { const slice = this.slices.find(s => s.index === this.currentSliceIndex); if (slice && slice.sampleCount > 0) { // Trim the data array to actual size slice.data = slice.data.subarray(0, slice.sampleCount); slice.endTime = Date.now(); } } /** * Get a slice for transcription */ getSliceForTranscription() { const slice = this.slices.find(s => s.index === this.transcribeSliceIndex && !s.isProcessed); if (slice && slice.sampleCount > 0) { return slice; } return null; } /** * Mark a slice as processed */ markSliceAsProcessed(sliceIndex) { const slice = this.slices.find(s => s.index === sliceIndex); if (slice) { slice.isProcessed = true; } } /** * Move to the next slice for transcription */ moveToNextTranscribeSlice() { this.transcribeSliceIndex += 1; } /** * Get audio data for transcription (base64 encoded) */ getAudioDataForTranscription(sliceIndex) { const slice = this.slices.find(s => s.index === sliceIndex); if (!slice || slice.sampleCount === 0) { return null; } return slice.data.subarray(0, slice.sampleCount); } /** * Get a slice by index */ getSliceByIndex(sliceIndex) { return this.slices.find(s => s.index === sliceIndex) || null; } /** * Clean up old slices to manage memory */ cleanupOldSlices() { if (this.slices.length <= this.maxSlicesInMemory) { return; } // Sort slices by index this.slices.sort((a, b) => a.index - b.index); // Keep only the most recent slices const slicesToKeep = this.slices.slice(-this.maxSlicesInMemory); const slicesToRemove = this.slices.slice(0, -this.maxSlicesInMemory); // Release old slices slicesToRemove.forEach(slice => { if (!slice.isReleased) { slice.isReleased = true; // Clear the audio data to free memory slice.data = new Uint8Array(0); } }); this.slices = slicesToKeep; } /** * Get memory usage statistics */ getMemoryUsage() { const activeSlices = this.slices.filter(s => !s.isReleased); const totalBytes = activeSlices.reduce((sum, slice) => sum + slice.sampleCount, 0); // Estimate memory usage (Uint8Array = 1 byte per sample) const estimatedMB = totalBytes / (1024 * 1024); return { slicesInMemory: activeSlices.length, totalSamples: totalBytes / 2, // Convert bytes to samples (2 bytes per sample) estimatedMB: Math.round(estimatedMB * 100) / 100 // Round to 2 decimal places }; } /** * Reset all slices and indices */ reset() { // Release all slices this.slices.forEach(slice => { slice.isReleased = true; // Clear the audio data to free memory slice.data = new Uint8Array(0); }); // Reset state this.slices = []; this.currentSliceIndex = 0; this.transcribeSliceIndex = 0; } /** * Get current slice information */ getCurrentSliceInfo() { return { currentSliceIndex: this.currentSliceIndex, transcribeSliceIndex: this.transcribeSliceIndex, totalSlices: this.slices.length, memoryUsage: this.getMemoryUsage() }; } /** * Force move to the next slice, finalizing the current one regardless of capacity */ forceNextSlice() { const currentSlice = this.slices.find(s => s.index === this.currentSliceIndex); if (currentSlice && currentSlice.sampleCount > 0) { // Finalize current slice this.finalizeCurrentSlice(); // Move to next slice this.currentSliceIndex += 1; return { slice: currentSlice }; } // If no current slice or it's empty, just move to next index this.currentSliceIndex += 1; return {}; } } exports.SliceManager = SliceManager; //# sourceMappingURL=SliceManager.js.map