Skip to the content.

Lopatnov.Translate

Self-hosted speech and text translation service. .NET 10 · gRPC · ONNX Runtime · Docker.

CI License: Apache 2.0 GitHub issues GitHub stars

A self-hosted gRPC service for speech-to-text transcription, text translation, text-to-speech synthesis, and end-to-end speech-to-speech translation. All models run locally — no cloud dependencies. Multiple models can be configured by name and selected per request. Optional GPU/NPU acceleration via DirectML (Windows) or CUDA (Linux).


Getting Started

1. Clone

git clone https://github.com/lopatnov/translate.git
cd translate

2. Download models through hf

# Translation model (MIT, 100 languages)
hf download lopatnov/m2m100_418M-onnx --local-dir ./models/translate/m2m100_418M

# Language detection — required for auto-detect and DetectLanguage RPC (CC-BY-SA 3.0)
hf download lopatnov/fasttext-language-id lid.176.bin --local-dir ./models/detect-lang/fasttext-language-id

# Speech-to-text — Whisper small (~500 MB, MIT)
hf download lopatnov/whisper.cpp ggml-small.bin --local-dir ./models/audio-to-text/whisper.cpp

# Text-to-speech — Piper English voice (MIT)
hf download lopatnov/piper-voices \
  en_US/en_US-joe-medium.onnx en_US/en_US-joe-medium.onnx.json \
  --local-dir ./models/text-to-audio/piper-voices

See docs/models.md for all available models, voices, and language detection options.

3. Start

docker compose -f docker/docker-compose.yml up --build

The gRPC server starts on port 5100.

4. Translate text

grpcurl -plaintext \
  -d '{"text":"Hello","source_language":"en","target_language":"uk"}' \
  localhost:5100 lopatnov.translate.v1.TranslateService/TranslateText

5. Transcribe audio

# Linux (GNU base64)
grpcurl -plaintext \
  -d "{\"audio_data\": \"$(base64 -w0 my-audio.wav)\", \"language\": \"auto\"}" \
  localhost:5100 lopatnov.translate.v1.TranslateService/TranscribeAudio

# macOS (BSD base64 has no -w flag)
grpcurl -plaintext \
  -d "{\"audio_data\": \"$(base64 my-audio.wav | tr -d '\n')\", \"language\": \"auto\"}" \
  localhost:5100 lopatnov.translate.v1.TranslateService/TranscribeAudio

# PowerShell (Windows)
$b = [Convert]::ToBase64String([IO.File]::ReadAllBytes("my-audio.wav"))
grpcurl -plaintext -d "{`"audio_data`":`"$b`",`"language`":`"auto`"}" `
  localhost:5100 lopatnov.translate.v1.TranslateService/TranscribeAudio

6. Synthesize speech

grpcurl -plaintext \
  -d '{"text":"Hello, world!","language":"en"}' \
  localhost:5100 lopatnov.translate.v1.TranslateService/SynthesizeSpeech \
  | jq -r '.audioData' | base64 -d > output.wav

7. Speech-to-speech translation

# Transcribe + translate + synthesize in one call
grpcurl -plaintext \
  -d "{\"audio_data\": \"$(base64 -w0 speech.wav)\", \"source_language\": \"uk\", \"target_language\": \"en\"}" \
  localhost:5100 lopatnov.translate.v1.TranslateService/TranslateAudio \
  | jq -r '.translatedAudio' | base64 -d > translated.wav

See docs/api.md for the full API reference.


Documentation

Doc Description
docs/api.md gRPC API reference — RPCs, messages, examples
docs/models.md Model setup — download, configuration, licenses
docs/deployment.md Docker deployment
docs/development.md Local dev, build, testing

Project Structure

src/
  Lopatnov.Translate.Grpc/           # gRPC server, DI wiring, model registry
  Lopatnov.Translate.Core/           # interfaces, language detection, JSON localization
  Lopatnov.Translate.Nllb/           # NLLB-200 translator (ONNX Runtime)
  Lopatnov.Translate.M2M100/         # M2M-100 translator (ONNX Runtime)
  Lopatnov.Translate.Whisper/        # Whisper speech-to-text (Whisper.net)
  Lopatnov.Translate.Piper/          # Piper text-to-speech (ONNX Runtime + espeak-ng)
  Lopatnov.Translate.LibreTranslate/ # LibreTranslate HTTP client (optional)

tests/
  Lopatnov.Translate.Grpc.Tests/     # service dispatch, model session manager
  Lopatnov.Translate.Core.Tests/     # language detection, JSON localization
  Lopatnov.Translate.Nllb.Tests/     # tokenizer, translator, integration
  Lopatnov.Translate.M2M100.Tests/   # tokenizer, translator, integration
  Lopatnov.Translate.Whisper.Tests/  # audio resampling, recognizer, integration
  Lopatnov.Translate.Piper.Tests/    # phonemizer, synthesizer, integration

models/                              # gitignored — populate via hf (see docs/models.md)
  translate/                         # M2M-100, NLLB ONNX files
  detect-lang/                       # FastText LID-176, GlotLID
  audio-to-text/                     # Whisper ggml files
  text-to-audio/                     # Piper voice files

clients/
  translate-angular/                 # Angular web UI (7 pages: translate, detect, localize,
                                     #   transcribe, synthesize, speech-to-speech, live)
  translate-mcp/                     # MCP server — integrates the service as an AI tool

docker/
  Dockerfile
  docker-compose.yml

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request.


License

Apache 2.0 © 2026 Oleksandr Lopatnov · LinkedIn