Metadata-Version: 2.5
Name: tapra
Version: 0.1.4
Summary: Official Python SDK for the Tapra API: Tunisian code-switching transcription, speech, translation, and script conversion.
Project-URL: Homepage, https://www.tapra.tn
Project-URL: Documentation, https://www.tapra.tn/docs
License: Proprietary
Requires-Python: >=3.10
Requires-Dist: httpx>=0.21.2
Requires-Dist: pydantic>=1.9.2
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: aiohttp
Requires-Dist: aiohttp<4,>=3.10.0; extra == 'aiohttp'
Requires-Dist: httpx-aiohttp>=0.1.8; extra == 'aiohttp'
Provides-Extra: realtime
Requires-Dist: websockets>=13; extra == 'realtime'
Description-Content-Type: text/markdown

# Tapra Python SDK

Official Python client for the Tapra API: Tunisian Arabic / French / English code-switching
transcription, speech, translation, and Arabizi ↔ Arabic conversion.

```bash
pip install "tapra[realtime]"   # drop [realtime] if you only use the REST endpoints
```

```python
from tapra import Tapra

client = Tapra()  # https://api.tapra.tn; api_key defaults to TAPRA_API_KEY

with open("meeting.m4a", "rb") as audio:
    transcript = client.transcriptions.create(file=audio, timestamps="word")
print(transcript.text)

client.script.convert(text="3lech 7abit l9anoun?", direction="ZI2AR")
# Translations are currently offline (the endpoint returns an error until Tapra-Translate is back).
for event in client.translations.create_stream(input="عندي برشا خدمة", target="French"):
    print(event.type, event.delta)
```

Pass `base_url=` to target another host, such as a local model host.

Async: `AsyncTapra` has the same methods. Errors raise typed exceptions
(`PaymentRequiredError` for HTTP 402, `UnauthorizedError`, …) whose `.body.error` holds
`type` and `message`. Pass `idempotency_key=` to retry metered requests safely, and use
`client.<resource>.with_raw_response.<method>()` to read `x-tapra-cost-tnd`.

## Realtime transcription

```python
from tapra import connect_realtime

async with connect_realtime(language="ar-AR") as session:  # wss://api.tapra.tn
    for chunk in pcm_chunks:            # mono pcm_s16le, 16 kHz
        await session.send_audio(chunk)
    final = await session.stop()
print(final.text, final.usage)
```

## Prices

Tapra charges in TND. The SDK does not hardcode any price or dollar amount: it reads the
same live price list the website and the meter use.

```python
from tapra.pricing import fetch_tapra_prices, estimate_cost_tnd, estimate_cost_usd

prices = fetch_tapra_prices()  # GET https://www.tapra.tn/api/pricing, no key needed

estimate_cost_tnd(prices, "tts", 1200)  # 0.24 TND — 1,200 characters
estimate_cost_usd(prices, "tts", 1200)  # ≈ $0.08, at the rate the list was fetched with
```

`estimate_cost_micro_tnd` returns the exact integer amount the meter charges, including the
per-request minimum for text products. The endpoint also returns `tndPerUsd` and the date of
the published rate, so a UI can show which rate it used.

## Development

`src/tapra/` is generated by Fern from `openapi/tapra-api.json`; do not edit it by hand.
`src/tapra/realtime.py` and `src/tapra/pricing.py` are hand-written (kept by `.fernignore`).
Tests: `sdks/tests/python`.

## Command line

Installing the SDK also installs the `tapra` command (`pip install "tapra[realtime]"` adds `tapra stream`). Same commands as the npm package's:

```bash
tapra auth login                               # checks the key, then saves it
tapra transcribe call.mp3                      # Derja + French + English, speakers labelled
tapra transcribe video.mp4 --format srt -o subs.srt   # any audio/video; long files are split (needs ffmpeg)
tapra stream --partials                        # live from the microphone (ffmpeg), Ctrl+C to stop
tapra speak "حبيت نتلقاو demain" --voice amal -o hello.wav
tapra flip "3lech 7abit l9anoun?"               # -> علاش حبيت القانون؟
tapra translate "chnowa el jaw?" --to French
tapra balance                                  # also: models, voices, pricing, languages, health
```

In a terminal, paid commands show the estimated cost and your balance and ask first (`-y` skips, `--max-cost 0.5` sets a limit). They print the exact cost and balance on stderr when done; `--json` prints the full response and `--dry-run` shows the request without sending it. Exit codes: 0 ok, 1 error, 2 bad usage, 3 missing or invalid key, 4 balance too low. Full reference: https://www.tapra.tn/cli
