Skip to content

About

Windows voice translation app with local whisper.cpp transcription, translation services, and virtual audio routing.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BabelSync — Real-Time Two-Way Voice Translation

Aplikasi Windows berbasis Python untuk terjemahan suara dua arah secara real-time di meeting Zoom/Meet/Teams, via whisper.cpp + VB-Audio Virtual Cable:

  • Inbound ("Telinga"): audio lawan bicara (Zoom/YouTube/dll) → transkrip → terjemahan Indonesia → dibacakan ke headset Anda.
  • Outbound ("Pita Suara"): suara Anda dari microphone → transkrip (Bahasa Indonesia) → terjemahan Inggris → disintesis dan dimainkan ke CABLE-A Input, yang di Zoom/Meet Anda pilih sebagai microphone (CABLE-A Output) — lawan bicara mendengar suara Inggris hasil AI.

Lihat proposal BABELSYNC.pdf untuk konteks produk lengkap.


1. Struktur Project

babelsync-stt/
├── src/
│   ├── __init__.py
│   ├── config.py          # Semua nilai yang bisa dikonfigurasi
│   ├── exceptions.py      # Exception khusus per komponen
│   ├── audio_capture.py   # Capture audio dari VB-Cable via sounddevice
│   ├── vad.py              # Voice Activity Detection -> segmentasi ucapan
│   ├── whisper_client.py  # Kelola subprocess whisper-server + HTTP client
│   ├── transcriber.py     # Orkestrator threading (capture/VAD/inferensi)
│   ├── display.py         # Output status & transkrip ke terminal
│   └── main.py            # Entry point + argparse + Ctrl+C handling
├── requirements.txt
├── run.bat                 # Launcher cepat untuk Windows
└── README.md                # Dokumen ini

Catatan arsitektur: whisper.cpp tidak dipanggil ulang per segmen audio (itu akan me-reload model setiap kali → sangat lambat). Sebagai gantinya, whisper-server (binary bawaan whisper.cpp) dijalankan sekali sebagai subprocess persisten saat aplikasi start, model ter-load sekali ke memory, lalu tiap segmen ucapan dikirim lewat HTTP lokal (/inference). Ini yang memungkinkan latency < 2 detik. Detail lebih lanjut ada di komentar whisper_client.py.


2. Instalasi Dependency Python

cd babelsync-stt
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt

Isi requirements.txt:

sounddevice>=0.4.6
numpy>=1.24.0
requests>=2.31.0
scipy>=1.11.0
colorama>=0.4.6
  • sounddevice — capture audio dari device (via PortAudio, WASAPI di Windows)
  • scipy — resampling berkualitas tinggi jika device tidak native 16kHz
  • requests — HTTP client ke whisper-server lokal
  • colorama — warna teks di CMD/PowerShell

3. Instalasi & Build Whisper.cpp

  1. Clone & build (butuh CMake + Visual Studio Build Tools / MSVC, atau bisa juga pakai MinGW):

    git clone https://github.com/ggerganov/whisper.cpp.git
    cd whisper.cpp
    cmake -B build
    cmake --build build --config Release

    Jika build sukses, akan muncul beberapa executable di build\bin\Release\, termasuk whisper-server.exe (yang dipakai aplikasi ini) dan main.exe.

    Untuk performa CPU lebih baik, tambahkan flag AVX2/OpenBLAS sesuai dokumentasi whisper.cpp. Untuk GPU NVIDIA, build dengan dukungan CUDA (-DGGML_CUDA=ON) supaya inferensi jauh lebih cepat — sangat direkomendasikan untuk mengejar target latency < 2 detik dengan model yang lebih besar dari "base".

  2. Download model ggml (format whisper.cpp, bukan model OpenAI Whisper Python biasa):

    cd models
    download-ggml-model.cmd base

    Ini akan menghasilkan models\ggml-base.bin. Untuk bahasa Indonesia, model multilingual (bukan varian .en) wajib dipakai — base, small, atau medium semuanya multilingual secara default. Semakin besar model → akurasi naik, tapi latency juga naik. Rekomendasi awal: base atau small untuk keseimbangan latency/akurasi di CPU.

  3. Sesuaikan path di src/config.py (atau lewat argumen CLI, lihat Bagian 6) agar mengarah ke lokasi hasil clone di atas:

    server_executable = "whisper.cpp/build/bin/Release/whisper-server.exe"
    model_path = "whisper.cpp/models/ggml-base.bin"

