textfold
Fold papers, web pages, files, and AI replies into five levels of detail. Zoom from an overview to the original text.
翻譯準備中
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A voice-first Android keyboard that works alongside Gboard. Voicebar is a one-row bar under the app for talking, moving the cursor and editing; for typing, ABC pops up Voicebar's own full keyboard over the bar (hold it to hand the field to Gboard instead, and a button drawn over Gboard brings you back, already listening).
Download the APK from Releases and open it (allow your browser or file manager to install apps when Android asks). On first launch a setup wizard walks through everything Voicebar needs, one page each, checking each step as you come back from Android's screens:
Required steps have an “I'll do this later”; optional ones can be skipped. Run it again from Settings › How to use it › Run setup again. Updating an app that's already set up skips the wizard.
First-run tips: the first few times the bar opens, a purple bubble above it points at one control at a time: Voice, then (during your first recording) how to finish, then ABC, Cursor and ⌫ on later openings, and after a few dictations the “voice bar” commands. One per opening; using a feature retires its tip, “Got it” moves on, “Skip tips” stops them. Settings › How to use it has Show tips on the bar and Show all tips again.
ABC pops up Voicebar's keyboard: a full QWERTY that takes over the bar's row too, so its bottom row (?123, ⋮, comma, space, period, ↵) is where your thumbs already are. Pull the handle at the top down to put the voice bar back (or flick it). ⋮ opens the bar's menu over the keyboard, which stays up; hold ⋮ for Gboard. Suggestions across the top finish the word you're typing (your own words first, then the 60,000 most common English words). Swipe to type: slide across a word's letters without lifting; the trail follows your finger, the word goes in with a space before it, and the strip offers the other words it might have been. ⌫ right after a swipe deletes the whole word (and the space the swipe put before it), as Gboard does; once you've typed, picked a suggestion or moved the cursor, ⌫ goes back to one letter at a time. It runs FUTO Swipe's open models on the phone with Voicebar's own decoder (Powered by FUTO Swipe), in a few milliseconds and with nothing sent anywhere; a tap puts one in with a space, and punctuation right after takes the space's place. Capitals come at the start of a sentence; tap shift for one, double-tap it for caps lock. Hold a key for its accents (the top row's numbers first) and slide to one; hold ⌫ to keep deleting; slide on space to move the cursor; two spaces type a period; a second thumb types the first thumb's key at once. ?123 and =< have numbers and symbols, and ↵ shows the field's action (send, search, go). On a space it fixes a lone "i" and missing apostrophes ("dont"); ⌫ right after puts back what you typed. Starting to talk puts it away too. In Settings ▸ Bar and Gboard, ABC can swap the two: tap for Gboard, hold for Voicebar's keyboard.
Hold ABC to switch the field to Gboard. The accessibility service Voicebar: way back from Gboard (Android 11+; on 13+ a sideloaded app first needs Allow restricted settings in its App info) draws a way back while Gboard is open, in one of three styles:
Any of them switches back and starts dictation right away. If the service is off, ABC says so first (tap the message to open Accessibility settings, or tap ABC again to switch anyway). The service reads only Gboard's window: its position, its key layout and its background color.
Listen as soon as a text box opens (off by default): dictation starts by itself whenever a text field opens Voicebar (not in password fields).
With a physical keyboard (Bluetooth, USB or a keyboard case): the bar still opens, even though Android normally hides on-screen keyboards then. It starts listening by itself only when the phone is in your hand (half a second of the gyroscope tells a hand's tremor from a phone lying still at a desk); lying still, it says so once ("a keyboard is connected and the phone is lying still") and waits for a tap. Tap Voice, say “voice bar, listen”, or use Gboard's way-back button to dictate.
While you're dictating (or saying what to fix), the screen stays on, so a long dictation isn't cut off by the screen dimming or locking.
When the cleanup fails (a reply that isn't the cleaned text or is far longer than what was said, the service overloaded or rate-limited, a timeout, a dropped connection), Voicebar asks once more before giving up; only a second failure shows the warning. A wrong key or a bad request isn't asked again, and the cleanup at a pause mid-dictation isn't either (the one at the end comes anyway). Fixing the box by voice asks again after a reply that isn't usable. If you swiped to send and the cleanup still fails, the message isn't sent: it's typed as spoken, for a look, and the warning says it wasn't sent.
If Voice is tapped while the app hasn't connected a text box to the keyboard (it happens: the keyboard is up, but there's nothing to type into), Voicebar first asks the app to focus its text box again (the one it was last in, else the focused one, else the lowest on screen) through the accessibility service, waits up to a second for it, then listens into it. A dictation that finishes with no text box gets the same try, for up to 1.5 s, before its words go to the clipboard. Settings ▸ Logs shows each try ("field: …").
Type as you speak (default): the words go straight into the text field as the keyboard's draft and are rewritten in place as the recognizer firms them up; the polished text replaces the draft in one step.
Preview mode (setting off): words stream into the voice pill and are typed when you finish.
claude-haiku-5-5, effort low) while the mic stays open; the cleaned text replaces the raw words in the draft. Keep talking and the next cleanup (another pause, ✓, or the timeout) sends the cleaned text and the new raw words marked apart (<cleaned> / <raw>), so spoken corrections across the pause ("Tuesday… no, Wednesday") still resolve. If nothing was said after the last pause, finishing types the cleaned text with no further request. Any failure or timeout falls back to what's there: cleaned part plus raw words.voice/Transcriber and voice/Cleaner are interfaces; another provider is one class each.Settings (open the app) use Material 3 with your wallpaper colors: setup steps (turn on Voicebar, switch to it, turn on Gboard, turn on the way back) until everything is ready, then Bar and Gboard, Voice typing, Text and language, a short guide and a text box to try it in.
./gradlew testDebugUnitTest -Prender renders the bar's states, the color schemes and the settings pages into app/build/previews/, for checking the look without a phone.
Icons: gear and cancel from Material Symbols (Apache 2.0); the keyboard-switch glyph is AOSP's ic_ime_switcher (Apache 2.0).
Settings → Voice typing → Estimated cost shows what dictation cost over the past 24 hours, 7 days and 30 days, split into Scribe and Claude. Voicebar counts what it actually sent: the seconds of audio streamed to Scribe v2 Realtime (priced at $0.39 per hour), and the input and output tokens Claude reports back in each cleanup reply (priced per model at list rates; Haiku 5.5 is $0.10 / $0.50 per million). The counts are kept on the phone in hourly buckets for 31 days; no text or audio is stored. It's an estimate at list prices: plan allowances, free hours and credits aren't taken into account, so the providers' dashboards are the real bill. A model with no known price has its tokens counted but not priced.
Say “voice bar, hands free” (while the bar or the Gboard button is up, or anywhere with Listen for it everywhere on), or use the Hands-free Quick Settings tile, and control the phone by voice. It runs in the accessibility service, which reads every app's screen and acts on it with real taps and gestures (canPerformGestures).
commit_strategy=vad). The pill in the status bar (left of the camera) shows what it heard and what it's doing; tap it, or say “stop”, to end. It turns off after 5 minutes without a command, or when the screen goes off.Cost while on: ElevenLabs streaming (about $0.39 an hour) plus a fraction of a cent per Claude-planned command. Settings → Voice typing → Hands-free.
Settings › Voice typing › Speech recognition chooses where speech becomes text: ElevenLabs Scribe (cloud, live words, your key) or Parakeet on this phone: NVIDIA's Parakeet Unified 0.6B (April 2026, English, with punctuation and capitals), run by sherpa-onnx with no network and no key. The model (663 MB) downloads once, resumably, from a pinned Hugging Face revision of the sherpa-onnx export, and is checked against known sizes and SHA-256 sums; Remove frees the space. The setup wizard offers it as an alternative to an ElevenLabs key.
Parakeet Unified's true streaming exports re-run a context window per chunk and measured slower than real time even on an M1 Max, so Voicebar uses the regular model with on-device voice detection (Silero VAD, bundled): each stretch of speech is read once at the pause and committed, and between pauses the stretch so far is re-read about every 0.8 s (less often on slower phones) so words still show while you talk. On an M1 Max that whole loop costs about a tenth of real time. Hands-free mode uses it the same way, one command per utterance. The model loads when the keyboard opens (if chosen) and is let go after three idle minutes. Cleanup still uses Claude when you add a key; keyterms and screen context for recognition are ElevenLabs-only.
When dictation starts with text already in the field, the cleanup gets the text either side of the cursor (up to 1,000 characters before, 400 after; never from password fields) as <before> and <after>, and is told to return only the new words, fitted to that spot: no capital mid-sentence, no closing period when the sentence carries on after the cursor, the surrounding style kept, and the whole sentence used to pick the right sound-alike. A reply that echoes the field anyway has that part taken back off. The words just before the cursor also go to ElevenLabs as the lead-in for recognition (read from the field itself, so this works with screen context off), and when the new words land against a word after the cursor, a space goes between them.
Settings › Voice typing › Other voices › Ignore children's voices silences a small child talking between your words, with nothing to set up and no model to download. A young child's voice sits more than an octave above an adult man's (roughly 250–400 Hz against 85–155 Hz), so pitch alone tells them apart. Audio goes through a short-time Fourier transform on the phone (64 ms frames every 16 ms). Each frame's pitch is the lowest one whose harmonics stand out over the troughs between them, checked against being an adult's bright 2nd–6th harmonic, judged over the last few frames, and required to glide the way a voice does. A stretch that's only a child (no adult heard in the last ~130 ms) is replaced with silence, held ~220 ms past the child's last voiced sound for the consonants. About 50 ms of delay; it runs before Only my voice when both are on.
How high counts as a child sets the line from 260 Hz (Gentle) down to 190 Hz (Strict); stronger catches older children but may cut adults with high voices. When a child talks over you at the same moment, the audio can't be pulled apart this way, so cleanup is also told to drop words that are plainly a child cutting in.
Tested with synthetic voices (macOS's Daniel as the adult; Samantha raised to a child's pitch and vocal-tract size) through Parakeet: a child talking alone or between the adult's sentences went from 28–29 transcribed words to none, the adult's sentences were transcribed the same as unfiltered, and overlapping speech was unchanged.
Settings › Voice typing › Other voices › Only my voice keeps other people out of your dictation and hands-free commands: someone talking between your sentences, a TV, a conversation nearby. It needs a speaker model, 3D-Speaker ERes2Net (26 MB, downloaded when you turn it on, pinned and SHA-256-checked like Parakeet), and works one of two ways:
While you dictate, audio goes through in half-second blocks. Each block with speech in it (Silero VAD) is compared with your voiceprint using the last second of speech; a block that doesn't sound like you is replaced with silence before ElevenLabs or Parakeet hears it. That adds about half a second, plus up to another half second at the start of speech while there's enough to judge. A pause of half a second starts the judging afresh, so a new speaker isn't judged by your last words, and a word too short to judge ("yes") is let through. Strength (Gentle to Strict) sets how closely speech must match: stronger silences more of other voices but may drop some of yours in noise or when you whisper. Check it, on the voiceprint page, shows a live match meter against the current strength. Voices speaking at the very same moment as you can't be separated this way. The voiceprint is a list of numbers kept in app storage; nothing about it leaves the phone. The wake word isn't filtered.
On a test with seven synthetic voices, ERes2Net separated the enrolled voice from every other at one-second windows with no errors, at about 28 ms per window on an M1 Max; CAM++ models were twice as fast but confused voices 13–25% of the time.
When dictation starts, Voicebar reads the text on screen once: the app you're typing into, such as the chat you're replying to. It reads every app window (split screen too) through the Gboard companion's accessibility service, but never keyboards, the status bar or password fields; without the companion, only the text box itself is read. The reading happens in the background while you start talking, and your first words wait for it (at most 0.4 s).
It's used three ways:
previous_text context with the first audio.Turn it off in Settings → Voice typing → Use what's on screen.
When you hand-fix a word Voicebar typed (a name it misheard, a product, an acronym), Voicebar notices the edit, in its own bar or in Gboard through the accessibility service, for up to 15 minutes, until the text is sent or you leave the field. Only short swaps that sound alike pass a local filter (rewording, numbers and unrelated edits are skipped); Claude then judges each one and replies whether it's a new word, a mishearing to replace, both, or nothing. Accepted ones go into Settings → Dictionary with a "Learned … · tap to undo" note on the bar. You can also add words yourself, with what they're often heard as.
The dictionary is used three ways: the 50 most used terms go to ElevenLabs as keyterms (optional, extra cost); the whole list goes into the cleanup prompt; and a mishearing you added yourself, or that was learned twice, is replaced outright. It's stored on the phone only, and password fields are never read.
How you write a word. Change only a word's capitals by hand (LOL to lol, iphone to iPhone) and Voicebar counts it, with no model involved; the second time, that word is always written your way, wherever it comes up and whatever the cleanup did, with a note you can tap to undo. A first letter alone (The to the) isn't counted: that's where the word fell in a sentence. Adding a word yourself in capitals a sentence wouldn't give it (lol, iPhone, YODA) does the same at once; a plain capitalized word (Will) doesn't, so it can't turn every "will" into a name. These entries say Always written like this in Settings ▸ Dictionary, where removing one ends it. The cleanup prompt doesn't change: it's a last step on the text, so it costs nothing and can't make the cleanup worse.
./gradlew assembleRelease # app/build/outputs/apk/release/app-release.apk
./gradlew testDebugUnitTest # Robolectric tests: the bar, dictation flow, protocol against fake servers
Release builds are signed with the permanent key in ~/Code/BubbleKeyboard-signing/ on Ryder's Mac (not in the repo); add bk.signingDir=<that folder> to local.properties. Without it the build falls back to the machine's debug key, and that APK won't install over one signed with the real key.
Needs JDK 17+ and the Android SDK (platform 37). minSdk 26.
The internal app ID stays com.ryderdavid.bubblekeyboard (and the service classes keep their names) so Voicebar installs over Bubble Keyboard with its settings, keys and enabled services intact.
. , ? ! ' " : ; - … / @, then ( ) # & * $ % + = _ ~ ^, then < > [ ] { } | \ ` ° • §), and under them space, Pixel-style dots for the page, ↵ and ⌫ (hold it to keep deleting). Swipe the rows sideways for the next page, or tap a dot. A mark with a dot offers more when held: ’ ‘, “ ”, – —, € £ ¥ ¢; slide to one and let go. The palette stays up while you tap marks and closes when you tap anywhere outside it, or its key again; that tap only closes it and never reaches the app or the bar. A mark that closes up to a word (. , ? ! : ; … and closing brackets and quotes) right after the space a dictation left takes that space's place and keeps it after itself, so "see you there " and ! give "see you there! ".