Detect word boundary only in speech marks

This commit is contained in:
Hongbo Wu 2022-10-05 16:50:16 +08:00
parent 174afe0085
commit d279790e81

View file

@ -1,10 +1,8 @@
import {
CancellationDetails,
CancellationReason,
PropertyId,
ResultReason,
SpeechConfig,
SpeechSynthesisBoundaryType,
SpeechSynthesisOutputFormat,
SpeechSynthesisResult,
SpeechSynthesizer,
@ -32,7 +30,7 @@ export interface SpeechMark {
start?: number
length?: number
word: string
type: 'word' | 'bookmark' | 'punctuation' | 'sentence'
type: 'word' | 'bookmark'
}
export const synthesizeTextToSpeech = async (
@ -49,17 +47,11 @@ export const synthesizeTextToSpeech = async (
)
speechConfig.speechSynthesisOutputFormat =
SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3
// Required for sentence-level WordBoundary events
speechConfig.setProperty(
PropertyId.SpeechServiceResponse_RequestSentenceBoundary,
'true'
)
// Create the speech synthesizer.
const synthesizer = new SpeechSynthesizer(speechConfig)
const speechMarks: SpeechMark[] = []
let timeOffset = 0
// let wordOffset = 0
synthesizer.synthesizing = function (s, e) {
// convert arrayBuffer to stream and write to stream
@ -94,14 +86,13 @@ export const synthesizeTextToSpeech = async (
// The unit of e.audioOffset is tick (1 tick = 100 nanoseconds), divide by 10,000 to convert to milliseconds.
synthesizer.wordBoundary = (s, e) => {
e.boundaryType === SpeechSynthesisBoundaryType.Sentence &&
speechMarks.push({
word: e.text,
time: (timeOffset + e.audioOffset) / 10000,
start: e.textOffset,
length: e.text.length,
type: 'sentence',
})
speechMarks.push({
word: e.text,
time: (timeOffset + e.audioOffset) / 10000,
start: e.textOffset,
length: e.text.length,
type: 'word',
})
}
synthesizer.bookmarkReached = (s, e) => {
@ -150,8 +141,6 @@ export const synthesizeTextToSpeech = async (
const startSsmlTag = startSsml(ssmlOptions)
const text = _.escape(input.text)
const ssml = `${startSsmlTag}${text}${endSsml()}`
// set the text offset to be the end of SSML start tag
// wordOffset -= startSsmlTag.length
const result = await speakSsmlAsyncPromise(ssml)
if (result.reason === ResultReason.Canceled) {
throw new Error(result.errorDetails)