Metadata-Version: 2.4
Name: transcribe-api
Version: 0.1.5
Summary: Official Python SDK for Transcribe API.
Author-email: Transcribe API <admin@transcribeapi.com>
License-Expression: MIT
Project-URL: Homepage, https://transcribeapi.com
Keywords: transcription,speech-to-text,whisper,audio,api
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31.0

# Transcribe API Python SDK

Official Python SDK for Transcribe API.

Use this SDK to send one file, many files, local uploads, remote audio URLs, webhook jobs, and large multipart uploads to the Transcribe API from Python.

## Installation

```bash
pip install transcribe-api
```

## Import

```python
from transcribe_api import TranscribeAPI, TranscribeAPIError
```

## Quick start

```python
import os
from transcribe_api import TranscribeAPI

client = TranscribeAPI(
    apiKey=os.environ["TRANSCRIBE_API_KEY"],
    polling={
        "interval": 10,
        "timeout": 15 * 60,
    },
)

result = client.transcribe(
    language="en",
    files=[
        {"reference_id": "meeting_001", "file": "./meeting.mp3"},
    ],
)

print(result)
```

`client.transcribe(files=[...])` is the main API for both single-file and multi-file transcription.

> Important: the current SDK uses camelCase option names such as `apiKey`, `baseUrl`, `uploadConcurrency`, `showLogs`, and `webhookUrl`. It does not use `api_key`, `base_url`, `upload_concurrency`, or `client.batch.transcribe(...)`.

## How `transcribe` routes work

The SDK automatically chooses the right API flow:

- One small local file is sent through the direct synchronous upload path.
- Remote URLs, webhook jobs, multiple files, files larger than 30 MB, and files estimated over 10 minutes are sent through the async job flow.
- Large local async uploads use signed R2 upload URLs returned by the API.
- Multipart upload is used automatically when the backend returns multipart upload instructions.
- If `polling` is configured, async calls wait until the job reaches a terminal status.
- If `polling` is not configured, async calls return the upload-completion/job response. Use `client.jobs.get(job_id)` or `client.waitForJobCompletion(job_id, ...)` to check later.

Terminal job statuses are `completed`, `failed`, and `insufficient_funds`. Completed job responses include `result_url` when the API has a result file ready.

## Client options

```python
client = TranscribeAPI(
    apiKey="YOUR_API_KEY",
    baseUrl="https://api.transcribeapi.com/v1",
    uploadConcurrency=4,
    showLogs=True,
    logger=print,
    polling={
        "interval": 10,
        "timeout": 15 * 60,
    },
)
```

| Option | Description |
| --- | --- |
| `apiKey` | Required. Your Transcribe API key. |
| `baseUrl` | Optional. Defaults to `https://api.transcribeapi.com/v1`. |
| `uploadConcurrency` | Optional. Number of in-flight upload PUTs. Defaults to `1` and is capped at `32`. |
| `showLogs` | Optional. Prints upload progress, upload completion, polling status, and final result info. |
| `logger` | Optional. Callable or logger-like object. Defaults to `print`. |
| `polling` | Optional. `{"interval": 10, "timeout": 900}` in seconds. `interval` must be at least `10`. Omit or set to `None`/`False` to disable automatic polling. |

## File inputs

Each item in `files` must be a dictionary with either `file` or `url`:

```python
{"reference_id": "episode_1", "file": "./episode.mp3"}
{"reference_id": "episode_2", "url": "https://example.com/signed-audio-url.mp3"}
```

Supported local/upload inputs:

- Local path strings, such as `"./audio.mp3"`.
- `pathlib.Path` objects.
- `bytes` or `bytearray`.
- File-like objects with a `.read()` method.

Supported remote inputs:

- Public or signed URLs using `{"url": "https://..."}`.

Do not include both `file` and `url` in the same item.

Local path inputs are streamed from disk. `bytes`, `bytearray`, and file-like inputs are read into memory by the SDK.

## Single local file

```python
result = client.transcribe(
    files=[
        {"reference_id": "call_001", "file": "./call.mp3"},
    ],
    language="en",
)
```

For one small local file, this usually uses the direct upload path. Larger files automatically become async jobs.

## File-like objects and bytes

```python
with open("./meeting.wav", "rb") as audio:
    result = client.transcribe(
        files=[
            {"reference_id": "meeting", "file": audio},
        ],
        language="en",
    )
```

```python
audio_bytes = Path("./clip.mp3").read_bytes()

result = client.transcribe(
    files=[
        {"reference_id": "clip", "file": audio_bytes},
    ],
)
```

When the SDK receives raw bytes, it uses the fallback filename `audio.mp3`. For best content-type detection, prefer passing a path or file-like object with a useful `.name`.

## Remote URL transcription

```python
job = client.transcribe(
    files=[
        {"reference_id": "remote_001", "url": "https://example.com/audio.mp3"},
    ],
    language="en",
)
```

Remote URL jobs are async because the API fetches the audio from the URL.

## Batch and mixed input transcription

```python
job = client.transcribe(
    language="en",
    uploadConcurrency=8,
    files=[
        {"reference_id": "episode_1", "file": "./episode-1.mp3"},
        {"reference_id": "episode_2", "file": "./episode-2.wav"},
        {"reference_id": "episode_3", "url": "https://example.com/episode-3.m4a"},
    ],
)
```

Local files and remote URLs can be mixed in the same batch. Provide a unique `reference_id` for every item so uploads and results can be matched reliably.

