The Problem

Running real‑time voice translation on a small, offline device is hard. Cloud services add latency, cost, and a dependency on connectivity that many kiosk or handheld deployments cannot tolerate. This repo delivers a turnkey solution that runs a Gemma 4 model locally, captures microphone audio, and returns spoken translations without an internet connection.

What This Does

The project bundles a React/Vite UI and a Python FastAPI backend that together:

  • Front‑end (frontend/src/App.jsx) captures microphone input via useAudioRecorder, sends the raw waveform to the backend, and displays the translated text and synthesized speech in a terminal‑style UI (components/LanguageLane.jsx, components/ResponseDrawer.jsx).
  • Back‑end (backend/server.py) receives audio, forwards it to Moonshine for speech‑to‑text, then sends the text to LiteRT‑LM to run the gemma4‑e2b model locally. The resulting translation is returned as JSON, and the TTS engine converts it back to audio.
  • Deployment scripts (deploy-pi.sh, start.sh, setup.sh) automate the creation of a Python virtual environment, installation of dependencies, download of the LiteRT model, and launch of all services.

How It Is Wired

Entry Points

  • start.sh – orchestrates all services.
  • In dev mode: runs node --inspect frontend/ (Vite dev server) and python -m backend.server.
  • In prod mode: builds the React app (npm run build), starts backend/server.py (serves /dist/), and the LiteRT inference server (lite-rt start -m gemma4-e2b).

Control Flow

  1. frontend/src/main.jsx mounts App.jsx.
  2. App.jsx uses useAudioRecorder to capture mic data.
  3. Recorder calls fetch('/api/transcribe', {body: audioBlob}).
  4. backend/server.py receives the POST, streams the blob to Moonshine (moonshine.stt), gets text.
  5. Text is sent to LiteRT (lite-rt run) via the API exposed in server.py.
  6. The response JSON contains translation and a URL to an audio file.
  7. App.jsx fetches the audio and plays it, while the translated text is displayed in ResponseDrawer.jsx.

Key Functions

  • server.transcribe() – handles /api/transcribe.
  • server.translate() – proxies to LiteRT.
  • server.tts() – streams audio back via Moonshine.

The backend is the single point with the widest blast radius: any change to the inference pipeline must be reflected in server.py. The frontend is decoupled; UI changes rarely touch the backend.

How To Use It

Setup

# Clone
git clone https://github.com/moses-y/gemma-translator

# Make scripts executable
chmod +x setup.sh download_model.sh start.sh deploy-pi.sh

# Install Python deps
./setup.sh          # creates venv, installs FastAPI, Moonshine, etc.

# Download the Gemma 4 model
./download_model.sh

Run Locally (Development)

./start.sh          # starts Vite dev server (http://localhost:5173) and backend

Run in Production Mode

./start.sh --prod   # builds UI, serves via backend on http://localhost:3000

Deploy to Raspberry Pi 5

./deploy-pi.sh     # installs systemd unit, builds UI, configures LXDE kiosk

Configuration

  • No external env vars are required for the provided scripts.
  • Model path is hard‑coded in download_model.sh to ~/.lite-rt/lm/gemma4-e2b.

Real‑World Use

An 8 GB Raspberry Pi 5 Raspberry‑Pi kiosk can sit in a museum exhibit and translate spoken questions into the exhibit’s language, all on a small 480×320 touchscreen. The UI remains responsive because the model inference runs locally and audio capture is piped directly to the backend.

Code Health & Issues

  • Medium/SDLC – No test files detected – 0 tests across 31 files.
  • Medium/SDLC – No CI/CD pipeline detected – no .github/ or ci/ folder.
  • No obvious security or licensing gaps beyond the MIT license.

The Bottom Line

This repo delivers a functional, offline voice‑translation stack that’s easy to deploy on a Raspberry Pi 5. The architecture is clear, but the lack of automated tests and CI limits confidence in future changes. Teams wanting a quick prototype can adopt it immediately; teams requiring production‑grade reliability should add tests and a CI pipeline.