The most portable, accurate language translator you can build yourself.
A universal translator framework that runs on edge hardware — a microphone, an earpiece, a small OLED screen, and a local LLM. No cloud required. When internet is available, it transparently upgrades to a cloud LLM for even better translation quality.
Named after the Babel Fish from The Hitchhiker's Guide to the Galaxy — the tiny creature you put in your ear that instantly translates any language.
- Listens to speech through a microphone (with voice activity detection)
- Transcribes it to text using offline Vosk speech-to-text
- Translates the text using a local LLM (Ollama on Jetson/Pi) or cloud LLM
- Speaks the translation into your earpiece via Piper text-to-speech
- Displays the translated text on a small OLED screen for visual confirmation
- Caches common translations for instant recall on repeat phrases
Everything runs locally. No data leaves your device unless you enable cloud mode.
[Microphone] -> [capture.py] -> [stt.py] -> [translator.py] -> [tts.py] -> [Earpiece]
|
[screen.py] <- text readout in your language
|
[llm_bridge.py] <- local Ollama (default) / cloud (when online)
|
[cache.py] <- phrase cache for instant repeats
|
[main.py] <- orchestrator + CLI
| Code | Language | Native Name |
|---|---|---|
| en | English | English |
| es | Spanish | Espanol |
| fr | French | Francais |
| de | German | Deutsch |
| zh | Chinese | Chinese |
| ja | Japanese | Japanese |
| hi | Hindi | Hindi |
| ar | Arabic | Arabic |
Adding a language is a one-line change in src/core/types.py.
# Clone and test with zero hardware
git clone https://github.com/drwjkirkpatrick-web/tiny-babel-fish.git
cd tiny-babel-fish
# Run the test suite (109 tests, all mock-based)
python -m pytest tests/ -v
# Run one translation cycle in mock mode
cd src
python -m main --mock --once
# Run continuously in mock mode
python -m main --mock
# Translate Spanish to English
python -m main --mock --source-lang es --target-lang en| Component | Example | Price Range |
|---|---|---|
| Compute | NVIDIA Jetson Orin Nano 8GB or Raspberry Pi 5 | $150-250 |
| Microphone | USB mic (Blue Snowball) or I2S MEMS (INMP441) | $10-50 |
| Earpiece | USB earbuds or I2S DAC + speaker | $5-15 |
| Screen | SSD1306 0.96" I2C OLED (128x64) | $3-8 |
| Battery | USB power bank (5000mAh+) | $10-20 |
| Total | $178-343 |
OLED SDA -> Jetson/Pi I2C SDA (pin 3)
OLED SCL -> Jetson/Pi I2C SCL (pin 5)
OLED VCC -> 3.3V (pin 1)
OLED GND -> GND (pin 6)
# Install system dependencies
sudo apt-get install python3-pip python3-venv libportaudio2 portaudio19-dev
sudo apt-get install libatlas-base-dev ffmpeg libopenblas-dev
# Install Python dependencies
pip install pyaudio webrtcvad vosk piper-tts onnxruntime pyyaml pytest
# Download Vosk model (English, 40MB)
mkdir -p models
cd models
wget https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip
unzip vosk-model-small-en-us-0.15.zip
cd ..
# Download Piper TTS voice (English, ~50MB)
cd models
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/amy/medium/en_US-amy-medium.onnx
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/amy/medium/en_US-amy-medium.onnx.json
cd ..
# Install Ollama and pull a model
curl -fsSL https://ollama.ai/install.sh | sh
ollama pull qwen2.5:3b
# Run the translator
cd src
python -m main --source-lang en --target-lang esCreate a config.yaml for your hardware setup:
# Local LLM (Ollama)
local_model: "qwen2.5:3b"
local_host: "127.0.0.1"
local_port: 11434
# Cloud LLM (optional — leave empty for offline-only)
cloud_api_key: "" # Your API key
cloud_model: "gpt-4o-mini"
cloud_endpoint: "https://api.openai.com/v1/chat/completions"
# Speech models
stt_model_dir: "models/vosk-model-small-en-us-0.15"
tts_model_path: "models/en_US-amy-medium.onnx"
tts_voice: "en_US-amy-medium"
tts_speed: 1.0
# Display
screen_type: "ssd1306" # ssd1306 | pygame | mock
screen_width: 128
screen_height: 64
screen_i2c_addr: 0x3C
# Microphone
mic_device_index: -1 # -1 = default
vad_aggressiveness: 2 # 0-3 (0=permissive, 3=strict)
# Pipeline
mock_mode: false
source_lang: "en"
target_lang: "es"
# Cache
cache_db_path: "models/cache.db"
translation_cache_ttl: 86400 # 24 hoursRun with: python -m main --config config.yaml
The bridge routing logic is simple and robust:
- Cache hit -> instant return (no LLM call needed)
- Cloud LLM -> if internet is available and cloud is configured, use it for best quality
- Local LLM -> always available as fallback (Ollama on device)
- Rule-based -> basic phrase dictionary if all LLMs fail
The bridge never crashes on network failure. If the cloud goes down, it falls back to local. If local goes down, it falls back to the phrase dictionary. If the dictionary doesn't have the phrase, it echoes the original text with low confidence.
tiny-babel-fish/
src/
core/
types.py # Shared dataclasses + language registry
config.py # TranslatorConfig (from YAML or defaults)
capture.py # Microphone + VAD (pyaudio + webrtcvad)
stt.py # Speech-to-text (Vosk offline)
translator.py # Translation engine (LLM + rule-based fallback)
tts.py # Text-to-speech (Piper)
screen.py # Display output (SSD1306 OLED / pygame / mock)
cache.py # Translation cache (SQLite 3-tier lookup)
llm_bridge.py # Local/cloud LLM routing with fallback
main.py # Pipeline orchestrator + CLI
__init__.py # Package exports
tests/ # 109 tests (all mock-based, zero hardware)
scripts/
install.sh # Hardware setup script
docs/
hardware_guide.md # Component selection + wiring guide
models/ # Downloaded model files (gitignored)
voices/ # Voice profiles (gitignored)
PROMPTS.md # Testable build prompts
All 109 tests run in mock mode — no hardware, no network, no LLM required.
python -m pytest tests/ -vHardware-dependent tests (pyaudio, webrtcvad, vosk, piper) use
pytest.importorskip and skip gracefully when the library is missing.
MIT. Build it, modify it, sell it if you want. No restrictions.