A Rust-based speech translation pipeline using the Candle ML framework that:
Supports both single-file recording and segmented recording mode where you can press space to save each sentence separately.

The pipeline processes audio through four stages:
graph LR
A[Audio Input<br/>Finnish Speech] --> B[Speech-to-Text<br/>Whisper Finnish]
B --> C[Translation<br/>Helsinki-NLP Marian]
C --> D[Text-to-Speech<br/>Parler TTS Portuguese]
D --> E[Audio Output<br/>Portuguese Speech]
E -.-> F[Evaluation<br/>Whisper Portuguese]
style B fill:#e1f5ff,stroke:#333,color:#000
style C fill:#e1f5ff,stroke:#333,color:#000
style D fill:#e1f5ff,stroke:#333,color:#000
style F fill:#d4edda,stroke:#333,color:#000
audio_capture.rs)cpalspeech_to_text.rs)translation.rs)text_to_speech.rs)speech_evaluator.rs) - Test Mode Onlybrew install cmake)brew install llvm)Prerequisites (macOS):
Before building, install required dependencies:
# Install CMake (required for sentencepiece)
brew install cmake
# Install LLVM (required for Rust bindings)
brew install llvm
# Set LIBCLANG_PATH environment variable
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
Build the project:
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
cargo build --release
Or use the provided build script:
./build.sh
Before running the application, download the required models:
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib" # macOS only
cargo run --release -- --download-models
This downloads all required models to ./models/ directory:
The download only happens once - existing files are skipped.
Custom models directory:
cargo run --release -- --download-models --models-dir /path/to/models
For CUDA:
cargo build --release --features cuda
For Metal (Apple Silicon):
cargo build --release --features metal
cargo run --release -- --microphone
cargo run --release -- --microphone --segmented
Creates output files: output_portuguese_001.wav, output_portuguese_002.wav, etc.
cargo run --release -- --microphone --duration 10
cargo run --release -- --input audio.wav
cargo run --release -- --test-mode --test-text "Hei, miten voit?"
cargo run --release -- --test-mode --test-text "Hei, miten voit?" --evaluate
The --evaluate flag (only in test mode) will:
cargo run --release -- --microphone --output my_translation.wav
cargo run --release -- --microphone --cpu
cargo run --release -- --microphone --show-original
# or use short form:
cargo run --release -- --microphone -s
# Auto-detect best device (default)
cargo run --release -- --device auto --microphone
# Force CPU
cargo run --release -- --device cpu --microphone
# Use CUDA (if available)
cargo run --release -- --device cuda --microphone
# Use Metal on Apple Silicon (if available)
cargo run --release -- --device metal --microphone
cargo run --release -- --microphone --save-input recorded_finnish.wav --output translated_portuguese.wav
cargo run --release -- --models-dir /path/to/models --microphone
# Segmented recording with original Finnish text shown
cargo run --release -- --microphone --segmented --show-original
# Process file with GPU acceleration and custom output
cargo run --release -- --input finnish_audio.wav --device cuda --output result.wav
# Long recording with custom duration and both input/output saved
cargo run --release -- --microphone --duration 30 --save-input input.wav --output output.wav --show-original
Options:
-i, --input <INPUT> Input audio file (WAV format, 16kHz, mono)
-o, --output <OUTPUT> Output audio file path [default: output_portuguese.wav]
--save-input <SAVE_INPUT> Save input audio to file (when recording from microphone)
-m, --microphone Record from microphone (default mode if no input file specified)
-d, --duration <DURATION> Recording duration in seconds (only used with --microphone) [default: 5]
--segmented Enable segmented recording mode with space key to cut segments
-s, --show-original Show the original Finnish transcription text
--cpu Run on CPU rather than GPU
--device <DEVICE> Device to use for computation [default: auto] [possible values: auto, cpu, cuda, metal]
--test-mode Use test text instead of audio file (set via --test-text)
--test-text <TEST_TEXT> Test text to translate (only used with --test-mode) [default: "Hei, miten voit tänään?"]
--models-dir <MODELS_DIR> Directory containing model files [default: ./models]
--download-models Download missing models and exit
--evaluate Evaluate synthesized speech quality (test mode only)
-h, --help Print help
-V, --version Print version
| Option | Compatible With | Notes |
|---|---|---|
--input | --output, --show-original, --device, --cpu, --models-dir | Cannot use with --microphone, --duration, --save-input, --segmented |
--microphone | --duration, --segmented, --save-input, --output, --show-original, --device, --cpu, --models-dir | Cannot use with --input |
--segmented | --microphone only | Enables space-key recording mode |
--test-mode | --test-text, --evaluate | No audio input/output, text-only translation testing |
--evaluate | --test-mode only | Synthesizes and evaluates speech quality |
--download-models | --models-dir only | Exits after downloading, ignores all other options |
--cpu | Any audio processing mode | Overrides --device setting |
--device | Any audio processing mode | Ignored if --cpu is set |
All components now use real neural models:
| Component | Model | HuggingFace Link | Size |
|---|---|---|---|
| Speech-to-Text (Finnish) | Whisper Tiny Finnish | Finnish-NLP/whisper-tiny-finnish | ~151 MB |
| Translation (Finnish→English) | Marian MT (Stage 1) | Helsinki-NLP/opus-tatoeba-fi-en | ~141 MB |
| Translation (English→Portuguese) | Marian MT (Stage 2) | Helsinki-NLP/opus-mt-tc-big-en-pt | ~1.1 GB |
| Text-to-Speech (Portuguese) | Parler TTS Mini PTBR | freds0/parler-tts-mini-v1.1-ptbr | ~275 MB |
| Evaluation (Portuguese) | Whisper Tiny Portuguese | dominguesm/whisper-tiny-pt | ~151 MB |
Download: Use --download-models flag to download all models (~1.8 GB total). Models are cached locally and only downloaded once.
Note: Translation uses a two-stage pipeline (Finnish→English→Portuguese) as direct Finnish-to-Portuguese models are less common. The intermediate English translation is displayed during processing.
src/
├── main.rs # Main pipeline orchestration
├── audio_capture.rs # Audio recording functionality
├── speech_to_text.rs # Whisper-based STT (Finnish)
├── translation.rs # Marian MT translation (Finnish→Portuguese)
├── text_to_speech.rs # Parler TTS (Brazilian Portuguese)
└── speech_evaluator.rs # Portuguese speech evaluation (test mode)
Real-time Performance: Current implementation is batch-based, not optimized for real-time streaming.
macOS Building: Requires LLVM/Clang to be installed and LIBCLANG_PATH set before compilation.
Voice Variety: Currently uses a single Brazilian Portuguese female voice. No option to select different voices or dialects.
Model Size: Total download size is ~1.8 GB (including a large EN-PT translation model). Consider internet bandwidth and disk space for initial download.
Two-Stage Translation: Uses Finnish→English→Portuguese pipeline instead of direct translation, which may introduce slight quality variations compared to a hypothetical direct model.
# Test translation only with evaluation
cargo run --release -- --test-mode --test-text "Hyvää huomenta" --evaluate
# Test with different devices
cargo run --release -- --device cuda --test-mode --test-text "Kiitos"
cargo run --release -- --device metal --test-mode --test-text "Näkemiin"
cargo run --release -- --device cpu --test-mode --test-text "Hei"
# Save both input and output when using microphone
cargo run --release -- --microphone --save-input input.wav --output output.wav
MIT
10 commits
Rust
58.3%
Python
40.3%
Shell
1.4%
A Rust-based speech translation pipeline using the Candle ML framework that:
Supports both single-file recording and segmented recording mode where you can press space to save each sentence separately.