4. Instalasi & Konfigurasi VB-Audio Virtual Cable

  1. Download dari situs resmi VB-Audio Virtual Cable (vb-audio.com/Cable), lalu install dan restart Windows.

  2. Setelah restart, akan muncul dua device audio baru:

    • CABLE Input (VB-Audio Virtual Cable) — bertindak sebagai speaker/output
    • CABLE Output (VB-Audio Virtual Cable) — bertindak sebagai microphone/input
  3. Set sebagai default output (opsional, paling praktis) atau atur per-aplikasi:

    • Cara A (global): klik kanan ikon speaker di taskbar → Sound settings → set Output device = CABLE Input. Semua suara sistem (YouTube, Zoom, Spotify, dll) akan mengalir ke virtual cable.
    • Cara B (per-aplikasi, direkomendasikan): Windows 10/11 → Settings → System → Sound → Volume mixer (atau "App volume and device preferences") → untuk aplikasi seperti Chrome/Zoom, set Output-nya ke CABLE Input. Ini agar suara notifikasi Windows lain tidak ikut tertranskripsi.
  4. Suara asli sengaja TIDAK diperdengarkan. Audio yang dialihkan ke CABLE Input masuk ke virtual cable dan tidak terdengar di earphone Anda. Ini memang perilaku yang diinginkan: sesuai visi "Invisible AI", Anda cukup mendengar terjemahannya saja, tanpa dua suara bertabrakan.

    Jangan aktifkan "Listen to this device" di Windows — itu akan memunculkan kembali suara asli dan bertabrakan dengan terjemahan.

    Kalau Anda memang ingin tetap mendengar suara aslinya (misal untuk menangkap intonasi lawan bicara), nyalakan dengan --monitor. Saat aktif, suara asli otomatis meredup ke 15% selagi terjemahan berbunyi (auto-ducking, lihat monitor.py), lalu kembali normal:

    python -m src.main --monitor --monitor-volume 0.8 --duck-volume 0.1
  5. Aplikasi Python ini akan otomatis mencari device input yang namanya mengandung "CABLE Output" (lihat config.py → device_name_hint), jadi tidak perlu index device manual.

Setup Outbound (Mic → Suara Inggris ke Zoom) — VB-CABLE A+B

Pipeline outbound butuh satu virtual cable tambahan supaya tidak bentrok dengan cable inbound:

  1. Download VB-CABLE A+B dari vb-audio.com/Cable (paket terpisah dari VB-CABLE biasa, bagian "VB-CABLE A+B"), install CABLE A, lalu restart Windows. Akan muncul device baru CABLE-A Input dan CABLE-A Output.
  2. Di Zoom/Meet/Teams → Settings → Audio → Microphone → pilih CABLE-A Output.
  3. Selesai. BabelSync akan memainkan suara Inggris hasil terjemahan ke CABLE-A Input, dan Zoom membacanya dari CABLE-A Output seolah-olah itu microphone Anda.
  4. Microphone fisik Anda tetap dipakai oleh BabelSync (device input default sistem) — jangan set mic fisik sebagai input Zoom, nanti lawan bicara dengar dua suara.

Belum install VB-CABLE A+B? Jalankan dengan --no-outbound untuk memakai mode inbound saja seperti sebelumnya.


5. Cara Menjalankan Program

venv\Scripts\activate
python -m src.main

Atau langsung pakai launcher:

run.bat

Output contoh:

====================================================================
  BabelSync STT - Real-Time System Audio Transcription
====================================================================
Tekan Ctrl+C untuk berhenti.

Menjalankan whisper.cpp server (loading model)...
Membuka audio device...
Audio device   : CABLE Output (VB-Audio Virtual Cable)
Sample rate    : 16000 Hz (target whisper.cpp: 16000 Hz)
Whisper server : http://127.0.0.1:8090
Status         : READY

