Metadata-Version: 2.4
Name: voicekit-client
Version: 0.4.0
Summary: Official Python SDK for VoiceKit (synthesis, transcription, analysis, moderation, batches).
Author: VoiceKit
License-Expression: MIT
Project-URL: Homepage, https://ttsapi.ru
Project-URL: Documentation, https://ttsapi.ru/docs
Project-URL: Repository, https://github.com/lomshakov/voicekit-python
Keywords: tts,speech,synthesis,transcription,stt,voice,russian
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24
Provides-Extra: streaming
Requires-Dist: websockets>=12.0; extra == "streaming"
Dynamic: license-file

# VoiceKit — Python SDK

[![PyPI version](https://img.shields.io/pypi/v/voicekit-client)](https://pypi.org/project/voicekit-client/)
[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://pypi.org/project/voicekit-client/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)

Official Python wrapper for **[VoiceKit](https://ttsapi.ru)** — the REST API for Russian speech:
neural speech synthesis (TTS), transcription (STT) with diarization and timestamps,
sentiment analysis, voice cloning, voice biometrics, audio effects and batch operations.

> **Links:** [Website](https://ttsapi.ru) · [Documentation](https://ttsapi.ru/docs) · [API reference](https://ttsapi.ru/swagger) · [Pricing](https://ttsapi.ru/pricing) · [Blog](https://ttsapi.ru/blog)

## Install

```bash
pip install voicekit-client
```

Streaming (WebSocket) requires an optional extra:

```bash
pip install "voicekit-client[streaming]"
```

## Quick start

```python
from voicekit import VoiceKitClient, b64

client = VoiceKitClient(api_key="YOUR_KEY")

# Synthesis → raw audio bytes
audio = client.synthesize("Привет! Это синтез русской речи.", voice="preset_anna", format="mp3")
with open("speech.mp3", "wb") as f:
    f.write(audio)

# Streaming (Pro/Business)
for chunk in client.synthesize_stream("Первое предложение. Второе."):
    pass  # write chunks to a file or socket

# Transcription (async → poll)
job = client.transcribe("audio.wav", keyterms=["диагноз"])
result = client.get_transcription_job(job["job_id"])
while result["status"] not in ("completed", "failed"):
    result = client.get_transcription_job(job["job_id"])

# Short-file sync transcription
transcript = client.transcribe_sync("audio.wav")

# Analysis (sentiment + keywords + entities)
analysis = client.analyze_sync("audio.wav")

# Text intelligence
lang = client.detect_language("Как дела?")
topics = client.topics("Нейросети и алгоритмы")
summary = client.summarize("Длинный текст для резюме.", max_sentences=3)
moderation = client.moderate("Это оскорбительное сообщение.")

# Batches
batch = client.batch_synthesize([
    {"text": "Первый текст", "voice": "preset_anna"},
    {"text": "Второй текст", "voice": "dmitri"},
])
status = client.get_batch(batch["batch_id"])

analysis_batch = client.batch_analyze([
    {"audio": b64("a.wav"), "language": "ru"},
    {"audio": b64("b.wav"), "language": "ru"},
])

# Voice cloning (Pro/Business)
clone = client.create_clone_voice(
    name="My voice",
    prompt_text="Точный текст образца.",
    samples="reference.wav",
)
print(client.list_clone_voices())
client.delete_clone_voice(clone["id"])

# VAD (speech segments)
segments = client.vad("audio.wav")

# Account
usage = client.usage()
balance = client.billing_balance()
```

### Audio effects (Pro/Business)

```python
# Inline during synthesis — the chain is applied to the synthesized audio
audio = client.synthesize(
    "Привет!",
    effects='[{"type":"reverb","room_size":0.5},{"type":"pitch","semitones":2}]',
)

# Async processing of an existing file
import time

job = client.apply_audio_effects("voice.mp3", [{"type": "compressor", "ratio": 3}])
while client.get_audio_effects_job(job["job_id"])["status"] not in ("completed", "failed"):
    time.sleep(1)
result = client.download_audio_effects(job["job_id"])
open("voice_fx.mp3", "wb").write(result)
```

### Audio cleaning (Pro/Business)

```python
# Denoise + normalize an existing file as a background job
import time

job = client.clean_audio("noisy.wav")            # one-click preset
# or with options:
# job = client.clean_audio("noisy.wav", options={"denoise": {"strength": 0.8}})

while client.get_audio_cleaning_job(job["job_id"])["status"] not in ("completed", "failed"):
    time.sleep(1)

clean = client.download_audio_cleaning(job["job_id"])
open("voice_clean.wav", "wb").write(clean)
```

### Search & Q&A (Pro/Business)

```python
# Hybrid semantic/full-text search over your recordings
hits = client.search("почему клиент отказался?", limit=5,
                     keywords="дорого", source="upload")
for h in hits["hits"]:
    print(h["score"], h["start"], h["text"])

# RAG question with verbatim citations
answer = client.ask("почему клиент отказался от Pro?")
print(answer["answer"])
for c in answer["citations"]:
    print(c["recording_id"], c["start"], c["quote"])
```

### WebSocket streaming (Pro/Business)

```python
import asyncio

async def main():
    client = VoiceKitClient(api_key="YOUR_KEY")

    stream = await client.transcribe_stream(language="ru", keyterms=["диагноз"])
    await stream.send_audio(pcm16_chunk_1)   # raw PCM16, 16 kHz mono
    await stream.send_audio(pcm16_chunk_2)
    await stream.stop()                       # finalize the utterance
    async for event in stream:                # session / vad / partial / final / error
        print(event["type"], event)
    await stream.close()

    vad = await client.vad_stream()           # VAD events only (speech_started/ended)
    await vad.send_audio(pcm16_chunk)
    await vad.stop()
    async for event in vad:
        print(event["type"], event)
    await vad.close()

asyncio.run(main())
```

### Voice ID (Pro/Business)

```python
# Voice passport: language, gender, age, emotion, speaker embedding, AI-vs-human
passport = client.voice_id("recording.wav")

# Voice biometrics on your own profiles
profile = client.enroll_voice("speaker.wav", name="Alice")    # → {"profile_id": "voice_…"}

check = client.verify_voice("check.wav", profile["profile_id"])
# → {"profile_id": "voice_…", "similarity": 0.81, "verified": true, "threshold": 0.7}

match = client.identify_voice("check.wav")                    # 1:N across your profiles
# → {"best_match": {…}, "matches": […], "threshold": 0.7}

profiles = client.list_voice_profiles()
client.delete_voice_profile(profile["profile_id"])
```

### Recordings, QA & meeting intelligence (Pro/Business)

```python
# Recordings library (list / link channel / speakers)
recordings = client.list_recordings(limit=10)
job = client.recording_from_link("https://example.com/call.mp3")   # Link channel
speakers = client.recording_speakers(recording_id)
client.update_speaker(recording_id, "SPEAKER_00", display_name="Alice", role="operator")

# Call QA
qa = client.qa_evaluate(recording_id, [{"id": "greeting", "kind": "required", "description": "..."}])
trend = client.qa_analytics(days=30)
csv = client.qa_export(format="csv")

# Meeting protocol
protocol = client.meeting_protocol(recording_id, template="standup")

# Translation & speech evaluation
translated = client.translate_transcript(job_id, target_language="en")
wer = client.evaluate("audio.wav", reference="Ожидаемый текст")
```

## Examples

Runnable scripts live in [`examples/`](./examples): synthesis, streaming, transcription,
analysis, voice cloning and batches. Each script reads the `VOICEKIT_API_KEY`
environment variable.

## Configuration

| Option | Default | Description |
| --- | --- | --- |
| `api_key` | — | API key (required) |
| `base_url` | `https://ttsapi.ru` | API base URL (e.g. `http://localhost:5080` for local dev) |
| `timeout` | `120.0` | Per-request timeout in seconds |

Errors raise `VoiceKitError` with `.status` (HTTP status), `.code` (machine-readable
code) and `.message`.

## Documentation

Full API reference and guides: **[ttsapi.ru/docs](https://ttsapi.ru/docs)**.

## License

[MIT](./LICENSE)
