Metadata-Version: 2.4
Name: turkish-stt
Version: 2.0.0
Summary: Real-time, low-latency Turkish speech-to-text (STT) that runs on the CPU.
Author: mihu · Speech Systems
Maintainer-email: Deniz Gökdünek <deniz@mihu.ai>
License: mihu Community License
        Version 1.0
        
        These terms govern all use of the turkish-stt and turkish-stt-66m-v2 materials released by mihu
        ("mihu", "Licensor"). By downloading, accessing, or otherwise using the Materials, you
        ("Licensee") accept and agree to be bound by this License.
        
        1. DEFINITIONS
           1.1 "Materials" — the turkish-stt and turkish-stt-66m-v2 model weights, model card, and any
               accompanying code, documentation, or related artifacts released under this License.
           1.2 "Outputs" — anything produced by running the Materials.
           1.3 "Derivative" — any work created from, adapted from, or built upon the Materials.
           1.4 "Annual Revenue" — the combined worldwide gross revenue of Licensee together with
               its affiliates over the preceding twelve months.
        
        2. COMMUNITY GRANT
           Provided Licensee's Annual Revenue stays below USD 500,000, and subject to every term
           below, Licensor grants Licensee a worldwide, non-exclusive, non-transferable,
           royalty-free, no-cost right to use, reproduce, and make Derivatives of the Materials.
           This covers, without limitation:
             (a) research and academic work;
             (b) personal and other non-commercial use;
             (c) commercial use within the revenue limit above, once any commercial-use
                 registration that Licensor requires has been completed.
        
        3. ABOVE THE THRESHOLD
           Once Licensee's Annual Revenue reaches USD 500,000 or more, no use is permitted under
           the Community Grant. Licensee must first secure a separate commercial agreement from
           mihu. Write to support@mihu.ai to arrange terms.
        
        4. ATTRIBUTION
           Licensee shall (a) keep this License intact, together with any copyright or attribution
           notices, in a "NOTICE" file shipped alongside the Materials or any Derivative, and
           (b) show "Powered by mihu" clearly in any product, service, interface, or documentation
           that builds on the Materials or their Outputs.
        
        5. RESTRICTIONS
           Licensee shall not:
             (a) use the Materials or Outputs to train, build, or refine any competing speech,
                 foundational, or general-purpose AI model;
             (b) strip, hide, or modify any attribution or proprietary notice;
             (c) use the mihu name, logo, or marks beyond the attribution required in Section 4
                 (no trademark rights are granted here);
             (d) use the Materials unlawfully or contrary to any Acceptable Use Policy that
                 Licensor may publish;
             (e) sublicense, sell, or redistribute the Materials except where this License
                 expressly allows it.
        
        6. OWNERSHIP
           Between the parties, Licensor keeps all right, title, and interest in the Materials.
           Licensee holds the Derivatives it lawfully makes and the Outputs it generates, always
           subject to Licensor's rights in the underlying Materials. Nothing beyond the rights
           stated here is granted, by implication or otherwise.
        
        7. NO WARRANTY
           THE MATERIALS ARE SUPPLIED "AS IS", WITH NO WARRANTY OF ANY KIND, WHETHER EXPRESS OR
           IMPLIED, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
           PURPOSE, OR NON-INFRINGEMENT.
        
        8. LIMITATION OF LIABILITY
           TO THE FULLEST EXTENT THE LAW ALLOWS, LICENSOR IS NOT LIABLE FOR ANY INDIRECT,
           INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES CONNECTED TO THE MATERIALS OR
           THIS LICENSE.
        
        9. TERMINATION
           This License ends automatically if (a) Licensee's Annual Revenue reaches or passes
           USD 500,000 without a commercial agreement in place, (b) Licensee breaches any term, or
           (c) Licensee brings litigation or a patent claim against Licensor over the Materials.
           On termination, Licensee must stop all use and delete every copy of the Materials. To
           keep using them, arrange a commercial agreement via support@mihu.ai.
        
        10. GENERAL
           This License is the complete agreement covering the Materials. It is governed by the
           laws of Licensor's principal place of business, disregarding conflict-of-law rules.
        
        © mihu. All rights reserved.
        
        turkish-stt, turkish-stt-66m-v2 and the mihu Community License are provided by Hunters AI, operating
        under the mihu brand. "mihu" is a trademark of Hunters AI.
        