[14:32:10] Halo semuanya selamat datang di presentasi hari ini  (410 ms)
[14:32:14] terima kasih sudah bergabung  (350 ms)
-- status -- whisper=ONLINE avg_latency=380ms segments=2 queue_depth=0

Tekan Ctrl+C kapan saja untuk berhenti — aplikasi akan menutup audio stream, mem-flush sisa audio yang belum ditranskripsi, dan mematikan proses whisper-server dengan rapi (tidak meninggalkan proses zombie).

Argumen CLI opsional

python -m src.main --my-language id --remote-language en --threads 8
Argumen Keterangan
--device Substring device capture inbound (default "CABLE Output")
--mic-device Substring microphone untuk outbound (default: mic default sistem)
--outbound-device Device playback outbound (default "CABLE-A Input")
--my-language Bahasa Anda (default id)
--remote-language Bahasa lawan bicara (default en)
--segment-ms Durasi maks satu segmen (default 2000) — pengungkit latensi utama
--tts-speed Kecepatan bicara minimum terjemahan (default 1.0 = alami)
--tts-max-speed Batas atas kecepatan adaptif (default 1.8)
--monitor Ikut perdengarkan suara asli (default: hanya terjemahan)
--monitor-volume Volume suara asli 0.0-1.0 (default 1.0), saat --monitor aktif
--duck-volume Volume suara asli selagi terjemahan bicara (default 0.15)
--list-devices Tampilkan semua audio device lalu keluar
--test-audio Putar suara tes ke tiap output untuk cari device yang terdengar
--no-inbound Matikan pipeline inbound
--no-outbound Matikan pipeline outbound (mode lama, inbound saja)
--model Path ke file .bin model ggml
--server-exe Path ke whisper-server.exe
--port Port lokal whisper-server (default 8090)
--threads Jumlah thread CPU inferensi

6. Alur Kerja Program (Workflow)

 [App sumber suara]        [VB-Audio Virtual Cable]        [Python App]
 YouTube / Zoom / Teams          CABLE Input                     |
 Spotify / VLC / dll.  ---->   (virtual speaker)                 |
                                      |                           |
                                CABLE Output          <---  sounddevice.InputStream
                              (virtual microphone)           (audio_capture.py)
                                                                   |
                                                          block audio ~30-50ms
                                                                   |
                                                                   v
                                                      SpeechSegmenter (vad.py)
                                                    deteksi awal/akhir ucapan
                                                    berbasis energi RMS
                                                                   |
                                                     segmen ucapan lengkap
                                                                   |
                                                                   v
                                                     WhisperClient (whisper_client.py)
                                                     POST WAV in-memory ke
                                                     whisper-server (HTTP lokal)
                                                                   |
                                                        whisper-server (subprocess
                                                        persisten, model sudah
                                                        di-load di memory)
                                                                   |
                                                              hasil teks JSON
                                                                   |
                                                                   v
                                                      ConsoleDisplay (display.py)
                                                      cetak teks + timestamp +
                                                      waktu proses ke terminal

Threading yang berjalan paralel (lihat transcriber.py):

  1. Thread capture (dikelola PortAudio) — terus menangkap block audio kecil tanpa henti, dorong ke queue_raw_audio.
  2. Thread segmenter — konsumsi queue tersebut, jalankan VAD, dan begitu 1 ucapan selesai (hening terdeteksi atau batas durasi maks tercapai), submit segmen ke thread pool inferensi.
  3. Thread pool whisper (2 worker) — kirim HTTP request ke whisper-server, cetak hasil begitu balasan diterima. Karena menggunakan pool, capture & segmentasi ucapan berikutnya tidak pernah menunggu hasil transkripsi sebelumnya selesai.
  4. Thread status — cetak baris status berkala (device, whisper ONLINE/DOWN, rata-rata latency, jumlah segmen, kedalaman queue).

7. Optimasi Latency

Target: < 2 detik dari akhir ucapan sampai suara terjemahan mulai berbunyi. Terukur pada Intel Ultra 7 155H: rata-rata 1.01s (whisper 0.53s + translate 0.15s + TTS 0.22s).

