Init view TTS with text segmentation granularity (#47)

in order to support more TTS backends

This PR also fixes a potential off-by-one error at the end boundary of the segment using `sentence` granularity.
This commit is contained in:
Huang Xin
2025-02-13 07:52:03 +00:00
committed by GitHub
parent 34b9079a1b
commit 27f8b57d05
2 changed files with 6 additions and 6 deletions
+4 -4
View File
@@ -34,10 +34,10 @@ const getSegmenter = (lang = 'en', granularity = 'word') => {
while (sum <= index) sum += strs[++strIndex].length while (sum <= index) sum += strs[++strIndex].length
const startIndex = strIndex const startIndex = strIndex
const startOffset = index - (sum - strs[strIndex].length) const startOffset = index - (sum - strs[strIndex].length)
const end = index + segment.length const end = index + segment.length - 1
if (end < str.length) while (sum <= end) sum += strs[++strIndex].length if (end < str.length) while (sum <= end) sum += strs[++strIndex].length
const endIndex = strIndex const endIndex = strIndex
const endOffset = end - (sum - strs[strIndex].length) const endOffset = end - (sum - strs[strIndex].length) + 1
yield [(name++).toString(), yield [(name++).toString(),
makeRange(startIndex, startOffset, endIndex, endOffset)] makeRange(startIndex, startOffset, endIndex, endOffset)]
} }
@@ -207,11 +207,11 @@ export class TTS {
#ranges #ranges
#lastMark #lastMark
#serializer = new XMLSerializer() #serializer = new XMLSerializer()
constructor(doc, textWalker, highlight) { constructor(doc, textWalker, highlight, granularity) {
this.doc = doc this.doc = doc
this.highlight = highlight this.highlight = highlight
this.#list = new ListIterator(getBlocks(doc), range => { this.#list = new ListIterator(getBlocks(doc), range => {
const { entries, ssml } = getFragmentWithMarks(range, textWalker) const { entries, ssml } = getFragmentWithMarks(range, textWalker, granularity)
this.#ranges = new Map(entries) this.#ranges = new Map(entries)
return [ssml, range] return [ssml, range]
}) })
+2 -2
View File
@@ -577,12 +577,12 @@ export class View extends HTMLElement {
for (const item of list) this.deleteAnnotation(item) for (const item of list) this.deleteAnnotation(item)
this.#searchResults.clear() this.#searchResults.clear()
} }
async initTTS() { async initTTS(granularity = 'word') {
const doc = this.renderer.getContents()[0].doc const doc = this.renderer.getContents()[0].doc
if (this.tts && this.tts.doc === doc) return if (this.tts && this.tts.doc === doc) return
const { TTS } = await import('./tts.js') const { TTS } = await import('./tts.js')
this.tts = new TTS(doc, textWalker, range => this.tts = new TTS(doc, textWalker, range =>
this.renderer.scrollToAnchor(range, true)) this.renderer.scrollToAnchor(range, true), granularity)
} }
startMediaOverlay() { startMediaOverlay() {
const { index } = this.renderer.getContents()[0] const { index } = this.renderer.getContents()[0]