Turn text into deterministic, BB-8-style droid speech, right from your terminal.
Status: VOICE_V12 noun/verb recognizability is active.
VOICE_V12gives content words a learnable grammatical signature: nouns open with a broadband click/pop and settle, verbs open with an up-swept chirp and push, both as a compoundstem → resolutionsilhouette driven by a baked, pinned word-class table (no runtime tagger, no tensor runtime). Unclassified words render exactly asVOICE_V11's natural voice. EarlierVOICE_V*contracts remain historical lock points, and any sample-affecting change still requires a new voice identifier plus regenerated golden WAV fixtures. macOS release automation is committed; the first tagged release will publish Homebrew and prebuilt installer artifacts. See the roadmap and packaging notes.
dootdoot reads text and emits short bursts of warbly droid chatter. It's a small,
learnable sound language with three defining properties:
- Deterministic. The same text always produces the same audio, bit-for-bit, on every platform.
- Semantic. Text with similar meaning sounds similar, so you can learn to "hear" words.
- Droid by design. However you phrase the input, the output is unmistakably the same character.
Try the real VOICE_V12 renderer in your browser,
powered by the same Rust core compiled to WebAssembly.
Homebrew (recommended on macOS, available after the first tagged release):
brew install skeswa/tap/dootdoot
brew upgrade dootdootInstaller script (macOS fallback without Homebrew, available after the first tagged release):
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/skeswa/dootdoot/releases/latest/download/dootdoot-installer.sh | sh
dootdoot-updateFrom source (requires the Rust toolchain):
git clone https://github.com/skeswa/dootdoot
cd dootdoot
cargo build --release
# binary at ./target/release/dootdootLocal Cargo install from a checkout:
cargo install --path dootdoot --lockeddootdoot "hello there" # synthesize and play it
dootdoot "hello there" -o out.wav # render to a WAV file (no playback)
dootdoot "hello there" -o out.wav --play # do both
echo "piped text" | dootdoot # read from stdin
dootdoot "curious?" --explain # print the per-token sound breakdown--explain writes a full account of the sound profile to stderr so it never pollutes file
output or shell pipelines. It is an inspection mode, so it does not play audio (pass
--play if you also want to hear it). It reports every channel that affects the rendered
samples: the utterance-level mood and complexity; per voiced token the four learnable
knobs, the discourse role, and the gesture archetype; the planner's continuous
performance curves; and the glide/pause each control marker imposes:
mood valence:+0.325 arousal:+0.357
complexity scalar:+0.192 subtokens:0 chars:8
token │ pitch │ vowel │ contour │ warble │ role │ archetype
curious │ -0.660 │ +0.058 │ -0.390 │ +0.762 │ terminal-flourish │ yelp
? │ control:question · rising glide · pause 240 ms
curves │ p.bias │ p.vel │ f.tgt │ f.vel │ bright │ mouth │ tens │ gap
curious │ +0.350 │ +0.550 │ +0.300 │ +0.350 │ 0.550 │ 0.550 │ 0.600 │ -
The four knob columns depend only on the words (the learnable semantic core), so two
inputs that differ only in punctuation share them — but their role, archetype, curves,
mood, and control rows reveal why they still sound different. The mood, complexity,
and control: rows are not voiced tokens; they shape neighboring syllables and pauses.
Helloandhellosound the same because the embeddedpotion-base-8Mtokenizer is uncased.- Empty or whitespace-only input emits the fixed inquisitive
?chirp and exits 0. - Literal
[PAD],[CLS],[SEP], and[MASK]are dropped.[UNK]is kept and voiced with its own mapping. - Prosodic punctuation (
.,!,?,,,;,:) is control-only; question, statement, exclamation, and clause marks each shape the preceding syllable and pause. - Standalone dash forms (
-,--, en dash, em dash) and ellipses (...,…) are control-only hesitation markers. A dash clips the previous tail; an ellipsis trails off. - Other symbols are tokenized and voiced normally when the tokenizer produces a voiced token.
- Neutral multi-word text still gets deterministic semantic accents, short word rests, and V11 rubato; punctuation is not required for the voice to move.
- Non-Latin text and emoji are accepted, but the semantic mapping is English-oriented and
will often route through
[UNK]or repetitive WordPiece shapes. - Very large input warns past about 8 minutes of rendered audio and errors before the fixed 30 minute / 160 MB ceiling.
Text is tokenized, each token is mapped through the embedded .doot asset to a semantic
vector, those vectors are reduced to four perceptual knobs (pitch, vowel, glide, warble),
each word is looked up in an embedded noun/verb class table (VOICE_V12) that adds class
onset markers and a compound stem → resolution silhouette to content words, and a
deterministic performance planner adds phrase roles, local affect/archetypes, pauses,
rests, and motion curves. A fixed formant-synthesis voice then renders the plan to one
canonical 44.1 kHz / 16-bit / mono buffer for both playback and WAV output.
The runtime does not load model2vec, candle, or any tensor framework — and no POS
tagger. xtask generates assets/dootdoot_asset_v1.doot (semantics + tokenizer) and
assets/dootdoot_pos_v1.doot (the word-class table) ahead of time; the shipped CLI
embeds both assets and uses pinned math, so identical input yields identical output on
the CI-verified platforms.
Full rationale lives in docs/design.md; the requirements are in
docs/spec.md. The full documentation map is
docs/README.md.
Development conventions, the architecture, and the test-first (red-green) workflow are
documented in CLAUDE.md and docs/style.md. The build
plan is in docs/plan.md.
cargo test # run the suite (see docs/style.md §11 for the full toolchain)MIT.
dootdoot is an independent project that produces sounds reminiscent of droids from science fiction. It is not affiliated with, endorsed by, or associated with Lucasfilm or The Walt Disney Company. "BB-8" is a trademark of its respective owner.