Skip to content

Support sentence-accurate TTS seeking with HTML DOM ranges - #845

Open
Zellius wants to merge 1 commit into
readium:developfrom
Zellius:feat/tts-dom-range-sentence-seek
Open

Zellius wants to merge 1 commit into
readium:developfrom
Zellius:feat/tts-dom-range-sentence-seek

Conversation

@Zellius

@Zellius Zellius commented Oct 23, 2026

Copy link
Copy Markdown

Summary

Currently, TtsNavigator.go(locator) starts playback at the containing text element, even when the locator identifies a specific sentence using locations.domRange.start.

This PR adds sentence-accurate seeking to the existing TTS navigator. When a valid HTML DOM range is provided, playback starts at the sentence containing the specified DOM position.

The same behavior applies to initialLocator when creating a TTS navigator.

Use case

I want to start TTS from a specific sentence within a paragraph, rather than always starting from the beginning of that paragraph.

For example, consider a paragraph containing:

First sentence. Second sentence. Third sentence.

When the reader taps a word in "Second sentence.", I want to pass a locator representing that DOM position to TtsNavigator.go(locator) and have TTS start reading "Second sentence.", skipping the preceding sentence.

This is useful for tap-to-speak interactions in EPUB readers, where users expect playback to begin at the text they selected or tapped.

The locator's locations.domRange.start provides the precise DOM position, allowing the existing TTS navigator to determine the corresponding sentence.

Implementation

  • Add an internal Publication extension that resolves domRange.start to a normalized character offset within the containing HTML block, using Jsoup.
  • Use the start point's CSS selector, direct-child textNodeIndex, and UTF-16 charOffset to preserve the original DOM position.
  • Map the resolved offset to the appropriate utterance using the existing Readium text tokenizer, including content split across inline elements and <br>.
  • Update the utterance cursor and player context to preserve sentence selection during seeking, including while playback is paused.
  • Preserve ordinary navigation for locators without a DOM range and provide fallback behavior for invalid or stale DOM positions.
  • Add a short usage note to the TTS documentation.

The additional DOM parsing is necessary because Readium's Content API exposes extracted text and element locators, but not the original DOM text-node coordinates.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant