Repository navigation
Read PDFs aloud page by page - #731
Merged
Merged
Conversation
Text-to-speech used each child of the body as one paragraph. A PDF has one wrapper below the body, so the whole document was one paragraph. The glyph layer and the selection layer both contain the text, so the text was there twice. The engine rejects text longer than getMaxSpeechInputLength(), and it reports the rejection as a completed utterance, so the status went directly to "Finished". - Read the selection layer of each PDF page. Join the textContent of its lines, because a page off screen skips rendering and has no innerText. - Split text longer than the engine limit at sentence boundaries. - Give each paragraph its own utterance id, and clear the expected id before stop(). Before this change, stop() reported a completion, so "next" and "previous" moved one paragraph too far. Fixes #725 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ubFaJuyao9gkUwxwcXZQz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #725.
Problem
Text-to-speech uses each child of
document.bodyas one paragraph. A PDF from the core has one wrapperdiv.dbelow the body. So the whole PDF was one paragraph. The aria-hidden glyph layer (.vis) and the selection layer (.sel) both contain the text, soinnerTexthad the text twice.The engine rejects text longer than
TextToSpeech.getMaxSpeechInputLength()(4000 characters). The deprecatedOnUtteranceCompletedListenergets the rejection as a completion. Then TTS skipped the remaining<script>children, and the status went directly to "Finished". Onmainwith a 9-page PDF, the engine logsText too long: 53672 chars.Changes
PageView.getParagraph: if the page has.p > .sel, read one selection layer for each page. Join thetextContentof its lines.innerTextdoes not work here, because the core gives pagescontent-visibility:auto, and pages off screen have an emptyinnerText. Other formats still usedocument.body.childNodes.TtsActionModeCallback.paragraph: split text longer than the engine limit. The split is at a sentence boundary (BreakIteratorwith the document locale), else at a space, else at the limit.silence()clears the expected ID beforestop(), becausestop()also reports a completion. Before this change, "next" and "previous" moved one paragraph too far.Tests
On the Pixel_6_Pro emulator (Pro debug build). A DevTools wrapper around
window.paragraphListenerlogged the text that TTS received:Casio_WVA-M650-7AJF.pdf(9 pages), playText too long.about.odtspotlessCheck,testProDebugUnitTest,lintProDebug, andlintLiteDebugpass. I did not runconnectedAndroidTestlocally.🤖 Generated with Claude Code