## Per-file language

Set `language` at the top level to apply a default to the whole job. Set `language` on a file item to override the default for that file.

```python
job = client.transcribe(
    language="en",
    files=[
        {"reference_id": "intro", "file": "./intro.mp3"},
        {"reference_id": "french_segment", "file": "./segment.m4a", "language": "fr"},
    ],
)
```

`language` must be a two-letter language code such as `en`, `fr`, or `es`. Omit it, pass an empty value, or pass `"auto"` to avoid sending an explicit language.

## Excluding outputs or features

Use `exclude` to pass API exclusions. Lists are joined with commas before sending. Valid values are only `vtt`, `segments`, `metadata`, `billing`, and `detected_language`.

```python
result = client.transcribe(
    files=[
        {"reference_id": "meeting", "file": "./meeting.mp3"},
    ],
    exclude=["vtt", "segments"],
)
```

You can also pass a comma-separated string:

```python
exclude="metadata,billing"
```

## Webhooks

```python
job = client.transcribe(
    webhookUrl="https://example.com/transcribe-webhook",
    files=[
        {"reference_id": "upload_001", "file": "./long-audio.mp3"},
    ],
)
```

Any request with `webhookUrl` uses the async job flow.

## Progress and logs

Use `onProgress` to receive structured progress events:

```python
def on_progress(event):
    print(event)

job = client.transcribe(
    files=[
        {"reference_id": "episode_1", "file": "./episode-1.mp3"},
        {"reference_id": "episode_2", "file": "./episode-2.mp3"},
    ],
    uploadConcurrency=4,
    onProgress=on_progress,
)
```

Common event names:

- `upload_urls_received`
- `upload_started`
- `upload_progress`
- `upload_completed`

Progress events may include `jobId`, `jobStatus`, `referenceId`, `loaded`, `total`, `fileLoaded`, `fileTotal`, `batchLoaded`, `batchTotal`, `uploadType`, `partNumber`, `totalParts`, and `multipartConcurrency`.

Set `showLogs=True` on the client or on a single call to print built-in progress and polling logs:

```python
client = TranscribeAPI(
    apiKey=os.environ["TRANSCRIBE_API_KEY"],
    showLogs=True,
)
```

## Manual async jobs

`transcribe` uploads automatically. Use `createBatchJob` when you want to separate job creation from upload.

```python
job = client.createBatchJob(
    language="en",
    files=[
        {"reference_id": "part_1", "file": "./part-1.mp3"},
        {"reference_id": "part_2", "url": "https://example.com/part-2.mp3"},
    ],
)

print(job.jobId)

completion = job.upload()
print(completion)
```

For a single large local file, you can also use `createBigFileJob`:

```python
job = client.createBigFileJob(
    file={"reference_id": "large_001", "file": "./large.wav"},
)

completion = job.upload()
```

## Job helpers

```python
job = client.jobs.get("job_id_here")
same_job = client.jobs.result("job_id_here")

final_job = client.waitForJobCompletion(
    "job_id_here",
    polling={"interval": 10, "timeout": 15 * 60},
)
```

Available job helpers:

| Method | Description |
| --- | --- |
| `client.jobs.get(jobId)` | Fetches `GET /v1/transcribe/{job_id}`. |
| `client.jobs.result(jobId)` | Alias for `jobs.get`. |
| `client.jobs.uploadCompleted(jobId)` | Calls `POST /v1/transcribe/{job_id}/upload-completed`. |
| `client.jobs.complete(jobId)` | Alias for `jobs.uploadCompleted`. |
| `client.jobs.createBatch(options)` | Creates a batch job and returns a `BatchJob`. |
| `client.jobs.createBigFile(options)` | Creates a one-file async upload job and returns a `BatchJob`. |
| `client.waitForJobCompletion(jobId, options)` | Polls until a terminal job status or timeout. |

## Direct upload method

Most applications should use `client.transcribe(files=[...])`. If you specifically need to force the direct upload endpoint for one file, use `transcribeDirect`:

```python
result = client.transcribeDirect(
    file="./short.mp3",
    referenceId="short_001",
    language="en",
)
```

## Limits and validation

- Batch jobs support up to `10,000` files.
- Batch local upload payloads support up to `10 GB` total local file size.
- Direct sync routing is used only for one local file up to `30 MB` and about `10 minutes`.
- Multipart upload starts when the backend returns multipart upload instructions. The SDK sends `size_bytes` for local files at least `128 MB` so the backend can choose multipart.
- `uploadConcurrency` defaults to `1` and is capped at `32`.
- `polling["interval"]` must be at least `10` seconds.
- Batch local uploads support `mp3`, `mpeg`, `mpga`, `m4a`, `wav`, and `webm`.
- `.mp4` is not supported.

## Error handling

```python
try:
    result = client.transcribe(
        files=[
            {"reference_id": "bad_file", "file": "./missing.mp3"},
        ],
    )
    print(result)
except TranscribeAPIError as error:
    print(str(error))
    print(error.code)
    print(error.status)
    print(error.response)
    print(error.to_json())
```

`TranscribeAPIError` includes `message`, `code`, `status`, `response`, and any extra fields returned by the API or generated by the SDK.

## CLI

The package exposes a small CLI entrypoint:

```bash
transcribe-api --version
```

At the moment, the CLI only prints the package version or a basic placeholder message. Use the Python SDK for transcription work.