Empat hal yang paling menentukan, semuanya sudah diterapkan by default:

  1. audio_ctx = 768 — pengungkit terbesar. Konteks encoder penuh (1500) setara 30 detik audio, padahal segmen kita maksimal 3.5 detik, jadi sisanya diproses percuma. Terukur pada 16 segmen podcast identik: penuh = 1.53s rata-rata, 768 = 0.79s dengan puncak jauh lebih stabil (1.33s vs 2.58s).

    Jangan tergoda menyetel audio_ctx otomatis per durasi segmen. Sudah dicoba dan lebih buruk: nilai terlalu kecil membuat whisper kehilangan keyakinan lalu mengulang inferensi dengan temperature lebih tinggi, sehingga puncaknya melonjak ke 4.59s dan segmen ikut hilang.

  2. max_segment_ms = 3500 + pemotongan di titik hening (cut_search_ms). Waktu inferensi whisper.cpp hampir konstan berapa pun panjang audionya (0.5 detik audio = 1.57s, 8 detik audio = 0.87s), karena input selalu di-padding ke 30 detik. Jadi segmen pendek tidak menghemat apa pun — ia hanya merusak konteks kalimat. Segmen panjang justru lebih efisien; latensi tetap rendah karena potongan hampir selalu dipicu jeda alami pembicara, bukan batas waktu.

  3. threads = 12 (dulu 4) — terukur di CPU 16-core: 4 thread = 1.03s, 8 = 0.82s, 12 = 0.63s, 16 = 0.66s (mulai jenuh).

  4. Session HTTP persisten untuk Google Translate & Google TTS — menghindari handshake TLS tiap segmen. Terukur translate 1.17s -> 0.09s dan TTS 1.58s -> 0.27s. Ini penghematan terbesar kedua setelah max_segment_ms.

  5. Kecepatan bicara adaptif + anggaran waktu — terjemahan Indonesia terukur 1.6x lebih panjang dari ucapan Inggris aslinya, dan pada kalimat panjang bisa 2-2.5x. Tanpa dipercepat, tiap segmen menambah utang waktu sampai antrean meluap dan kalimat dibuang diam-diam — terukur 26% kalimat tidak pernah berbunyi.

    Tiga setelan yang menyelesaikannya (terukur turun ke 0% dibuang):

    • tts_max_speed = 2.0 — batas 1.8 terus mentok sehingga audio tetap lebih panjang dari sumbernya.
    • tts_time_budget = 0.85 — target durasi playback dibuat lebih pendek dari ucapan aslinya. Menargetkan pas 1:1 tidak menyisakan kelonggaran sama sekali, sehingga antrean tidak pernah sempat terkuras.
    • tts_queue_depth = 2 dan tts_max_staleness_sec = 4.0 — pada kedalaman 1, kalimat baru langsung menendang kalimat sebelumnya sebelum sempat berbunyi. Pipeline sendiri sudah memakan ~1.4 detik, jadi ambang basi 2.5 detik membuang kalimat yang masih relevan.

    Kalau suaranya terasa terlalu cepat, turunkan --tts-max-speed 1.6; konsekuensinya sebagian kalimat akan kembali dibuang. Kalau justru masih ada yang hilang, naikkan --tts-max-speed 2.2.

    Percepatan memakai WSOLA time-stretch (tts_player._wsola), bukan resampling — nada suara tetap sama persis (diuji: sinus 220 Hz dipercepat 1.6x tetap 220 Hz). Resampling biasa akan menaikkan pitch ~8 semitone pada rasio segini dan terdengar seperti chipmunk. Biaya prosesnya hanya ~50 ms per segmen.

