echogarden 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/lexicons/heteronyms.en.json +1 -1
- package/data/lexicons/words.en.json +88 -0
- package/dist/alignment/SemanticTextAlignment.js +2 -2
- package/dist/alignment/SemanticTextAlignment.js.map +1 -1
- package/dist/api/Alignment.js +2 -2
- package/dist/api/Alignment.js.map +1 -1
- package/dist/nlp/Segmentation.d.ts +2 -8
- package/dist/nlp/Segmentation.d.ts.map +1 -1
- package/dist/nlp/Segmentation.js +39 -19
- package/dist/nlp/Segmentation.js.map +1 -1
- package/dist/nlp/TextNormalizer.d.ts.map +1 -1
- package/dist/nlp/TextNormalizer.js +22 -14
- package/dist/nlp/TextNormalizer.js.map +1 -1
- package/dist/recognition/AmazonTranscribeSTT.js +3 -3
- package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
- package/dist/synthesis/EspeakTTS.d.ts.map +1 -1
- package/dist/synthesis/EspeakTTS.js +14 -7
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/synthesis/KokoroTTS.d.ts.map +1 -1
- package/dist/synthesis/KokoroTTS.js +0 -5
- package/dist/synthesis/KokoroTTS.js.map +1 -1
- package/dist/synthesis/VitsTTS.d.ts.map +1 -1
- package/dist/synthesis/VitsTTS.js +0 -5
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/utilities/Timeline.js +2 -2
- package/dist/utilities/Timeline.js.map +1 -1
- package/dist/utilities/WikipediaReader.js +5 -5
- package/dist/utilities/WikipediaReader.js.map +1 -1
- package/package.json +12 -12
- package/src/alignment/SemanticTextAlignment.ts +2 -2
- package/src/api/Alignment.ts +2 -2
- package/src/nlp/Segmentation.ts +49 -19
- package/src/nlp/TextNormalizer.ts +29 -16
- package/src/recognition/AmazonTranscribeSTT.ts +3 -3
- package/src/synthesis/EspeakTTS.ts +16 -8
- package/src/synthesis/KokoroTTS.ts +0 -6
- package/src/synthesis/VitsTTS.ts +0 -6
- package/src/utilities/Timeline.ts +2 -2
- package/src/utilities/WikipediaReader.ts +5 -5
package/src/api/Alignment.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { type WhisperAlignmentOptions } from '../recognition/WhisperSTT.js'
|
|
|
14
14
|
import { DtwGranularity, createAlignmentReferenceUsingEspeak } from '../alignment/SpeechAlignment.js'
|
|
15
15
|
import { type SubtitlesConfig } from '../subtitles/Subtitles.js'
|
|
16
16
|
import { type EspeakOptions, defaultEspeakOptions } from '../synthesis/EspeakTTS.js'
|
|
17
|
-
import {
|
|
17
|
+
import { includesWordCharacter } from '../nlp/Segmentation.js'
|
|
18
18
|
|
|
19
19
|
const log = logToStderr
|
|
20
20
|
|
|
@@ -264,7 +264,7 @@ export async function align(input: AudioSourceParam, transcript: string, options
|
|
|
264
264
|
logger.log('')
|
|
265
265
|
|
|
266
266
|
// Remove non-word entries from recognition timeline
|
|
267
|
-
recognitionTimeline = recognitionTimeline.filter(entry =>
|
|
267
|
+
recognitionTimeline = recognitionTimeline.filter(entry => includesWordCharacter(entry.text))
|
|
268
268
|
|
|
269
269
|
// Synthesize the ground-truth transcript and get its timeline
|
|
270
270
|
logger.start('Synthesize ground-truth transcript with eSpeak')
|
package/src/nlp/Segmentation.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { sumArray, logToStderr } from '../utilities/Utilities.js'
|
|
2
2
|
import { getShortLanguageCode } from '../utilities/Locale.js'
|
|
3
3
|
import { ParagraphBreakType, WhitespaceProcessing } from '../api/Common.js'
|
|
4
|
-
import {
|
|
4
|
+
import { splitAndPreserveSeparators } from '../utilities/StringUtilities.js'
|
|
5
|
+
import { anyOf, buildRegExp, unicodeProperty, oneOrMore, possibly, codepoint, inputStart, inputEnd, whitespace } from 'regexp-composer'
|
|
5
6
|
|
|
6
7
|
import * as TextSegmentation from '@echogarden/text-segmentation'
|
|
7
8
|
import { splitChineseTextToWords_Jieba } from './ChineseSegmentation.js'
|
|
@@ -9,50 +10,77 @@ import { splitJapaneseTextToWords_Kuromoji } from './JapaneseSegmentation.js'
|
|
|
9
10
|
|
|
10
11
|
const log = logToStderr
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
const includesWordCharacterPattern = anyOf(unicodeProperty('Letter'), unicodeProperty('Number'))
|
|
14
|
+
const includesWordCharacterRegExp = buildRegExp(includesWordCharacterPattern)
|
|
13
15
|
|
|
14
16
|
// See: https://mathiasbynens.be/notes/es-unicode-property-escapes
|
|
15
|
-
export const emojiSequenceRegExp = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/u
|
|
17
|
+
//export const emojiSequenceRegExp = /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/u
|
|
18
|
+
const includesEmojiSequencePattern = anyOf(
|
|
19
|
+
[unicodeProperty('Emoji_Modifier_Base'), possibly(unicodeProperty('Emoji_Modifier'))],
|
|
20
|
+
unicodeProperty('Emoji_Presentation'),
|
|
21
|
+
[unicodeProperty('Emoji'), codepoint('FE0F')]
|
|
22
|
+
)
|
|
23
|
+
const includesEmojiSequenceRegExp = buildRegExp(includesEmojiSequencePattern)
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
const symbolWordsList = ['$', '€', '¢', '£', '¥', '©', '®', '™', '%', '&', '#', '~', '@', '+', '±', '÷', '/', '\\', '^', '*', '×', '=', '≈', '¼', '½', '¾', '→', '≤', '≥']
|
|
26
|
+
const includesSymbolWordPattern = anyOf(...symbolWordsList)
|
|
27
|
+
const includesSymbolWordRegExp = buildRegExp(includesSymbolWordPattern)
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
const isAllSymbolWordsPattern = [inputStart, oneOrMore(includesSymbolWordPattern), inputEnd]
|
|
30
|
+
const isAllSymbolWordsRegExp = buildRegExp(isAllSymbolWordsPattern)
|
|
31
|
+
|
|
32
|
+
const includesWordCharacterOrEmojiPattern = anyOf(includesWordCharacterPattern, includesEmojiSequencePattern)
|
|
33
|
+
const includesWordCharacterOrEmojiRegExp = buildRegExp(includesWordCharacterOrEmojiPattern)
|
|
34
|
+
|
|
35
|
+
const includesWordCharacterOrEmojiOrIsAllSymbolWordPattern = anyOf(includesWordCharacterPattern, includesEmojiSequencePattern, isAllSymbolWordsPattern)
|
|
36
|
+
const includesWordCharacterOrEmojiOrIsAllSymbolWordRegExp = buildRegExp(includesWordCharacterOrEmojiOrIsAllSymbolWordPattern)
|
|
37
|
+
|
|
38
|
+
const includesPunctuationPattern = unicodeProperty('Punctuation')
|
|
39
|
+
const includesPunctuationRegExp = buildRegExp(includesPunctuationPattern)
|
|
40
|
+
|
|
41
|
+
const isAllPunctuationPattern = [inputStart, oneOrMore(includesPunctuationPattern), inputEnd]
|
|
42
|
+
const isAllPunctuationRegExp = buildRegExp(isAllPunctuationPattern)
|
|
43
|
+
|
|
44
|
+
const phraseSeparatorsList = [',', '、', ',', '،', ';', ';', ':', ':', '—']
|
|
45
|
+
const includesPhraseSeparatorsPattern = anyOf(...phraseSeparatorsList)
|
|
46
|
+
const includesPhraseSeparatorsRegExp = buildRegExp(includesPhraseSeparatorsPattern)
|
|
47
|
+
|
|
48
|
+
const isAllWhitespacePattern = [inputStart, oneOrMore(whitespace), inputEnd]
|
|
49
|
+
const isAllWhitespaceRegExp = buildRegExp(isAllWhitespacePattern)
|
|
22
50
|
|
|
23
51
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
24
52
|
// Predicates
|
|
25
53
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
26
54
|
export function isWordOrEmojiOrSymbolWord(str: string) {
|
|
27
|
-
return
|
|
55
|
+
return includesWordCharacterOrEmojiOrIsAllSymbolWordRegExp.test(str.trim())
|
|
28
56
|
}
|
|
29
57
|
|
|
30
58
|
export function isWordOrEmoji(str: string) {
|
|
31
|
-
return
|
|
59
|
+
return includesWordCharacterOrEmojiRegExp.test(str.trim())
|
|
32
60
|
}
|
|
33
61
|
|
|
34
62
|
export function isSymbolWord(str: string) {
|
|
35
|
-
return
|
|
63
|
+
return isAllSymbolWordsRegExp.test(str.trim())
|
|
36
64
|
}
|
|
37
65
|
|
|
38
|
-
export function
|
|
39
|
-
return
|
|
66
|
+
export function includesWordCharacter(str: string) {
|
|
67
|
+
return includesWordCharacterRegExp.test(str.trim())
|
|
40
68
|
}
|
|
41
69
|
|
|
42
70
|
export function includesPunctuation(str: string) {
|
|
43
|
-
return includesPunctuationRegExp.test(str
|
|
71
|
+
return includesPunctuationRegExp.test(str.trim())
|
|
44
72
|
}
|
|
45
73
|
|
|
46
74
|
export function isAllPunctuation(str: string) {
|
|
47
|
-
return isAllPunctuationRegExp.test(str
|
|
75
|
+
return isAllPunctuationRegExp.test(str.trim())
|
|
48
76
|
}
|
|
49
77
|
|
|
50
78
|
export function includesEmoji(str: string) {
|
|
51
|
-
return
|
|
79
|
+
return includesEmojiSequenceRegExp.test(str.trim())
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
export function isAllWhitespace(str: string) {
|
|
55
|
-
return
|
|
83
|
+
return isAllWhitespaceRegExp.test(str)
|
|
56
84
|
}
|
|
57
85
|
|
|
58
86
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -280,11 +308,13 @@ export class Word {
|
|
|
280
308
|
this.isSentenceFinalizer = isSentenceFinalizer
|
|
281
309
|
}
|
|
282
310
|
|
|
283
|
-
get containsOnlyPunctuation() { return !
|
|
311
|
+
get containsOnlyPunctuation() { return !isWordOrEmojiOrSymbolWord(this.text) }
|
|
284
312
|
|
|
285
|
-
get isSymbolWord() { return
|
|
313
|
+
get isSymbolWord() { return isSymbolWord(this.text) }
|
|
286
314
|
|
|
287
|
-
get isPhraseSeperator() {
|
|
315
|
+
get isPhraseSeperator() {
|
|
316
|
+
return this.containsOnlyPunctuation && includesPhraseSeparatorsRegExp.test(this.text)
|
|
317
|
+
}
|
|
288
318
|
|
|
289
319
|
get length() { return this.text.length }
|
|
290
320
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getShortLanguageCode } from '../utilities/Locale.js'
|
|
2
2
|
import { substituteCharactersUsingLookup } from '../utilities/StringUtilities.js'
|
|
3
|
-
import { anyOf, buildRegExp, charRange, inputEnd, inputStart, repeated, zeroOrMore } from 'regexp-composer'
|
|
3
|
+
import { anyOf, buildRegExp, charRange, inputEnd, inputStart, oneOrMore, repeated, unicodeProperty, zeroOrMore } from 'regexp-composer'
|
|
4
4
|
|
|
5
5
|
export function getNormalizedFragmentsForSpeech(
|
|
6
6
|
words: string[],
|
|
@@ -25,14 +25,24 @@ export function getNormalizedFragmentsForSpeech(
|
|
|
25
25
|
const nextNonWhitespaceWord = nextNonWhitespaceWords[0]
|
|
26
26
|
|
|
27
27
|
const originalWordIndex = nonWhitespaceWordOriginalIndex[wordIndex]
|
|
28
|
+
|
|
28
29
|
const isFollowedByWhitespace = words[originalWordIndex + 1]?.trim().length === 0
|
|
30
|
+
const isSpecialCharacterBeforeYear = ['(', ',', '©'].includes(words[originalWordIndex])
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
//const isWordPrecedingAYear = wordsPrecedingAYear.includes(lowerCaseWord)
|
|
33
|
+
const isWordPrecedingAYear =
|
|
34
|
+
isAllLettersRegExp.test(lowerCaseWord) || isSpecialCharacterBeforeYear
|
|
35
|
+
|
|
36
|
+
const followedByFourDigitYearPattern = fourDigitYearRegExp.test(nextNonWhitespaceWord)
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
const isWordPrecedingADecade = wordsPrecedingADecade.includes(lowerCaseWord)
|
|
39
|
+
const followedByFourDigitDecadePattern = fourDigitDecadeRegExp.test(nextNonWhitespaceWord)
|
|
35
40
|
|
|
41
|
+
if (isWordPrecedingAYear &&
|
|
42
|
+
(isFollowedByWhitespace || isSpecialCharacterBeforeYear) &&
|
|
43
|
+
followedByFourDigitYearPattern) {
|
|
44
|
+
|
|
45
|
+
// Normalize a four digit year pattern, e.g. 'in 1995'.
|
|
36
46
|
const normalizedString = normalizeFourDigitYearString(nextNonWhitespaceWord)
|
|
37
47
|
|
|
38
48
|
normalizedFragments.push(word)
|
|
@@ -43,11 +53,11 @@ export function getNormalizedFragmentsForSpeech(
|
|
|
43
53
|
|
|
44
54
|
wordIndex += 1
|
|
45
55
|
} else if (
|
|
46
|
-
|
|
56
|
+
isWordPrecedingADecade &&
|
|
47
57
|
isFollowedByWhitespace &&
|
|
48
|
-
|
|
58
|
+
followedByFourDigitDecadePattern) {
|
|
49
59
|
|
|
50
|
-
|
|
60
|
+
// Normalize a four digit decade pattern, e.g. 'the 1980s'.
|
|
51
61
|
|
|
52
62
|
const normalizedString = normalizeFourDigitDecadeString(nextNonWhitespaceWord)
|
|
53
63
|
|
|
@@ -58,7 +68,7 @@ export function getNormalizedFragmentsForSpeech(
|
|
|
58
68
|
referenceFragments.push(nextNonWhitespaceWord)
|
|
59
69
|
|
|
60
70
|
wordIndex += 1
|
|
61
|
-
} else if (
|
|
71
|
+
} else if (fourDigitYearRangeRegExp.test(words.slice(originalWordIndex, originalWordIndex + 3).join(''))) {
|
|
62
72
|
// Normalize a year range pattern, e.g. '1835-1896', ensure there are no spaces between words
|
|
63
73
|
normalizedFragments.push(normalizeFourDigitYearString(nonWhitespaceWords[wordIndex]))
|
|
64
74
|
referenceFragments.push(nonWhitespaceWords[wordIndex])
|
|
@@ -92,7 +102,7 @@ export function getNormalizedFragmentsForSpeech(
|
|
|
92
102
|
const referenceString = word
|
|
93
103
|
referenceFragments.push(referenceString)
|
|
94
104
|
}
|
|
95
|
-
} else if (
|
|
105
|
+
} else if (followingCurrencyRegExp.test(lowerCaseWord)) {
|
|
96
106
|
const currencyWord = currencySymbolsAsWords[currencySymbols.indexOf(lowerCaseWord[lowerCaseWord.length - 1])]
|
|
97
107
|
|
|
98
108
|
const normalizedString = `${word.substring(0, word.length - 1)} ${currencyWord}`
|
|
@@ -234,14 +244,14 @@ const wordsFollowingACurrency = [
|
|
|
234
244
|
|
|
235
245
|
const arabicNumeralPattern = charRange('0', '9')
|
|
236
246
|
|
|
237
|
-
const
|
|
247
|
+
const isNumberPattern = [
|
|
238
248
|
inputStart,
|
|
239
249
|
arabicNumeralPattern,
|
|
240
250
|
zeroOrMore(anyOf(arabicNumeralPattern, ',', '.')),
|
|
241
251
|
inputEnd
|
|
242
252
|
]
|
|
243
253
|
|
|
244
|
-
const
|
|
254
|
+
const isNumberRegExp = buildRegExp(isNumberPattern)
|
|
245
255
|
|
|
246
256
|
const precedingCurrencyPattern = [
|
|
247
257
|
inputStart,
|
|
@@ -261,13 +271,16 @@ const followingCurrencyPattern = [
|
|
|
261
271
|
inputEnd
|
|
262
272
|
]
|
|
263
273
|
|
|
264
|
-
const
|
|
274
|
+
const followingCurrencyRegExp = buildRegExp(followingCurrencyPattern)
|
|
265
275
|
|
|
266
276
|
const fourDigitYearPattern = [inputStart, repeated(4, arabicNumeralPattern), inputEnd]
|
|
267
|
-
const
|
|
277
|
+
const fourDigitYearRegExp = buildRegExp(fourDigitYearPattern)
|
|
268
278
|
|
|
269
279
|
const fourDigitDecadePattern = [inputStart, repeated(3, arabicNumeralPattern), '0s', inputEnd]
|
|
270
|
-
const
|
|
280
|
+
const fourDigitDecadeRegExp = buildRegExp(fourDigitDecadePattern)
|
|
271
281
|
|
|
272
282
|
const fourDigitYearRangePattern = [inputStart, repeated(4, arabicNumeralPattern), anyOf('-', '–'), repeated(4, arabicNumeralPattern), inputEnd]
|
|
273
|
-
const
|
|
283
|
+
const fourDigitYearRangeRegExp = buildRegExp(fourDigitYearRangePattern)
|
|
284
|
+
|
|
285
|
+
const isAllLettersPattern = [inputStart, oneOrMore(unicodeProperty('Letter')), inputEnd]
|
|
286
|
+
const isAllLettersRegExp = buildRegExp(isAllLettersPattern)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Item, LanguageCode, StartStreamTranscriptionCommandInput } from '@aws-sdk/client-transcribe-streaming'
|
|
2
|
-
import { wordCharacterRegExp } from '../nlp/Segmentation.js'
|
|
3
1
|
import * as FFMpegTranscoder from '../codecs/FFMpegTranscoder.js'
|
|
2
|
+
import { Item, LanguageCode, StartStreamTranscriptionCommandInput } from '@aws-sdk/client-transcribe-streaming'
|
|
3
|
+
import { isWordOrEmojiOrSymbolWord } from '../nlp/Segmentation.js'
|
|
4
4
|
import { Logger } from '../utilities/Logger.js'
|
|
5
5
|
import { Timeline } from '../utilities/Timeline.js'
|
|
6
6
|
import { RawAudio } from '../audio/AudioUtilities.js'
|
|
@@ -103,7 +103,7 @@ export async function recgonize(rawAudio: RawAudio, languageCode: string, region
|
|
|
103
103
|
for (const event of events) {
|
|
104
104
|
const text = event.Content!
|
|
105
105
|
|
|
106
|
-
if (!
|
|
106
|
+
if (!isWordOrEmojiOrSymbolWord(text)) {
|
|
107
107
|
continue
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -4,7 +4,7 @@ import { Logger } from '../utilities/Logger.js'
|
|
|
4
4
|
import { RawAudio, getEmptyRawAudio } from '../audio/AudioUtilities.js'
|
|
5
5
|
import { getNormalizedFragmentsForSpeech, simplifyPunctuationCharacters } from '../nlp/TextNormalizer.js'
|
|
6
6
|
import { ipaPhoneToKirshenbaum } from '../nlp/PhoneConversion.js'
|
|
7
|
-
import { isAllPunctuation,
|
|
7
|
+
import { isAllPunctuation, isWordOrEmoji, splitToWords, isWordOrEmojiOrSymbolWord } from '../nlp/Segmentation.js'
|
|
8
8
|
import { Lexicon, tryGetFirstLexiconSubstitution } from '../nlp/Lexicon.js'
|
|
9
9
|
import { phonemizeSentence } from '../nlp/EspeakPhonemizer.js'
|
|
10
10
|
import { Timeline, TimelineEntry } from '../utilities/Timeline.js'
|
|
@@ -12,7 +12,7 @@ import { extendDeep } from '../utilities/ObjectUtilities.js'
|
|
|
12
12
|
import { escapeHtml } from '../encodings/HtmlEscape.js'
|
|
13
13
|
import * as TextSegmentation from '@echogarden/text-segmentation'
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { OperationCallbacks, SynthesisCallbacks } from '../api/API.js'
|
|
16
16
|
import { loadPackage } from '../utilities/PackageManager.js'
|
|
17
17
|
|
|
18
18
|
import { wrapEmscriptenModuleHeap } from 'wasm-heap-manager'
|
|
@@ -73,11 +73,14 @@ export async function preprocessAndSynthesize(text: string, language: string, es
|
|
|
73
73
|
for (let i = 0; i < mergedWords.length; i++) {
|
|
74
74
|
const mergedWord = mergedWords[i]
|
|
75
75
|
|
|
76
|
-
// Convert isolated groups of vertical bars and em dashes to a comma
|
|
77
76
|
if (/^[\|│—─–]+$/.test(mergedWord)) {
|
|
77
|
+
// Convert isolated groups of vertical bars or em dashes to a comma
|
|
78
78
|
mergedWords[i] = ','
|
|
79
|
-
} else if (isAllPunctuation(mergedWord)) {
|
|
80
|
-
|
|
79
|
+
} else if (isAllPunctuation(mergedWord)) {
|
|
80
|
+
// Collapse repeated punctuation to up to 3 repetitions,
|
|
81
|
+
// Since otherwise eSpeak may go crazy.
|
|
82
|
+
|
|
83
|
+
mergedWords[i] = mergedWord.substring(0, Math.min(3, mergedWord.length))
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
|
|
@@ -102,7 +105,12 @@ export async function preprocessAndSynthesize(text: string, language: string, es
|
|
|
102
105
|
|
|
103
106
|
const { normalizedFragments, referenceFragments } = getNormalizedFragmentsForSpeech(words, nonWhitespaceWords, nonWhitespaceWordsOriginalIndex, language)
|
|
104
107
|
|
|
105
|
-
const simplifiedFragments = normalizedFragments.map(word =>
|
|
108
|
+
const simplifiedFragments = normalizedFragments.map(word => {
|
|
109
|
+
return simplifyPunctuationCharacters(word)
|
|
110
|
+
.toLocaleLowerCase()
|
|
111
|
+
.replaceAll('(', ',')
|
|
112
|
+
.replaceAll(')', ',')
|
|
113
|
+
})
|
|
106
114
|
|
|
107
115
|
if ([`'`].includes(simplifiedFragments[0])) {
|
|
108
116
|
normalizedFragments[0] = `()`
|
|
@@ -150,8 +158,8 @@ export async function preprocessAndSynthesize(text: string, language: string, es
|
|
|
150
158
|
{
|
|
151
159
|
const fragmentWordSequence = new TextSegmentation.WordSequence()
|
|
152
160
|
|
|
153
|
-
for (let fragment of
|
|
154
|
-
fragmentWordSequence.addWord(fragment, 0, !
|
|
161
|
+
for (let fragment of simplifiedFragments) {
|
|
162
|
+
fragmentWordSequence.addWord(fragment, 0, !isWordOrEmojiOrSymbolWord(fragment))
|
|
155
163
|
}
|
|
156
164
|
|
|
157
165
|
const wordEntries = referenceTimeline.flatMap(phraseEntry => phraseEntry.timeline!)
|
|
@@ -72,12 +72,6 @@ export class KokoroTTS {
|
|
|
72
72
|
const voicePrimaryLanguage = voice.languages[0]
|
|
73
73
|
const voicePrimaryLanguageShort = getShortLanguageCode(voicePrimaryLanguage)
|
|
74
74
|
|
|
75
|
-
sentenceText = //simplifyPunctuationCharacters(sentence.trim())
|
|
76
|
-
sentenceText
|
|
77
|
-
.replaceAll('(', ', ')
|
|
78
|
-
.replaceAll(')', ', ')
|
|
79
|
-
.replaceAll('—', ', ')
|
|
80
|
-
|
|
81
75
|
const simplifiedSentenceText = simplifyPunctuationCharacters(sentenceText.trim())
|
|
82
76
|
|
|
83
77
|
const voiceLanguage = voiceEntry.languages[0]
|
package/src/synthesis/VitsTTS.ts
CHANGED
|
@@ -72,12 +72,6 @@ export class VitsTTS {
|
|
|
72
72
|
|
|
73
73
|
lengthScale *= baseLengthScale
|
|
74
74
|
|
|
75
|
-
sentence = //simplifyPunctuationCharacters(sentence.trim())
|
|
76
|
-
sentence
|
|
77
|
-
.replaceAll('(', ', ')
|
|
78
|
-
.replaceAll(')', ', ')
|
|
79
|
-
.replaceAll('—', ', ')
|
|
80
|
-
|
|
81
75
|
const Espeak = await import('../synthesis/EspeakTTS.js')
|
|
82
76
|
|
|
83
77
|
logger.end()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { addMissingPunctuationWordsToWordSequence, segmentWordSequence, WordSequence } from '@echogarden/text-segmentation'
|
|
2
2
|
import { ParagraphBreakType, WhitespaceProcessing } from '../api/Common.js'
|
|
3
|
-
import { applyWhitespaceProcessing,
|
|
3
|
+
import { applyWhitespaceProcessing, includesWordCharacter, isWordOrEmojiOrSymbolWord, splitToParagraphs } from '../nlp/Segmentation.js'
|
|
4
4
|
import { deepClone } from './ObjectUtilities.js'
|
|
5
5
|
import { getUTF32Chars } from './StringUtilities.js'
|
|
6
6
|
import { roundToDigits } from './Utilities.js'
|
|
@@ -213,7 +213,7 @@ function replaceSentenceEndersWithinWordsWithMaskingCharacter(transcript: string
|
|
|
213
213
|
for (const wordEntry of wordTimeline) {
|
|
214
214
|
const wordText = wordEntry.text
|
|
215
215
|
|
|
216
|
-
if (!
|
|
216
|
+
if (!includesWordCharacter(wordText)) {
|
|
217
217
|
continue
|
|
218
218
|
}
|
|
219
219
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { OperationCallbacks } from '../api/Common.js'
|
|
2
|
-
import {
|
|
2
|
+
import { isWordOrEmojiOrSymbolWord, splitToParagraphs } from '../nlp/Segmentation.js'
|
|
3
3
|
|
|
4
4
|
export async function fetchAndParseWikipediaArticle(articleName: string, language: string, callbacks: OperationCallbacks) {
|
|
5
|
-
const { default:
|
|
5
|
+
const { default: wtfWikipedia } = await import('wtf_wikipedia')
|
|
6
6
|
|
|
7
|
-
const document = await
|
|
7
|
+
const document = await wtfWikipedia.fetch(articleName, language)
|
|
8
8
|
|
|
9
9
|
if (!document) {
|
|
10
10
|
throw new Error('Error fetching Wikipedia article')
|
|
@@ -16,7 +16,7 @@ export async function fetchAndParseWikipediaArticle(articleName: string, languag
|
|
|
16
16
|
for (const section of sections) {
|
|
17
17
|
const sectionTitle = section.title()
|
|
18
18
|
|
|
19
|
-
if (
|
|
19
|
+
if (isWordOrEmojiOrSymbolWord(sectionTitle)) {
|
|
20
20
|
sectionsText.push(sectionTitle)
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ export async function fetchAndParseWikipediaArticle(articleName: string, languag
|
|
|
25
25
|
for (const paragraph of sectionParagraphs) {
|
|
26
26
|
const paragraphText = paragraph
|
|
27
27
|
|
|
28
|
-
if (
|
|
28
|
+
if (isWordOrEmojiOrSymbolWord(paragraphText)) {
|
|
29
29
|
sectionsText.push(paragraphText)
|
|
30
30
|
}
|
|
31
31
|
}
|