fix: filter punctuation and whitespace only utterance out

This commit is contained in:
Hongbo Wu 2024-04-30 14:33:10 +08:00
parent 1a3697e24b
commit 76c1cd5330

View file

@ -5,6 +5,7 @@ import {
SentenceTokenizerNew,
WordPunctTokenizer,
} from 'natural'
import { isElement } from 'underscore'
// this code needs to be kept in sync with the
// frontend code in: useReadingProgressAnchor
@ -49,6 +50,7 @@ const DEFAULT_LANGUAGE = 'en-US'
const DEFAULT_VOICE = 'en-US-JennyNeural'
const DEFAULT_SECONDARY_VOICE = 'en-US-GuyNeural'
const DEFAULT_RATE = '1.1'
const ELEMENT_INDEX_ATTRIBUTE = 'data-omnivore-anchor-idx'
const ANCHOR_ELEMENTS_BLOCKED_ATTRIBUTES = [
'omnivore-highlight-id',
@ -84,6 +86,9 @@ const SKIP_TAGS = [
'CODE',
]
const getAnchorIndex = (element: Element): number =>
Number(element.getAttribute(ELEMENT_INDEX_ATTRIBUTE))
function parseDomTree(pageNode: Element) {
if (!pageNode || pageNode.childNodes.length == 0) {
console.log('no child nodes found')
@ -118,7 +123,7 @@ function parseDomTree(pageNode: Element) {
visitedNodeList.forEach((node, index) => {
// We start at index 3, because the frontend starts two nodes above us
// on the #readability-page-1 element that wraps the entire content.
node.setAttribute('data-omnivore-anchor-idx', (index + 3).toString())
node.setAttribute(ELEMENT_INDEX_ATTRIBUTE, (index + 3).toString())
})
return visitedNodeList
}
@ -157,7 +162,7 @@ function emitElement(
isTopLevel: boolean
) {
const topLevelTags = ssmlTagsForTopLevelElement()
const idx = element.getAttribute('data-omnivore-anchor-idx')
const idx = getAnchorIndex(element)
let maxVisitedIdx = Number(idx)
if (isTopLevel) {
@ -166,6 +171,11 @@ function emitElement(
for (const child of Array.from(element.childNodes)) {
if (SKIP_TAGS.indexOf(child.nodeName) >= 0) {
// Skip unwanted tags and update the index
if (isElement(child)) {
const childIdx = getAnchorIndex(child)
maxVisitedIdx = Math.max(maxVisitedIdx, childIdx)
}
continue
}
@ -180,8 +190,8 @@ function emitElement(
}
emitTextNode(textItems, cleanedText, child)
}
if (child.nodeType == 1 /* Node.ELEMENT_NODE */) {
maxVisitedIdx = emitElement(textItems, child as HTMLElement, false)
if (isElement(child)) {
maxVisitedIdx = emitElement(textItems, child, false)
if (child.nodeName === 'LI') {
// add a new line after each list item
emit(textItems, '\n')
@ -265,6 +275,11 @@ export const stripEmojis = (text: string): string => {
return text.replace(emojiRegex, '').replace(/\s+/g, ' ')
}
const filterUtterances = (utterances: Utterance[]): Utterance[] => {
const punctuationOrSpaceOnly = /^[\s.,;:!?]+$/
return utterances.filter((u) => !punctuationOrSpaceOnly.test(u.text))
}
const textToUtterances = ({
wordTokenizer,
idx,
@ -309,7 +324,10 @@ const textToUtterances = ({
const sentenceTokenizer = new SentenceTokenizerNew()
sentences = sentenceTokenizer.tokenize(text)
} catch (err) {
console.debug('Unable to tokenize sentences')
console.log(
'Unable to tokenize sentences, falling back to old tokenizer',
text
)
// fallback to old sentence tokenizer
const sentenceTokenizer = new SentenceTokenizer()
sentences = sentenceTokenizer.tokenize(text)
@ -371,15 +389,13 @@ const replaceSmartQuotes = (text: string): string => {
// get the max idx of the element and its children
const getMaxVisitedIdx = (element: Element): number => {
let maxVisitedIdx = Number(element.getAttribute('data-omnivore-anchor-idx'))
let maxVisitedIdx = getAnchorIndex(element)
for (const child of Array.from(element.childNodes)) {
if (child.nodeType === 1) {
maxVisitedIdx = Math.max(
maxVisitedIdx,
getMaxVisitedIdx(child as Element)
)
if (isElement(child)) {
maxVisitedIdx = Math.max(maxVisitedIdx, getMaxVisitedIdx(child))
}
}
return maxVisitedIdx
}
@ -461,10 +477,12 @@ export const htmlToSpeechFile = (htmlInput: HtmlInput): SpeechFile => {
}
}
const filteredUtterances = filterUtterances(utterances)
return {
wordCount: wordOffset,
language,
defaultVoice,
utterances,
utterances: filteredUtterances,
}
}