UNPKG

sherpa-onnx-node

Version:

Speech-to-text, text-to-speech, speaker diarization, and speech enhancement using Next-gen Kaldi without internet connection

117 lines (100 loc) 3.17 kB
/** @typedef {import('./types').OfflineTtsConfig} OfflineTtsConfig */ /** @typedef {import('./types').OfflineTtsHandle} OfflineTtsHandle */ /** @typedef {import('./types').TtsRequest} TtsRequest */ /** @typedef {import('./types').GeneratedAudio} GeneratedAudio */ const addon = require('./addon.js'); /** * Internal symbol to mark async-created TTS instances. */ const kFromAsyncFactory = Symbol('OfflineTts.fromAsync'); class GenerationConfig { constructor(opts = {}) { Object.assign(this, opts); } } class OfflineTts { /** * Constructor (sync path). * * Users call: * new OfflineTts(config) * * Async factory calls this with an internal descriptor. * * @param {OfflineTtsConfig|Object} configOrInternal */ constructor(configOrInternal) { if (configOrInternal && typeof configOrInternal === 'object' && configOrInternal[kFromAsyncFactory]) { // ----- async factory path ----- this.handle = configOrInternal.handle; this.config = configOrInternal.config; } else { // ----- sync constructor path ----- this.config = configOrInternal; this.handle = addon.createOfflineTts(this.config); } // Common initialization this.numSpeakers = addon.getOfflineTtsNumSpeakers(this.handle); this.sampleRate = addon.getOfflineTtsSampleRate(this.handle); } /** * Create an OfflineTts asynchronously (non-blocking). * @param {OfflineTtsConfig} config * @returns {Promise<OfflineTts>} */ static async createAsync(config) { const handle = await addon.createOfflineTtsAsync(config); return new OfflineTts({ [kFromAsyncFactory]: true, handle, config, }); } /** * Generate audio synchronously. * @param {TtsRequest} obj * @returns {GeneratedAudio} */ generate(obj) { if (!obj || typeof obj !== 'object') { throw new TypeError('generate() expects an object'); } // If generationConfig is present, use new API if (obj.generationConfig !== undefined) { return addon.offlineTtsGenerateWithConfig(this.handle, obj); } // Fallback to legacy path return addon.offlineTtsGenerate(this.handle, obj); } /** * Generate audio asynchronously with optional generationConfig and progress * callback * * The progress callback receives streaming audio chunks. * * @param {TtsRequest & { generationConfig?: GenerationConfig, onProgress?: (info: { * samples: Float32Array, progress: number }) => number | boolean | void * }} obj * @returns {Promise<GeneratedAudio>} */ generateAsync(obj) { const {onProgress, ...rest} = obj; const hasConfig = obj.generationConfig !== undefined; const fn = hasConfig ? addon.offlineTtsGenerateAsyncWithConfig : addon.offlineTtsGenerateAsync; return fn(this.handle, { ...rest, callback: typeof onProgress === 'function' ? (info) => { const ret = onProgress(info); return ret === 0 || ret === false ? 0 : 1; } : undefined, }); } } module.exports = { OfflineTts, GenerationConfig, }