npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gitchad/babble

v0.1.0

Published

An original procedural character voice for the browser. Native Web Audio, no runtime dependencies.

Readme

babble

A small, original procedural character voice for the browser. Native Web Audio, zero runtime dependencies, no speech recordings, voice packages or network TTS. English-like phonemes flow into connected words with tunable pitch, formants and punctuation-aware expression. It is a stylized voice, not general-purpose TTS.

The repository includes a character-only playground with an editable speech input and DialKit voice controls. The character is demo artwork, not part of the library package. Portfolio: tobis.vision.

Install

npm install @gitchad/babble

Local setup

Requires Bun 1.2.14 or newer for development/building. Consumers do not need Bun.

bun install --frozen-lockfile
bun test
bun run build
bun run typecheck
bun run demo:dev

The demo runs at http://127.0.0.1:4100; set PORT to change it. demo:dev builds once and serves; rerun bun run demo:build after changes. bun run demo:build creates the complete static site in demo/dist. bun run demo:preview serves an existing build. Set DEMO_REPO_URL when building to enable its Repository link. The portfolio link is already configured. Hosting is configured separately.

To test a local artifact:

bun run build
npm pack --ignore-scripts
npm install ./gitchad-babble-0.1.0.tgz

API

import { createBabble } from "@gitchad/babble"

const voice = createBabble() // No AudioContext, synthesis or network request yet.

// Call directly from a deliberate user gesture, such as a button click.
voice.speak("You found the bag?", {
  pitch: 1.35,
  formant: 1,
  intonation: 1,
  speed: 1.5,
  volume: 0.55,
  overlap: 0,
  softness: 0.7,
})

voice.stop()    // Release active sound and cancel queued/pending speech.
voice.dispose() // Release nodes/buffers/listeners and close its owned context.

createBabble({ context?: AudioContext, onProgress?: (event: BabbleProgress) => void }) can share an existing caller-owned context; it never closes a supplied context. The public types Babble, BabbleOptions, BabbleProgress and BabbleTextCue, plus defaultBabbleOptions, are exported. ESM and TypeScript declarations are included. Importing the package does not require a browser or create audio.

Tuning

| Option | Default | Range | Effect | | --- | ---: | --- | --- | | pitch | 1.35 | 0.25–4.5 | Fundamental frequency; does not change timing/formants | | formant | 1 | 0.25–3.5 | Vocal resonances; does not change fundamental/timing | | intonation | 1 | 0–3 | Flat at 0, modest at 1, theatrical at 2–3 | | speed | 1.5 | 0.45–2.8 | Articulation duration and pauses, independently of pitch | | volume | 0.55 | 0–1 | Output gain | | overlap | 0 | 0–0.12 seconds | Removes the word gap before overlapping adjacent words | | softness | 0.7 | 0–1 | Softer consonant air, attacks and final-stop release |

Options apply to the next speak. Finite out-of-range inputs clamp; missing and non-finite values use defaults. New speech replaces the current utterance. Punctuation selects smooth endings: questions rise, statements settle, exclamations emphasize, commas continue and ellipses trail off. Endings shape the final full vowel, including before trailing consonants and the quiet "bag-uh" release. Intonation 0 removes all pitch variation. No random per-letter notes, playback-rate pitch shifting, or borrowed speech implementation is used.

Timed text

const voice = createBabble({
  onProgress(event) {
    switch (event.type) {
      case "start":
        // event.text preserves original case/accents/punctuation.
        // event.cues contains complete source-word display chunks.
        break
      case "word":
        // Reveal cue event.index; event.audioTime is its audible attack time.
        break
      case "end":
        // Keep completed text visible, if desired.
        break
      case "stop":
        // Clear text on Stop, replacement, interruption or disposal.
        break
    }
  },
})

Callbacks follow actual scheduled source onsets, not synthesis lookahead. A 16 ms poll checks the output AudioContext timestamp, with reported latency as a fallback. Initial unvoiced stop closures, pauses, speed, explicit overlap and delayed scheduling are accounted for. Main-thread load can delay delivery; device latency estimates still need real browser listening. The core never touches the DOM. With no callback, no progress timer is created.

Source text retains spelling, case, accents, whitespace and punctuation. Numbers reveal as complete source words at their first spoken digit. Display and speech share truncation limits; unsaid long-word suffixes are excluded. The demo uses 14px Times New Roman with white inline highlights and reserves future word layout invisibly. Completed text holds; Stop/tab hiding clears it. Only one polite complete-phrase announcement is exposed to screen readers.

Lifecycle and limits

Use a modern browser with Web Audio. Speech must start from a user gesture; autoplay restrictions are handled by calling resume immediately inside Speak. Use stop on document hiding/navigation and dispose on teardown. Pending resume, old timers and sources cannot revive replaced/stopped utterances. The demo does this automatically and uses one lazy AudioContext.

Input is bounded to 240 normalized characters, 64 scored words, 30 seconds, and 32 letters/three seconds per word. A bounded LRU holds at most 12 word buffers and six seconds of mono 24 kHz PCM. Pitch resonances remain below Nyquist, waveforms stay bounded, and zero overlap never stacks word audio. English spelling and stress are approximate; names/irregular words may be inaccurate, and unsupported scripts are silent. This package is not an accessibility TTS replacement or a universal language model.

The library has no React, Three.js, DialKit, renderer, font or asset dependencies. The current core is 12,140 bytes minified / 5,537 bytes gzip (level 9). Those are development-only demo dependencies. files explicitly allows only dist, this README and the code license into the npm tarball.

License

Library and demo code: MIT, copyright Tobias Moccagatta. The cat artwork/model and textures remain separately owned; see demo/public/character/LICENSE. Character assets are not included in the npm package.