diff --git a/packages/text-to-speech/src/index.ts b/packages/text-to-speech/src/index.ts index fc0e630dd..d5329b11e 100644 --- a/packages/text-to-speech/src/index.ts +++ b/packages/text-to-speech/src/index.ts @@ -10,7 +10,7 @@ import * as dotenv from 'dotenv' // see https://github.com/motdotla/dotenv#how-d import { synthesizeTextToSpeech, TextToSpeechInput } from './textToSpeech' import { File, Storage } from '@google-cloud/storage' import { PassThrough } from 'stream' -import * as fs from 'fs' +import { SSMLItem } from './htmlToSsml' dotenv.config() Sentry.GCPFunction.init({ @@ -140,12 +140,14 @@ export const textToSpeechStreamingHandler = Sentry.GCPFunction.wrapHttpFunction( } try { - const ssml = fs.readFileSync('./data/ssml.xml', 'utf8') + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const ssmlItems = req.body.ssmlItems as SSMLItem[] const audioStream = new PassThrough() const input: TextToSpeechInput = { - text: ssml, + text: '', textType: 'ssml', audioStream, + ssmlItems, } res.set({ 'Content-Type': 'audio/mpeg', diff --git a/packages/text-to-speech/src/textToSpeech.ts b/packages/text-to-speech/src/textToSpeech.ts index a79ee42c0..2217fe1a1 100644 --- a/packages/text-to-speech/src/textToSpeech.ts +++ b/packages/text-to-speech/src/textToSpeech.ts @@ -7,7 +7,7 @@ import { SpeechSynthesisResult, SpeechSynthesizer, } from 'microsoft-cognitiveservices-speech-sdk' -import { htmlToSsml, ssmlItemText } from './htmlToSsml' +import { htmlToSsml, SSMLItem, ssmlItemText } from './htmlToSsml' export interface TextToSpeechInput { id?: string @@ -20,6 +20,7 @@ export interface TextToSpeechInput { complimentaryVoice?: string bucket?: string audioStream: NodeJS.ReadWriteStream + ssmlItems?: SSMLItem[] } export interface TextToSpeechOutput { @@ -131,23 +132,24 @@ export const synthesizeTextToSpeech = async ( } try { - if (textType === 'html') { - const ssmlItems = htmlToSsml(input.text, { - primaryVoice: input.voice || 'en-US-JennyNeural', - secondaryVoice: input.complimentaryVoice || 'en-US-GuyNeural', - language: input.languageCode || 'en-US', - rate: '1', - }) + const ssmlItems = + input.textType === 'ssml' + ? input.ssmlItems + : htmlToSsml(input.text, { + primaryVoice: input.voice || 'en-US-JennyNeural', + secondaryVoice: input.complimentaryVoice || 'en-US-GuyNeural', + language: input.languageCode || 'en-US', + rate: '1', + }) + if (!ssmlItems || ssmlItems.length === 0) { + throw new Error('No SSML items found') + } - for (const ssmlItem of Array.from(ssmlItems)) { - const ssml = ssmlItemText(ssmlItem) - console.debug('start synthesizing', ssml) - const result = await speakSsmlAsyncPromise(ssml) - timeOffset = timeOffset + result.audioDuration - } - } else { - console.debug('start synthesizing', input.text) - await speakSsmlAsyncPromise(input.text) + for (const ssmlItem of Array.from(ssmlItems)) { + const ssml = ssmlItemText(ssmlItem) + console.debug('start synthesizing', ssml) + const result = await speakSsmlAsyncPromise(ssml) + timeOffset = timeOffset + result.audioDuration } } catch (error) { console.error('synthesis error', error)