Kalau terjemahan terasa terpotong-potong, naikkan --segment-ms 3000 (konteks lebih utuh, latensi naik ~1 detik).

  • Gunakan model kecil: base atau small jauh lebih cepat dari medium/large di CPU. Kalau akurasi bahasa Indonesia kurang memuaskan dengan base, coba small dulu sebelum lompat ke model besar.
  • Build whisper.cpp dengan akselerasi hardware: AVX2 (default di sebagian besar CPU modern) atau, idealnya, CUDA jika ada GPU NVIDIA (-DGGML_CUDA=ON saat cmake). Ini bisa memangkas waktu inferensi beberapa kali lipat.
  • Sesuaikan threads di config.py mendekati jumlah core fisik CPU (bukan logical/hyperthreaded) — biasanya sweet spot di 4-8.
  • Tuning VAD (vad.py / VADConfig):
    • silence_hangover_ms lebih kecil → segmen "dipotong" lebih cepat setelah orang berhenti bicara → hasil tampil lebih cepat, tapi terlalu kecil bisa memotong ucapan yang masih menggantung (koma).
    • max_segment_ms membatasi durasi maksimum 1 segmen supaya orang yang bicara panjang tanpa jeda tetap dapat transkripsi bertahap, bukan menunggu sampai dia diam total.
  • whisper-server persisten (bukan spawn ulang per segmen) adalah optimasi terbesar — sudah diterapkan by design di whisper_client.py.
  • In-memory WAV — audio dikonversi ke WAV di RAM (io.BytesIO), bukan ditulis ke file disk dulu, untuk menghindari overhead I/O.
  • Auto-mute / drop block terlama saat queue penuh (di audio_capture.py) mencegah latency menumpuk tak terbatas jika inferensi sempat lebih lambat dari real-time.

8. Penanganan Error

Situasi Perilaku aplikasi
VB-Cable belum terinstall / device tidak ditemukan AudioDeviceError dengan pesan jelas + daftar device input yang tersedia, program berhenti sebelum mulai capture
whisper-server.exe tidak ditemukan di path yang dikonfigurasi WhisperServerError dengan saran cek path/instalasi, program tidak lanjut
File model .bin tidak ditemukan WhisperServerError dengan saran cara download model
whisper-server gagal start / crash sebelum siap WhisperServerError, program berhenti dengan pesan detail
whisper-server crash saat sedang berjalan Request HTTP berikutnya gagal → otomatis mencoba restart server (maks max_restart_attempts kali, default 3) sebelum menyerah pada segmen tersebut; aplikasi tetap berjalan untuk segmen selanjutnya
Satu request transkripsi gagal/timeout Segmen tersebut dilewati (error dicetak), tapi aplikasi tidak crash — capture & segmen berikutnya tetap jalan
Ctrl+C ditekan Audio stream ditutup, sisa buffer di-flush, whisper-server dimatikan dengan terminate()/kill(), ringkasan jumlah segmen dicetak

9. Konfigurasi Bahasa

Bahasa dikonfigurasi per arah (lihat DirectionConfig di src/config.py):

  • Inbound: source_language="en" (bahasa lawan bicara) → target_language="id" (yang Anda dengar).
  • Outbound: source_language="id" (yang Anda ucapkan) → target_language="en" (yang lawan bicara dengar).

Whisper dipaksa ke bahasa sumber per-request (lebih cepat & stabil daripada auto-detect). Set source_language="auto" di config jika ingin whisper mendeteksi bahasa otomatis per segmen (mis. code-switching).

Ubah cepat lewat CLI: --my-language id --remote-language en.


10. Troubleshooting Cepat

  • Tidak ada suara yang tertranskripsi sama sekali: cek Volume Mixer Windows — pastikan aplikasi sumber suara benar diarahkan ke CABLE Input, dan level volume aplikasi tersebut tidak 0.
  • Semua block dianggap "hening" padahal ada suara: turunkan silence_rms_threshold di VADConfig.
  • Kata pertama tiap kalimat sering terpotong: naikkan pre_speech_padding_ms.
  • Transkrip terpotong-potong walau orang tidak sedang jeda panjang: naikkan max_segment_ms dan/atau silence_hangover_ms.
  • Server whisper.cpp lambat sekali (>3-5 detik per segmen): coba model lebih kecil, build dengan CUDA, atau turunkan threads bila CPU Anda sedikit core (thread berlebih justru bisa memperlambat karena overhead context-switch).

About

Windows voice translation app with local whisper.cpp transcription, translation services, and virtual audio routing.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages