UNPKG

whisper.rn

Version:

React Native binding of whisper.cpp

181 lines (161 loc) 5.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WavFileWriter = void 0; var _common = require("./common"); class WavFileWriter { dataSize = 0; isWriting = false; writeQueue = []; constructor(fs, filePath, config) { this.fs = fs; this.filePath = filePath; this.config = config; } /** * Initialize the WAV file with headers */ async initialize() { if (this.isWriting) { return; } try { // Create the initial WAV header (we'll update the size later) const header = this.createWavHeader(0); await this.fs.writeFile(this.filePath, (0, _common.uint8ArrayToBase64)(header), 'base64'); this.dataSize = 0; this.isWriting = true; this.writeQueue = []; } catch (error) { throw new Error(`Failed to initialize WAV file: ${error}`); } } /** * Append PCM audio data to the WAV file */ async appendAudioData(audioData) { if (!this.isWriting) { throw new Error('WAV file not initialized'); } try { // Queue the data for writing this.writeQueue.push(audioData); // Process the write queue await this.processWriteQueue(); } catch (error) { console.warn(`Failed to append audio data to WAV file: ${error}`); } } /** * Process the write queue to avoid blocking */ async processWriteQueue() { if (this.writeQueue.length === 0) { return; } try { // Combine all queued data const totalLength = this.writeQueue.reduce((sum, data) => sum + data.length, 0); const combinedData = new Uint8Array(totalLength); let offset = 0; this.writeQueue.forEach(data => { combinedData.set(new Uint8Array(data), offset); offset += data.length; }); // Append to file const base64Data = (0, _common.uint8ArrayToBase64)(combinedData); await this.fs.appendFile(this.filePath, base64Data, 'base64'); // Update data size this.dataSize += combinedData.length; // Clear the queue this.writeQueue = []; } catch (error) { console.warn(`Failed to process WAV write queue: ${error}`); // Don't throw here to avoid breaking the recording } } /** * Finalize the WAV file by updating the header with correct sizes */ async finalize() { if (!this.isWriting) { return; } try { // Process any remaining queued data await this.processWriteQueue(); // Read the current file const currentData = await this.fs.readFile(this.filePath, 'base64'); const currentBytes = (0, _common.base64ToUint8Array)(currentData); // Create the correct header with final data size const correctHeader = this.createWavHeader(this.dataSize); // Replace the header (first 44 bytes) const finalData = new Uint8Array(correctHeader.length + this.dataSize); finalData.set(correctHeader, 0); finalData.set(currentBytes.slice(44), 44); // Skip old header // Write the final file const finalBase64 = (0, _common.uint8ArrayToBase64)(finalData); await this.fs.writeFile(this.filePath, finalBase64, 'base64'); this.isWriting = false; } catch (error) { console.warn(`Failed to finalize WAV file: ${error}`); } } /** * Create WAV file header */ createWavHeader(dataSize) { const header = new ArrayBuffer(44); const view = new DataView(header); // RIFF header view.setUint32(0, 0x52494646, false); // "RIFF" view.setUint32(4, 36 + dataSize, true); // File size - 8 view.setUint32(8, 0x57415645, false); // "WAVE" // Format chunk view.setUint32(12, 0x666d7420, false); // "fmt " view.setUint32(16, 16, true); // Chunk size view.setUint16(20, 1, true); // Audio format (PCM) view.setUint16(22, this.config.channels, true); // Number of channels view.setUint32(24, this.config.sampleRate, true); // Sample rate view.setUint32(28, this.config.sampleRate * this.config.channels * (this.config.bitsPerSample / 8), true); // Byte rate view.setUint16(32, this.config.channels * (this.config.bitsPerSample / 8), true); // Block align view.setUint16(34, this.config.bitsPerSample, true); // Bits per sample // Data chunk view.setUint32(36, 0x64617461, false); // "data" view.setUint32(40, dataSize, true); // Data size return new Uint8Array(header); } /** * Cancel writing and cleanup */ async cancel() { this.isWriting = false; this.writeQueue = []; try { // Delete the incomplete file const exists = await this.fs.exists(this.filePath); if (exists) { await this.fs.unlink(this.filePath); } } catch (error) { console.warn(`Failed to cleanup WAV file: ${error}`); } } /** * Get current file statistics */ getStatistics() { const durationSec = this.dataSize / (this.config.sampleRate * this.config.channels * (this.config.bitsPerSample / 8)); return { filePath: this.filePath, dataSize: this.dataSize, durationSec, isWriting: this.isWriting, queuedChunks: this.writeQueue.length, estimatedFileSizeMB: (44 + this.dataSize) / (1024 * 1024) }; } } exports.WavFileWriter = WavFileWriter; //# sourceMappingURL=WavFileWriter.js.map