The pipeline processes audio through four stages:
graph LR
A[Audio Input<br/>Finnish Speech] --> B[Speech-to-Text<br/>Whisper Finnish]
B --> C[Translation<br/>Helsinki-NLP Marian]
C --> D[Text-to-Speech<br/>Parler TTS Portuguese]
D --> E[Audio Output<br/>Portuguese Speech]
E -.-> F[Evaluation<br/>Whisper Portuguese]
style B fill:#e1f5ff,stroke:#333,color:#000
style C fill:#e1f5ff,stroke:#333,color:#000
style D fill:#e1f5ff,stroke:#333,color:#000
style F fill:#d4edda,stroke:#333,color:#000
audio_capture.rs)cpalspeech_to_text.rs)translation.rs)text_to_speech.rs)speech_evaluator.rs) - Test Mode Onlybrew install cmake)brew install llvm)Prerequisites (macOS):
Before building, install required dependencies:
# Install CMake (required for sentencepiece)
brew install cmake
# Install LLVM (required for Rust bindings)
brew install llvm
# Set LIBCLANG_PATH environment variable
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
Build the project:
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
cargo build --release
Or use the provided build script:
./build.sh
Before running the application, download the required models:
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib" # macOS only
cargo run --release -- --download-models
This downloads all required models to ./models/ directory:
The download only happens once - existing files are skipped.
Custom models directory:
cargo run --release -- --download-models --models-dir /path/to/models
For CUDA:
cargo build --release --features cuda
For Metal (Apple Silicon):
cargo build --release --features metal
cargo run --release -- --microphone
cargo run --release -- --microphone --segmented
Creates output files: output_portuguese_001.wav, output_portuguese_002.wav, etc.
cargo run --release -- --microphone --duration 10
cargo run --release -- --input audio.wav
cargo run --release -- --test-mode --test-text "Hei, miten voit?"
cargo run --release -- --test-mode --test-text "Hei, miten voit?" --evaluate
The --evaluate flag (only in test mode) will:
cargo run --release -- --microphone --output my_translation.wav
cargo run --release -- --microphone --cpu
cargo run --release -- --microphone --show-original
# or use short form:
cargo run --release -- --microphone -s
# Auto-detect best device (default)
cargo run --release -- --device auto --microphone
# Force CPU
cargo run --release -- --device cpu --microphone
# Use CUDA (if available)
cargo run --release -- --device cuda --microphone
# Use Metal on Apple Silicon (if available)
cargo run --release -- --device metal --microphone
cargo run --release -- --microphone --save-input recorded_finnish.wav --output translated_portuguese.wav
cargo run --release -- --models-dir /path/to/models --microphone
# Segmented recording with original Finnish text shown
cargo run --release -- --microphone --segmented --show-original
# Process file with GPU acceleration and custom output
cargo run --release -- --input finnish_audio.wav --device cuda --output result.wav
# Long recording with custom duration and both input/output saved
cargo run --release -- --microphone --duration 30 --save-input input.wav --output output.wav --show-original
Options:
-i, --input <INPUT> Input audio file (WAV format, 16kHz, mono)
-o, --output <OUTPUT> Output audio file path [default: output_portuguese.wav]
--save-input <SAVE_INPUT> Save input audio to file (when recording from microphone)
-m, --microphone Record from microphone (default mode if no input file specified)
-d, --duration <DURATION> Recording duration in seconds (only used with --microphone) [default: 5]
--segmented Enable segmented recording mode with space key to cut segments
-s, --show-original Show the original Finnish transcription text
--cpu Run on CPU rather than GPU
--device <DEVICE> Device to use for computation [default: auto] [possible values: auto, cpu, cuda, metal]
--test-mode Use test text instead of audio file (set via --test-text)
--test-text <TEST_TEXT> Test text to translate (only used with --test-mode) [default: "Hei, miten voit tänään?"]
--models-dir <MODELS_DIR> Directory containing model files [default: ./models]
--download-models Download missing models and exit
--evaluate Evaluate synthesized speech quality (test mode only)
-h, --help Print help
-V, --version Print version
| Option | Compatible With | Notes |
|---|---|---|
--input | --output, --show-original, --device, --cpu, --models-dir | Cannot use with --microphone, --duration, --save-input, --segmented |
--microphone | --duration, --segmented, --save-input, --output, --show-original, --device, --cpu, --models-dir | Cannot use with --input |
--segmented | --microphone only | Enables space-key recording mode |
--test-mode | --test-text, --evaluate | No audio input/output, text-only translation testing |
--evaluate | --test-mode only | Synthesizes and evaluates speech quality |
--download-models | --models-dir only | Exits after downloading, ignores all other options |
--cpu | Any audio processing mode | Overrides --device setting |
--device | Any audio processing mode | Ignored if --cpu is set |
All components now use real neural models:
| Component | Model | HuggingFace Link | Size |
|---|---|---|---|
| Speech-to-Text (Finnish) | Whisper Tiny Finnish | Finnish-NLP/whisper-tiny-finnish | ~151 MB |
| Translation (Finnish→English) | Marian MT (Stage 1) | Helsinki-NLP/opus-tatoeba-fi-en | ~141 MB |
| Translation (English→Portuguese) | Marian MT (Stage 2) | Helsinki-NLP/opus-mt-tc-big-en-pt | ~1.1 GB |
| Text-to-Speech (Portuguese) | Parler TTS Mini PTBR | freds0/parler-tts-mini-v1.1-ptbr | ~275 MB |
| Evaluation (Portuguese) | Whisper Tiny Portuguese | dominguesm/whisper-tiny-pt | ~151 MB |
Download: Use --download-models flag to download all models (~1.8 GB total). Models are cached locally and only downloaded once.
Note: Translation uses a two-stage pipeline (Finnish→English→Portuguese) as direct Finnish-to-Portuguese models are less common. The intermediate English translation is displayed during processing.
src/
├── main.rs # Main pipeline orchestration
├── audio_capture.rs # Audio recording functionality
├── speech_to_text.rs # Whisper-based STT (Finnish)
├── translation.rs # Marian MT translation (Finnish→Portuguese)
├── text_to_speech.rs # Parler TTS (Brazilian Portuguese)
└── speech_evaluator.rs # Portuguese speech evaluation (test mode)
Real-time Performance: Current implementation is batch-based, not optimized for real-time streaming.
macOS Building: Requires LLVM/Clang to be installed and LIBCLANG_PATH set before compilation.
Voice Variety: Currently uses a single Brazilian Portuguese female voice. No option to select different voices or dialects.
Model Size: Total download size is ~1.8 GB (including a large EN-PT translation model). Consider internet bandwidth and disk space for initial download.
Two-Stage Translation: Uses Finnish→English→Portuguese pipeline instead of direct translation, which may introduce slight quality variations compared to a hypothetical direct model.
# Test translation only with evaluation
cargo run --release -- --test-mode --test-text "Hyvää huomenta" --evaluate
# Test with different devices
cargo run --release -- --device cuda --test-mode --test-text "Kiitos"
cargo run --release -- --device metal --test-mode --test-text "Näkemiin"
cargo run --release -- --device cpu --test-mode --test-text "Hei"
# Save both input and output when using microphone
cargo run --release -- --microphone --save-input input.wav --output output.wav
MIT
10 commits
Rust
58.3%
Python
40.3%
Shell
1.4%