Project-URL: Model weights, https://huggingface.co/mihuai/turkish-stt-66m-v2
Project-URL: Model weights (v1), https://huggingface.co/mihuai/turkish-stt
Project-URL: Damga (Turkish ITN), https://github.com/mihu-ai/damga
Keywords: speech-recognition,asr,streaming,turkish,on-device,cpu,voice-agent
Classifier: Programming Language :: Python :: 3
Classifier: License :: Other/Proprietary License
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sherpa-onnx
Requires-Dist: numpy
Requires-Dist: soundfile
Requires-Dist: soxr
Requires-Dist: huggingface_hub
Provides-Extra: itn
Requires-Dist: damga; extra == "itn"
Provides-Extra: eval
Requires-Dist: jiwer; extra == "eval"
Requires-Dist: num2words; extra == "eval"
Requires-Dist: damga; extra == "eval"
Dynamic: license-file

# turkish-stt

[🇹🇷 Türkçe](#türkçe) · [Model (v2)](https://huggingface.co/mihuai/turkish-stt-66m-v2) · [Damga (Turkish ITN)](https://github.com/mihu-ai/damga) · [PyPI](https://pypi.org/project/turkish-stt/)

**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=True` turns "yüz elli lira" into "150 TL" via [Damga](https://github.com/mihu-ai/damga)

> **2.0.0** ships the new model, [`turkish-stt-66m-v2`](https://huggingface.co/mihuai/turkish-stt-66m-v2):
> **~34% fewer word errors** than v1 at the same size and speed. See [Versions](#versions).

## Installation

```bash
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

```python
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:

```python
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`](https://huggingface.co/mihuai/turkish-stt-66m-v2)) the first time and are cached.

## Try it on your microphone

[`examples/microphone.py`](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:

```bash
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`](examples/export_transcript.py) turns any audio file into a plain-text
transcript or timed subtitles — the format follows the output extension:

```bash
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/`](examples)):

**LiveKit Agents** — [`examples/livekit_stt.py`](examples/livekit_stt.py):
```python
from livekit.agents import AgentSession
from livekit_stt import MihuSTT
session = AgentSession(stt=MihuSTT(), llm=..., tts=...)
```

**Pipecat** — [`examples/pipecat_stt.py`](examples/pipecat_stt.py):
```python
from pipecat_stt import MihuSTTService
pipeline = Pipeline([transport.input(), vad, MihuSTTService(), llm, tts, transport.output()])
```

## Damga — written-form output

[**Damga**](https://github.com/mihu-ai/damga) ([PyPI: `damga`](https://pypi.org/project/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:

```python
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](https://huggingface.co/mihuai/turkish-stt-66m-v2).

| 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/`](eval) — including the text (n-gram) and acoustic
(chromaprint) contamination audits.

```bash
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`](https://huggingface.co/mihuai/turkish-stt-66m-v2) | `pip install turkish-stt` |
| 1.0.0 | v1 — `turkish-stt` | [`mihuai/turkish-stt`](https://huggingface.co/mihuai/turkish-stt) | `pip install "turkish-stt>=1,<2"` |
| 0.1.1 | v1 — `turkish-stt` (first release) | [`mihuai/turkish-stt`](https://huggingface.co/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=True` to 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`](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=True` ile [Damga](https://github.com/mihu-ai/damga) "yüz elli lira"yı "150 TL" yapar

> **2.0.0** yeni modelle gelir: [`turkish-stt-66m-v2`](https://huggingface.co/mihuai/turkish-stt-66m-v2) —
> aynı boyut ve hızda v1'e göre **yaklaşık %34 daha az kelime hatası**. Bkz. [Sürümler](#sürümler).

### Kurulum

```bash
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

```python
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`](https://huggingface.co/mihuai/turkish-stt-66m-v2)) otomatik indirilir ve
önbelleğe alınır.

### Mikrofonla deneyin

```bash
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**](https://github.com/mihu-ai/damga) ([PyPI: `damga`](https://pypi.org/project/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.

```python
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ı](https://huggingface.co/mihuai/turkish-stt-66m-v2).

### Sürümler

| Paket | Model | Hugging Face | Kurulum |
|---|---|---|---|
| **2.0.0** (varsayılan) | **v2** — `turkish-stt-66m-v2` | [`mihuai/turkish-stt-66m-v2`](https://huggingface.co/mihuai/turkish-stt-66m-v2) | `pip install turkish-stt` |
| 1.0.0 | v1 — `turkish-stt` | [`mihuai/turkish-stt`](https://huggingface.co/mihuai/turkish-stt) | `pip install "turkish-stt>=1,<2"` |
| 0.1.1 | v1 — `turkish-stt` (first release) | [`mihuai/turkish-stt`](https://huggingface.co/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=True` kullanı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`](LICENSE). Ağırlıklar Hugging Face'te aynı lisansla yayınlanır.
