Real-time local audio dubber from English to Italian. Captures system audio, transcribes it, translates it, and synthesizes it in Italian with a male or female voice depending on the speaker.
Fully local. No LLMs. No virtual cables. Open source.
- System audio capture via WASAPI loopback (no virtual cable required)
- English transcription with Vosk large (
vosk-model-en-us-0.22) - Voice gender detection (male/female) with ECAPA-TDNN
- Automatic punctuation of the transcript with
kredor/punctuate-all - Offline EN→IT translation with Argos Translate
- Italian speech synthesis with Piper (Riccardo and Paola voices)
- Minimal GUI in Tkinter with device selection, widget locking during execution, and real-time log
- Output to a separate audio device (e.g. USB headphones), so the original stays muted
- 100% open source, usable in commercial contexts
System audio (speakers)
↓ WASAPI loopback
VAD (webrtcvad) — segments speech
↓
Gender detection (ECAPA-TDNN) — on English audio
↓
ASR (Vosk large) — English → text
↓
Punctuation (transformers) — adds punctuation
↓
Translation (Argos) — English → Italian
↓
TTS (Piper) — text → Italian voice (M or F)
↓
Playback on USB headphones
- Windows 10/11 (tested on Windows 11)
- CPU: modern quad-core (tested on i5-10400F)
- RAM: at least 8 GB (16 GB recommended)
- GPU: optional, but recommended for ECAPA and punctuation (tested on RTX 3060)
- Two separate audio devices:
- one for capture (e.g. speakers or main sound card)
- one for Italian output (e.g. USB headphones)
- Python 3.10+ (tested on 3.12.4)
- Up-to-date audio drivers (for WASAPI loopback)
- ~5 GB of disk space for models and dependencies
git clone https://github.com/<your-username>/dubber.git
cd dubberOr download the ZIP and extract it to a folder of your choice.
python -m venv venv
.\venv\Scripts\Activate.ps1If PowerShell blocks activation:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserThen retry:
.\venv\Scripts\Activate.ps1python -m pip install --upgrade pipIf you have an NVIDIA GPU with CUDA 12.6 or newer:
pip install torch==2.14.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cu126If you don't have an NVIDIA GPU (or prefer the CPU version):
pip install torch==2.14.0 torchaudio==2.11.0 --index-url https://download.pytorch.org/whl/cpupip install -r requirements.txtVosk large (English, ~1.8 GB)
Invoke-WebRequest -Uri "https://alphacephei.com/vosk/models/vosk-model-en-us-0.22.zip" -OutFile "vosk-model-en-us-0.22.zip"
Expand-Archive -Path "vosk-model-en-us-0.22.zip" -DestinationPath "models/"
Remove-Item "vosk-model-en-us-0.22.zip"Italian Piper voices (Riccardo M, Paola F)
New-Item -ItemType Directory -Force -Path "models/piper"
Invoke-WebRequest -Uri "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/it/it_IT/riccardo/x_low/it_IT-riccardo-x_low.onnx" -OutFile "models/piper/it_IT-riccardo-x_low.onnx"
Invoke-WebRequest -Uri "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/it/it_IT/riccardo/x_low/it_IT-riccardo-x_low.onnx.json" -OutFile "models/piper/it_IT-riccardo-x_low.onnx.json"
Invoke-WebRequest -Uri "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/it/it_IT/paola/medium/it_IT-paola-medium.onnx" -OutFile "models/piper/it_IT-paola-medium.onnx"
Invoke-WebRequest -Uri "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/it/it_IT/paola/medium/it_IT-paola-medium.onnx.json" -OutFile "models/piper/it_IT-paola-medium.onnx.json"Argos EN→IT package (~100 MB)
python -c "import argostranslate.package; argostranslate.package.update_package_index(); avail = argostranslate.package.get_available_packages(); pkg = next(filter(lambda x: x.from_code=='en' and x.to_code=='it', avail)); argostranslate.package.install_from_path(pkg.download()); print('Installed EN->IT')"HuggingFace models (ECAPA + punctuation): downloaded automatically on first launch. The first launch will take a few extra minutes.
python main.pyThe program loads the models in the background. Wait for the message:
All models ready. You can start.
At that point the Start button becomes active.
- Capture device (loopback): select the output endpoint you want to capture audio from (e.g. "Speakers (Realtek Audio) [Loopback]").
- Output device (USB headphones): select the headphones where you want to hear the Italian voice.
- Voice:
Auto (from gender)for automatic selection based on the speaker, or force male/female manually. - Press Start.
Important: mute the capture device (the speakers), otherwise you will also hear the original English along with the Italian. WASAPI loopback keeps working even with the device muted.
During execution, the menus are locked. Press Stop to interrupt cleanly (no residual audio).
The pipeline introduces a latency of 2-4 seconds between the original speech and the Italian voice. To sync video and dubbed audio for normal viewing, the cleanest approach is to delay the video with OBS.
- Open OBS and add a Source → Window Capture of the browser with YouTube.
- On the source, click Filters.
- Add one or more "Render Delay" filters (or the "Video Delay (Async)" filter if available for your source). Each "Render Delay" adds 500 ms; stacking several of them sums up (e.g. 10 filters = 5 seconds).
- Project the preview fullscreen onto the monitor where you want to watch.
- Mute the Windows speakers and do not add any audio sources in OBS. Audio is handled entirely by Dubber.
- Start Dubber and press Start.
- Adjust the video delay until the lip movement and the Italian voice are aligned. Start from 5000 ms and fine-tune by ear.
Note: the delay is not perfectly constant (it depends on segment length), so synchronization will be "good" but not always perfect. With a fixed delay of ~5 seconds, the misalignment is on the order of a few tenths of a second, which is tolerable.
If you need delays longer than 2-3 seconds, install the exeldro/obs-dynamic-delay plugin.
In config.py you can modify:
| Parameter | Default | Description |
|---|---|---|
VAD_MODE |
2 | VAD aggressiveness (0–3) |
VAD_SILENCE_TAIL_MS |
500 | Silence to close a segment |
VAD_MIN_SPEECH_MS |
300 | Minimum speech to start a segment |
VAD_MAX_SEGMENT_MS |
5000 | Maximum segment duration |
GENDER_MIN_SAMPLES |
16000 | Minimum samples to classify gender |
LOG_GUI_LINES |
500 | Maximum lines in the GUI log |
Practical tips:
- Segments too fragmented → increase
VAD_SILENCE_TAIL_MSto 700–900. - VAD not detecting weak speech → lower
VAD_MODEto 1. - VAD detecting too much noise → raise
VAD_MODEto 3. - Latency too high → lower
VAD_MAX_SEGMENT_MSto 3000–4000.
- Latency 2-4 seconds between original speech and Italian voice. To synchronize, delay the video with OBS (see above).
- ASR errors on compressed audio or fast speech: Vosk large is robust but not perfect. Whisper.cpp would improve quality but is slower and requires a pipeline redesign.
- Literal translation of idiomatic constructions: Argos performs NMT without context, so some sentences sound rigid.
- Overlapping voices: if two people speak at the same time, the gender is assigned to the dominant speaker.
- Proper nouns and technical terms: may be mis-transcribed and then translated oddly.
- Audio queue flush and
self.runningchecks distributed across the pipeline - No residual audio after Stop
- Fixed crash on log selection right after Stop
- Thread-safe log via
queue.Queueandroot.after() - GUI widgets locked during execution
- Start button disabled until models are ready
- Model warm-up after loading
VAD_MAX_SEGMENT_MSreduced from 15000 to 5000
- Added
kredor/punctuate-allmodel between ASR and translation - Better English text structure → more natural Italian translation
- Full pipeline: capture → VAD → gender → ASR → translation → TTS → output
- Vosk large (
vosk-model-en-us-0.22) - ECAPA-TDNN (
moorlee/gender-voice-classifier-ecapa) - Argos Translate EN→IT
- Italian Piper voices Riccardo (M) and Paola (F)
- Tkinter GUI
- WASAPI loopback capture without virtual cables
- v3: replace Vosk with Whisper.cpp for more accurate ASR
- v3: translation with MarianMT / Opus-MT for more natural sentences
- v3: streaming ASR for latency < 2 seconds constant
- v4: PyInstaller packaging for distribution without Python
| Component | License |
|---|---|
| Vosk | Apache 2.0 |
| Argos Translate | LGPL |
| Piper | MIT |
| SpeechBrain | Apache 2.0 |
| ECAPA-TDNN backbone | Apache 2.0 |
Gender classifier (moorlee) |
MIT |
Punctuator (kredor/punctuate-all) |
MIT |
| Piper voices Riccardo and Paola | MIT |
The project as a whole is usable in commercial contexts.
Project developed as an experiment in real-time local audio dubbing. Built on open source components from the Vosk, Piper, Argos, SpeechBrain, and HuggingFace communities.