Spaces:
Running
Running
metadata
title: kitsunechat
emoji: 🦊
colorFrom: blue
colorTo: purple
sdk: static
pinned: false
short_description: Voice-enabled Gemma 4 chat (Pocket TTS)
models:
- litert-community/gemma-4-E2B-it-litert-lm
- litert-community/gemma-4-E4B-it-litert-lm
kitsunechat
A voice-enabled fork of tylermullen/Gemma4 — same MediaPipe Gemma 4 chat UI, plus Pocket TTS running client-side. Every reply the model generates is automatically converted to speech and played back as it completes.
What's different
tylermullen/Gemma4 is a chat UI. This fork keeps everything the same and adds:
tts-bridge.js— observes the chat history shadow DOM for completed model messages (the.redo-buttononly appears whendoneGenerating=true, so it's the reliable "message is final" signal). When it appears, the message text is fed to Pocket TTS and the synthesized audio is attached inline as a<audio>element beneath the reply.worker.js+pkg/+tts-client.js— the Pocket TTS engine (Rust→WASM). Same code as our tts-site, with the audio/audios segmenter bug fixed. Model weights + voice embeddings are fetched at runtime from HuggingFace, then cached in the browser's Cache API.- Voice — azelma, by default.
The TTS runs entirely in your browser. Nothing leaves your device.
File layout
index.html loads bundle.js + tts-bridge.js
bundle.js MediaPipe Gemma 4 chat UI (from tylermullen/Gemma4)
tts-bridge.js ← observes chat-history, queues completed messages for TTS
tts-client.js orchestrator — picks worker per model
worker.js Pocket TTS worker (loads /pkg/tts_wasm_bg.wasm)
audio-worklet.js Web Audio worklet (not currently used; available for streaming)
pkg/ Pocket TTS WASM build (Rust → wasm-bindgen)
wasm/ MediaPipe LLM Inference WASM (from upstream)
Limits
- Pocket TTS text is bounded. Long LLM replies get split into segments; very long replies queue and play one after another.
- Browser autoplay policies may block the first auto-played clip until you click the page once. Subsequent replies autoplay normally.