turkish-stt
🇹🇷 Türkçe · Model (v2) · Damga (Turkish ITN) · PyPI
Real-time, low-latency speech-to-text (STT) for Turkish — on the CPU.
Turkish-only · streaming · CPU-native · runs on the edge. A compact 66 M-parameter causal streaming model, built for voice agents, call centers, and on-device transcription where a GPU is not an option — no API key, no cloud, no GPU.
- 🇹🇷 Turkish-first — every parameter serves one language, not ~100
- ⚡ Streaming — partial results as you speak (~320 ms), no 30-second windows
- 🖥️ CPU-native — RTF 0.128 on a single CPU thread (~8× faster than real time)
- 🔌 Tiny — ~68 MB; runs on a Raspberry-Pi-class device
- 🔢 Written-form output —
itn=Trueturns "yüz elli lira" into "150 TL" via Damga
2.0.0 ships the new model,
turkish-stt-66m-v2: ~34% fewer word errors than v1 at the same size and speed. See Versions.
Installation
pip install turkish-stt # 2.0.0 — model v2
pip install "turkish-stt[itn]" # + Damga, for written-form output
pip install --upgrade turkish-stt # existing users: upgrade to 2.0.0
Usage
import mihu_stt
# one-shot: transcribe a file (16 kHz mono, or anything soundfile reads)
text = mihu_stt.transcribe("audio.wav")
print(text) # "toplam yüz elli lira ödedim"
# written form via Damga (pip install "turkish-stt[itn]")
mihu_stt.transcribe("audio.wav", itn=True) # "toplam 150 TL ödedim"
# timed segments, cut at detected turn ends — for subtitles or a searchable transcript
for seg in mihu_stt.transcribe_segments("audio.wav", itn=True):
print(seg["start"], seg["end"], seg["text"])
Streaming — feed audio as it arrives and read an updating transcript, with turn-end detection built in:
import mihu_stt
stt = mihu_stt.StreamingSTT(itn=True)
# pcm16 = 16-bit PCM bytes from your mic / phone line
text, is_final = stt.accept_pcm16(pcm16, sample_rate=16000)
# `text` updates while speech continues; `is_final` turns True at end-of-utterance.
# With itn=True the final text of each turn is in written form; partials stay as heard.
Model weights download automatically from Hugging Face
(mihuai/turkish-stt-66m-v2) the first time and are cached.
Try it on your microphone
examples/microphone.py is a ~60-line live transcriber — partial text updates as
you speak, each turn commits with a ✓ when the model detects end-of-utterance:
pip install "turkish-stt[itn]" sounddevice
python examples/microphone.py # default input device
python examples/microphone.py --itn # finished turns in written form (Damga)
python examples/microphone.py --list-devices # or pick one: --device 1
✓ Telefon numaram 0532 123 45 67, toplam 150 TL ödedim.
Transcribe a file, export the transcript
examples/export_transcript.py turns any audio file into a plain-text
transcript or timed subtitles — the format follows the output extension:
python examples/export_transcript.py meeting.wav # -> meeting.txt
python examples/export_transcript.py meeting.wav -o subs.srt # .srt / .vtt / .json
Integrations
Drop-in adapters for the common voice-agent stacks (see examples/):
LiveKit Agents — examples/livekit_stt.py:
from livekit.agents import AgentSession
from livekit_stt import MihuSTT
session = AgentSession(stt=MihuSTT(), llm=..., tts=...)
Pipecat — examples/pipecat_stt.py:
from pipecat_stt import MihuSTTService
pipeline = Pipeline([transport.input(), vad, MihuSTTService(), llm, tts, transport.output()])
Damga — written-form output
Damga (PyPI: damga) is mihu's
open-source, offline, deterministic Turkish text normalizer. The model writes what it hears; Damga turns
it into what people write — numbers, money, dates, times, phone numbers. No GPU, no network, no LLM.
itn=True is the shortcut; you can also call Damga directly:
from damga import InverseNormalizer
itn = InverseNormalizer()
itn.normalize("yüz elli lira") # '150 TL'
itn.normalize("saat dokuz otuzda") # "saat 09:30'da"
itn.normalize("sıfır beş otuz iki yüz yirmi üç kırk beş altmış yedi") # '0532 123 45 67'
Use it when a person reads the text (subtitles, minutes, CRM notes). If the transcript goes straight to an LLM you can usually skip it — the LLM understands "on yedi" and "17" alike.
Benchmarks
Measured in-house, same audio, one scoring script. FLEURS-TR (743 clips, real human read speech). Full table, methodology and reproduction: model card.
| System | Class | Params | WER % (standard) | WER % (Damga) | CPU RTF |
|---|---|---|---|---|---|
| Whisper large-v3 | offline · GPU | 1.5 B | 7.82 | 4.48 | 6.095 |
| Whisper large-v3-turbo | offline · GPU | 0.8 B | 8.26 | 4.84 | 4.296 |
| turkish-stt 2.0.0 (v2) | streaming · CPU | 66 M | 10.06 | 6.21 | 0.128 |
| turkish-stt 0.1.1 (v1) | streaming · CPU | 66 M | 15.12 | 9.38 | 0.128 |
| Whisper small | offline · GPU | 244 M | 17.41 | 13.27 | 1.098 |
Standard = OpenAI Whisper BasicTextNormalizer (compare with other published numbers). Damga = Damga
written→spoken normalization + Turkish-aware casing — counts "17" and "on yedi" as the same word. CPU RTF on a
single thread (AMD EPYC 7282); v2 has the same architecture as v1, so speed is unchanged.
Reproduce the numbers
The evaluation set, references, and scripts are in eval/ — including the text (n-gram) and acoustic
(chromaprint) contamination audits.
pip install "turkish-stt[eval]"
python eval/run_fleurs.py --out hyp.jsonl # FLEURS-TR, 743 real-human clips
python eval/score.py --fleurs-tsv fleurs/tr_tr/test.tsv --hyp hyp.jsonl
# damga WER 6.21 CER 1.70 <- v2 (v1: 9.38)
# standard WER 10.06 CER 3.90 <- v2 (v1: 15.12)
python eval/run_eval.py --data-dir eval/tts-synthetic # synthetic check: v2 9.67% · v1 15.03%
Versions
| Package | Model | Hugging Face | Install |
|---|---|---|---|
| 2.0.0 (default) | v2 — turkish-stt-66m-v2 |
mihuai/turkish-stt-66m-v2 |
pip install turkish-stt |
| 1.0.0 | v1 — turkish-stt |
mihuai/turkish-stt |
pip install "turkish-stt>=1,<2" |
| 0.1.1 | v1 — turkish-stt (first release) |
mihuai/turkish-stt |
pip install turkish-stt==0.1.1 |
Upgrading from 1.x / 0.1.1. The API is unchanged. Two things to know:
- Numbers are written as words. v2 transcribes what it hears — "yüz elli lira", "sıfır beş otuz iki…".
Pass
itn=Trueto get "150 TL", "0532 …" (v1 wrote some numbers as digits, but could garble long ones such as phone numbers). - v1 is still one argument away:
mihu_stt.transcribe(..., model="v1"),StreamingSTT(model="v1").quantized=False(fp32 encoder) is available for v1 only; v2 ships int8 weights.
License
mihu Community License — free for research, personal, and limited commercial use. See LICENSE
for the full terms. Weights are released under the same license on Hugging Face.
Türkçe
Türkçe için gerçek zamanlı, düşük gecikmeli konuşma tanıma (STT) — CPU'da.
Yalnızca Türkçe · streaming · CPU'da çalışır · uç cihazlara uygun. Sesli asistanlar, çağrı merkezleri ve GPU'nun olmadığı cihaz üstü yazıya dökme için 66 M parametreli küçük bir streaming model. API anahtarı, bulut veya GPU gerekmez.
- 🇹🇷 Türkçe odaklı — her parametre tek bir dile hizmet eder
- ⚡ Streaming — siz konuşurken ara sonuçlar (~320 ms)
- 🖥️ CPU'da çalışır — tek CPU thread'inde RTF 0.128 (gerçek zamandan ~8 kat hızlı)
- 🔌 Küçük — ~68 MB; Raspberry Pi sınıfı cihazlarda çalışır
- 🔢 Yazılı biçim —
itn=Trueile Damga "yüz elli lira"yı "150 TL" yapar
2.0.0 yeni modelle gelir:
turkish-stt-66m-v2— aynı boyut ve hızda v1'e göre yaklaşık %34 daha az kelime hatası. Bkz. Sürümler.
Kurulum
pip install turkish-stt # 2.0.0 — model v2
pip install "turkish-stt[itn]" # + Damga, yazılı biçimde çıktı için
pip install --upgrade turkish-stt # mevcut kullanıcılar: 2.0.0'a yükseltme
Kullanım
import mihu_stt
text = mihu_stt.transcribe("ses.wav") # "toplam yüz elli lira ödedim"
mihu_stt.transcribe("ses.wav", itn=True) # "toplam 150 TL ödedim"
for seg in mihu_stt.transcribe_segments("ses.wav", itn=True): # altyazı / zaman damgalı metin
print(seg["start"], seg["end"], seg["text"])
stt = mihu_stt.StreamingSTT(itn=True) # canlı akış (mikrofon, telefon hattı)
text, is_final = stt.accept_pcm16(pcm16, sample_rate=16000)
# is_final=True olduğunda cümle bitmiştir; itn=True ise bu son metin yazılı biçimdedir
Model ağırlıkları ilk kullanımda Hugging Face'ten
(mihuai/turkish-stt-66m-v2) otomatik indirilir ve
önbelleğe alınır.
Mikrofonla deneyin
pip install "turkish-stt[itn]" sounddevice
python examples/microphone.py --itn # biten cümleler yazılı biçimde (Damga)
python examples/microphone.py --list-devices # cihaz seçmek için: --device 1
✓ Telefon numaram 0532 123 45 67, toplam 150 TL ödedim.
Damga — yazılı biçimde çıktı
Damga (PyPI: damga), mihu'nun
açık kaynak, çevrimdışı ve deterministik Türkçe metin normalizasyon motorudur. Model duyduğunu yazar;
Damga bunu insanların yazdığı biçime çevirir: sayılar, tutarlar, tarihler, saatler, telefon numaraları.
GPU, ağ bağlantısı veya LLM gerekmez.
from damga import InverseNormalizer
itn = InverseNormalizer()
itn.normalize("yüz elli lira") # '150 TL'
itn.normalize("saat dokuz otuzda") # "saat 09:30'da"
itn.normalize("sıfır beş otuz iki yüz yirmi üç kırk beş altmış yedi") # '0532 123 45 67'
Metni bir insan okuyacaksa (altyazı, tutanak, CRM notu) kullanın. Metin doğrudan bir LLM'e gidiyorsa genellikle gerekmez; LLM "on yedi" ile "17"yi aynı anlar.
Doğruluk — FLEURS-TR (743 klip)
| Sistem | Sınıf | Parametre | WER % (standart) | WER % (Damga) |
|---|---|---|---|---|
| Whisper large-v3 | offline · GPU | 1.5 B | 7.82 | 4.48 |
| Whisper large-v3-turbo | offline · GPU | 0.8 B | 8.26 | 4.84 |
| turkish-stt 2.0.0 (v2) | streaming · CPU | 66 M | 10.06 | 6.21 |
| turkish-stt 0.1.1 (v1) | streaming · CPU | 66 M | 15.12 | 9.38 |
| Whisper small | offline · GPU | 244 M | 17.41 | 13.27 |
Standart = OpenAI Whisper BasicTextNormalizer (başka yayınlanmış sayılarla bu sütunu karşılaştırın).
Damga = Damga ile yazılı→sözlü normalizasyon + Türkçe'ye uygun küçük harf; "17" ile "on yedi"yi aynı kelime
sayar. Ayrıntılar ve yeniden üretme: model kartı.
Sürümler
| Paket | Model | Hugging Face | Kurulum |
|---|---|---|---|
| 2.0.0 (varsayılan) | v2 — turkish-stt-66m-v2 |
mihuai/turkish-stt-66m-v2 |
pip install turkish-stt |
| 1.0.0 | v1 — turkish-stt |
mihuai/turkish-stt |
pip install "turkish-stt>=1,<2" |
| 0.1.1 | v1 — turkish-stt (first release) |
mihuai/turkish-stt |
pip install turkish-stt==0.1.1 |
1.x / 0.1.1'den yükseltirken. API aynı kaldı. Bilmeniz gereken iki şey:
- Sayılar yazıyla gelir. v2 duyduğunu yazar: "yüz elli lira", "sıfır beş otuz iki…". "150 TL", "0532 …"
için
itn=Truekullanın (v1 bazı sayıları rakamla yazıyordu ama telefon numarası gibi uzun sayıları bozabiliyordu). - v1'e tek argümanla dönebilirsiniz:
mihu_stt.transcribe(..., model="v1"),StreamingSTT(model="v1").quantized=False(fp32 encoder) yalnızca v1 için geçerlidir; v2 int8 ağırlıklarla gelir.
Lisans
mihu Community License — araştırma, kişisel ve sınırlı ticari kullanım için ücretsiz. Tüm koşullar için
LICENSE. Ağırlıklar Hugging Face'te aynı lisansla yayınlanır.
Metadata
Release files for turkish-stt 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| turkish_stt-2.0.0.tar.gz | 18.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| turkish_stt-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.8 kB
Release files / turkish_stt-2.0.0.tar.gz
| Download URL | turkish_stt-2.0.0.tar.gz |
|---|---|
| Size | 18.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cd1f66dc2c216b60a012d2d6f85c7d99dacd8658dca019166556909f8aa0d987
|
|
BLAKE2b-256 checksum How to use checksums |
2497409d8ed2baf2de96fcf96ff9aa6157ebf79423dd017047b912fd534dc503
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / turkish_stt-2.0.0-py3-none-any.whl
| Download URL | turkish_stt-2.0.0-py3-none-any.whl |
|---|---|
| Size | 13.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8728ec177af1728c15662f0429fc1fe9e7c837f09706ba02f6345f6327b7917c
|
|
BLAKE2b-256 checksum How to use checksums |
631e4463aa398df97da1963d4a35ec50a8948a7cfe16de96ced95fee84094167
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for turkish-stt 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for turkish_stt-2.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.