Real-time speech-to-speech translation for any meeting app โ your voice, every language.
Project description
๐๏ธ meetdub
Speak any language with your own voice โ in any meeting.
Real-time speech-to-speech translation that lives between your mic and Teams/Zoom/Meet.
English ยท ๆฅๆฌ่ช
built on OpenAI's gpt-realtime-translate ยท runs locally ยท BYO API key ยท MIT
๐น Demo GIF goes here โ
docs/demo.gif(Teams call with live JAโEN translation in the meetdub TUI)
Why meetdub?
| meetdub | Microsoft Teams Live Translation |
Krisp / Noise tools | Heygen (avatar dubbing) |
|
|---|---|---|---|---|
| Works in any app | โ | โ Teams only | โ | โ |
| Your own voice | โ | โ Synth voice / text captions | N/A | โ |
| Bring your own key | โ | โ | โ | โ |
| Open source | โ | โ | โ | โ |
| Cost | ~$2/hr | Per-seat license | Subscription | Subscription |
| Self-hostable | โ | โ | โ | โ |
Quick start
curl -fsSL https://raw.githubusercontent.com/Yarta-AI/meetdub/main/install.sh | bash
meetdub auth openai # paste your sk-โฆ (hidden input)
meetdub setup # one-time wizard: language + devices + passthrough
meetdub run # โถ start translating
In Teams / Zoom / Meet, set microphone โ BlackHole 2ch. That's it.
Day-to-day after that is just meetdub run, or meetdub run --to en to switch
target language for one session.
How it works
โโโโโโโโโโโโโโโโโ 24kHz PCM16 โโโโโโโโโโโโโโโโโโโโโโโโ
you speak โโโโโโโถ โ mic โ โโโโโโโโโโโโโโโโโโถโ gpt-realtime-translateโ
โ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โ translated audio
โ โ (your voice, target language)
โ โผ
โ โโโโโโโโโโโโโโโโโโโโโ
โ โ BlackHole 2ch โ โโโถ Teams hears it
โ โโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โผ (--monitor)
โ โโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโ live bilingual captions in your terminal โ your headphones โ
โโโโโโโโโโโโโโโโโโโโโ
- Capture โ
sounddevicereads 24 kHz mono PCM16 in 20 ms frames. - VAD โ RMS energy gate skips silence so you only pay for speech. No native deps.
- Translate โ WebSocket to
wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate(or your Azure deployment). - Play โ translated audio writes straight to BlackHole 2ch. Teams reads BlackHole as its microphone.
- TUI โ
rich.Liverenders bilingual source / target captions plus a running cost meter. - Hotkeys โ
pynputlistens for F2โF12 (language hot-swap), Space (push-to-translate), Esc (quit).
Features
- ๐ญ Voice preservation โ
gpt-realtime-translatekeeps your tone, pitch, and cadence. People hear you, just in another language. - ๐ช Universal โ Teams ยท Zoom ยท Google Meet ยท Slack huddles ยท Discord ยท OBS ยท QuickTime ยท FaceTime. If it picks a mic, meetdub works.
- โก One-command install + setup wizard โ
install.shhandles BlackHole / pipx / brew;meetdub setupwrites the rest. After that, you just runmeetdub run. - ๐ 11 output languages โ English, ๆฅๆฌ่ช, Espaรฑol, Franรงais, Deutsch, ไธญๆ, ํ๊ตญ์ด, Portuguรชs, Italiano, เคนเคฟเคจเฅเคฆเฅ, ะ ัััะบะธะน. Plus Indonesian and Vietnamese.
- โจ๏ธ Hot-swap mid-call โ tap F2โF12 to change target language without restarting.
- ๐๏ธ Live passthrough mix โ
+ / - / 0adjusts how loud your original voice rides under the translation. Cookbook-recommended for mixed-language meetings (avoids silence when the other side speaks your target language). - ๐ Push-to-translate โ hold Space (with
--ptt) so meetdub only listens while you're speaking. Perfect for multilingual calls where you want to hear the other side untranslated. - ๐ธ Live cost meter โ your TUI shows actual API spend so you never get a surprise invoice.
- ๐ Bilingual transcripts โ every session auto-saves a Markdown transcript to
~/.meetdub/transcripts/. - ๐ Local secrets โ credentials in
~/.meetdub/secrets.env(chmod 600), never in shell rc. - โ๏ธ Two backends โ OpenAI direct or Azure OpenAI (api-key or Microsoft Entra ID).
- ๐ MIT, no telemetry โ single Python package, no servers we control, no analytics.
Install
Requirements: macOS, an OPENAI_API_KEY (or Azure OpenAI deployment).
One-liner
curl -fsSL https://raw.githubusercontent.com/Yarta-AI/meetdub/main/install.sh | bash
The installer runs through 5 visible steps:
- Homebrew โ installs if missing
- pipx โ
brew install pipx && pipx ensurepath - BlackHole 2ch โ
brew install --cask blackhole-2ch(sudo for system extension) - meetdub โ
pipx install meetdub - Audio setup โ walks you through creating a Multi-Output Device so you can hear yourself while Teams hears the translation
Audit before running
git clone https://github.com/Yarta-AI/meetdub && cd meetdub
less install.sh
./install.sh
Or use the Python bootstrap: python3 scripts/bootstrap.py.
After install
If you see meetdub: command not found, your shell hasn't picked up ~/.local/bin yet:
exec zsh # or: source ~/.zshrc
Configure credentials
Credentials live in ~/.meetdub/secrets.env (chmod 600) โ never in your shell rc.
OpenAI
meetdub auth openai # interactive, hides input
meetdub auth openai --key sk-โฆ # non-interactive
Azure OpenAI
Three auth modes are supported:
# 1. API key
meetdub auth azure
# prompts: endpoint, deployment, key
meetdub auth azure --endpoint my-resource.openai.azure.com \
--deployment my-realtime-translate \
--key โฆ
# 2. Static Microsoft Entra Bearer token
meetdub auth azure --aad-token "$(az account get-access-token --resource https://cognitiveservices.azure.com --query accessToken -o tsv)"
# 3. Interactive browser login (no `az` CLI needed)
meetdub auth login
# opens your browser, signs you into Azure, caches the token for auto-refresh
Use case for auth login: when your Azure OpenAI resource is configured for Microsoft Entra ID only (api-key disabled). It's the smoothest path and survives token expiry automatically.
Inspect / clear
meetdub auth show # masked summary
meetdub auth clear --openai # remove specific backend
meetdub auth clear --azure
meetdub auth clear --all
meetdub auth path # print file path
Precedence: shell env vars > ~/.meetdub/secrets.env. So OPENAI_API_KEY=other-key meetdub run โฆ still overrides cleanly for one-off testing.
Run
After meetdub setup, the everyday command is just:
meetdub run
One-off overrides:
meetdub run --to en # switch target language for this session
meetdub run --ptt # push-to-translate mode (hold Space)
meetdub run --passthrough # mix original mic in at 15% (adjust with +/-)
meetdub run --azure # use Azure backend
If you skip meetdub setup, sane defaults apply:
- Output โ
BlackHole 2ch(the virtual mic Teams/Zoom will pick up) - Input โ auto-selects MacBook / Built-in mic when one is available (AirPods mic pickup is unreliable for translation)
- Monitor โ none (you won't hear the translation yourself โ pass
--monitor "AirPods"to fix)
In Teams / Zoom / Meet:
- Microphone:
BlackHole 2ch - Speaker: your real headphones (so you hear the other party)
- Noise suppression: โ Low or Off โ Teams' default "auto" filters out synthesized voices.
Hotkeys
| Key | Action |
|---|---|
F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 |
EN ยท JA ยท ES ยท FR ยท DE ยท ZH ยท KO ยท PT ยท IT ยท HI ยท RU |
+ / - |
passthrough volume ยฑ5% |
0 |
mute passthrough |
Space (hold, with --ptt) |
push-to-translate |
Esc |
quit |
Two paths handle these keys:
- Global (works while Teams is focused) โ
pynputlistener. Needs macOS Input Monitoring + Accessibility permission for your terminal app. - TTY fallback (works only when meetdub's terminal is focused, but needs no permissions) โ direct
/dev/ttyread in cbreak mode.
โ macOS reserves the F-key row for media controls by default. Either hold
fnwhile pressing F2, or enable System Settings โ Keyboard โ Use F1, F2, etc. keys as standard function keys.
CLI reference
meetdub install Install BlackHole + audio walkthrough
meetdub setup Interactive wizard (language, devices, passthrough)
meetdub run [options] Start translating
meetdub auth openai | azure | login Save credentials
meetdub auth show | clear | path Manage credentials
meetdub doctor Verify environment
meetdub devices List audio devices
meetdub languages Supported output languages
meetdub config Print current config
meetdub keys-test Verify keyboard permission (Input Monitoring)
meetdub mic-test Verify microphone permission + level
meetdub --version
meetdub run options
| Option | Default | Notes |
|---|---|---|
--to / -t |
from config | Target language code (en, ja, es, fr, de, zh, ko, pt, it, hi, ru, id, vi) |
--input |
auto-detect MacBook mic, else system default | Substring match on input device name |
--output |
BlackHole 2ch |
Substring match on output device name |
--monitor |
none (from config if set) | Also play translation here so you hear yourself |
--ptt |
off | Translate only while Space is held |
--passthrough |
off | Mix original mic at 15% into BlackHole (adjust with +/- in TUI) |
--passthrough-gain |
โ | Set explicit linear gain 0.0โ1.0 (overrides --passthrough) |
--no-vad |
off | Always send audio (more accurate, more cost) |
--no-transcript |
off | Skip the Markdown transcript |
--azure |
off | Use Azure backend |
--azure-endpoint |
from auth | my-resource.openai.azure.com |
--azure-deployment |
from auth | Deployment name |
--azure-api-version |
GA | Set for preview API (deprecated 2026-04-30) |
--azure-path |
/openai/v1/realtime/translations |
Override if your region 404s |
--latency-ms |
0 (device minimum) |
Output buffer in milliseconds. Bump to 30โ100 if you hear stutter; 0 is closest to real-time. |
--debug |
off | Verbose log to ~/.meetdub/debug.log |
Troubleshooting
Run meetdub doctor first โ it checks Homebrew, BlackHole, secrets, and Azure config.
| Symptom | Cause / fix |
|---|---|
meetdub: command not found |
Run exec zsh to refresh PATH after pipx install. |
meetdub doctor shows BlackHole as โ even after brew install |
Run sudo killall coreaudiod to make CoreAudio re-scan plugins. |
No audio captured โ mic-test shows < -100 dBFS |
macOS Microphone permission missing. Settings โ Privacy & Security โ Microphone โ enable your terminal. Cmd+Q the terminal, then reopen. |
F-keys / Esc / Space do nothing โ keys-test receives nothing |
macOS Input Monitoring permission missing. Settings โ Privacy & Security โ Input Monitoring and Accessibility โ enable your terminal. Cmd+Q, reopen. |
| Translation runs but Teams stays silent | Set Teams microphone to BlackHole 2ch. Also: noise suppression โ Low or Off. |
| Teams sounds robotic / chopped | Teams' noise suppression is filtering meetdub's output. Set it to Off. |
Endpoint configured for Microsoft Entra ID authentication, key is not needed |
Your Azure resource disabled api-key auth. Run meetdub auth login for browser login. |
| Audio is choppy / "ใทใคใทใค" | Bump the output buffer: meetdub run --latency-ms 50 (or 100). Bluetooth monitors like AirPods compound the issue โ try a wired output for comparison. |
| Persistent transcription errors mid-call | Speak in complete sentences (3+ seconds). Very short utterances or whispers fail to transcribe. Try --no-vad. |
Roadmap
- Demo GIF in this README
- Homebrew tap (
brew install Yarta-AI/meetdub/meetdub) - Linux support (PulseAudio / PipeWire null-sink)
- Windows support (VB-CABLE)
- Two-way mode โ pipe the other side's audio through translation back to your headphones
- Glossary plugin hooks โ rewrite jargon / product names before TTS
- Local-model backend โ
whisper.cpp+ open TTS for offline / privacy mode - macOS Keychain storage backend as alternative to
secrets.env - Web version using the WebRTC
/realtime/translations/callsendpoint (reaches mobile browsers)
๐ Not planned: native iOS / Android apps that inject into other apps' microphones. The platform sandbox forbids virtual audio drivers, so meetdub's BlackHole-style approach won't translate. The Web version above is the practical path for mobile users.
Contributing
PRs welcome โ please open an issue first for anything bigger than a typo. See CONTRIBUTING.md.
Acknowledgements
- OpenAI โ
gpt-realtime-translatemodel and Realtime API - Existential Audio โ the BlackHole virtual audio driver
- sounddevice ยท websockets ยท rich ยท typer ยท pynput ยท azure-identity
License
MIT โ do whatever you want, just don't blame us.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file meetdub-0.1.0.tar.gz.
File metadata
- Download URL: meetdub-0.1.0.tar.gz
- Upload date:
- Size: 51.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf02e9eb60c2a3e46ab50dd4eb49463a32bb43f6036bda481428bd2ad94c100e
|
|
| MD5 |
5b24351321c76201f828d7225b57d6b3
|
|
| BLAKE2b-256 |
04a875ced3bd79f602d1c5e3f09ab3c10edac9e68bbf3f0c368e7184a5f60d60
|
Provenance
The following attestation bundles were made for meetdub-0.1.0.tar.gz:
Publisher:
release.yml on Yarta-AI/meetdub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
meetdub-0.1.0.tar.gz -
Subject digest:
bf02e9eb60c2a3e46ab50dd4eb49463a32bb43f6036bda481428bd2ad94c100e - Sigstore transparency entry: 1572116862
- Sigstore integration time:
-
Permalink:
Yarta-AI/meetdub@e527911cdf38951ddd87000ac20d1392c4dd31b3 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Yarta-AI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e527911cdf38951ddd87000ac20d1392c4dd31b3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file meetdub-0.1.0-py3-none-any.whl.
File metadata
- Download URL: meetdub-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe6ed65961ab5075255c924703b39c8e90b994b25e5b1366ef289d8ffc30fca5
|
|
| MD5 |
187a0e9d72c5308b5b6f92c0f58e7cc4
|
|
| BLAKE2b-256 |
0b194e3fb388bbc3e61325ffe6de79d7f3ae53a233680cc93fba3d4952af2ef9
|
Provenance
The following attestation bundles were made for meetdub-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Yarta-AI/meetdub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
meetdub-0.1.0-py3-none-any.whl -
Subject digest:
fe6ed65961ab5075255c924703b39c8e90b994b25e5b1366ef289d8ffc30fca5 - Sigstore transparency entry: 1572116894
- Sigstore integration time:
-
Permalink:
Yarta-AI/meetdub@e527911cdf38951ddd87000ac20d1392c4dd31b3 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Yarta-AI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e527911cdf38951ddd87000ac20d1392c4dd31b3 -
Trigger Event:
push
-
Statement type: