Spectra-2 · Hosted API
Words, emotion,
and delivery. One call.
Spectra-2 transcribes speech and returns 31 independent emotion and speaking-style scores. The hosted L4 service runs all three tasks together.
Base URL: https://spectra-2-api.oruk.ai
Use a dedicated Spectra-2 service key supplied by Oruk. Keep it on your application server. Organization keys for speech-api.oruk.ai use a separate service and do not authenticate here. Request access.
Send a recording
Send the audio bytes directly in the request body. Use a mono, 16 kHz WAV recording. Every successful request returns a transcript and all 31 scores.
curl --fail-with-body https://spectra-2-api.oruk.ai/v1/audio/analysis \
-H "Authorization: Bearer $SPECTRA2_API_KEY" \
-H "Content-Type: audio/wav" \
--data-binary @audio.wav
If your recording has another sample rate or channel count, convert it first:
ffmpeg -i recording.mp3 -ar 16000 -ac 1 -c:a pcm_s16le audio.wav
Python
Reuse a session across requests to avoid repeating the connection setup.
import os
from pathlib import Path
import requests
with requests.Session() as session:
response = session.post(
"https://spectra-2-api.oruk.ai/v1/audio/analysis",
headers={
"Authorization": "Bearer " + os.environ["SPECTRA2_API_KEY"],
"Content-Type": "audio/wav",
"User-Agent": "my-app/1.0 (spectra-2)",
},
data=Path("audio.wav").read_bytes(),
timeout=(5, 50),
)
response.raise_for_status()
result = response.json()
print(result["transcript"])
scores = dict(zip(result["labels"], result["probabilities"]))
print(sorted(scores.items(), key=lambda item: item[1], reverse=True))
Read the result
| Field | Meaning |
|---|---|
model, release | Model name and the serving release used for this request. |
transcript | Recognized text. |
labels | 31 label names in score order: 15 emotions and 16 speaking styles. |
probabilities | 31 sigmoid scores aligned with labels. Several labels can apply at once; these scores do not sum to one. |
logits | The corresponding scores before the sigmoid transformation. |
native_tdt_token_ids | Native transcription token IDs, for exact-output comparisons. |
timing_ms.total | Combined model execution time on the server. |
timing_ms.request | Origin request processing time, including upload, decoding, waiting, and model execution. |
timing_ms.upload_decode_queue | Time before model execution begins at the origin. |
Use each label's score independently. A threshold of 0.5 is a starting point for a binary decision; choose thresholds for your application and evaluation data.
Keep latency low
The service uses batch size one, FP16 TensorRT inference, CUDA graphs, prepared caches, and one GPU execution thread. It starts with the model loaded and warm. It uses the original audio length without padding or cropping the recording.
Keep an HTTP connection open, upload binary mono 16 kHz audio, and place your application near us-central1. Requests return complete results; this endpoint does not send incremental transcript events.
Measured on the hosted L4
| Audio length | Model median | Local HTTP median | Local HTTP p95 |
|---|---|---|---|
| 0.25 s | 13.8 ms | 16.1 ms | 17.4 ms |
| 0.5 s | 16.6 ms | 18.9 ms | 20.5 ms |
| 1 s | 17.7 ms | 20.0 ms | 21.8 ms |
| 2 s | 20.3 ms | 22.7 ms | 25.0 ms |
| 4 s | 26.3 ms | 29.1 ms | 31.6 ms |
| 8 s | 41.1 ms | 44.7 ms | 47.9 ms |
| 16 s | 84.2 ms | 88.8 ms | 92.0 ms |
Warm batch-one requests, 60 calls per length across three speech windows, measured on September 26, 2026. Local HTTP includes request handling on the GPU host, without the internet round trip. Full regression: 1,557 identical transcription token sequences and exact logits on all 695 examples with saved label references.
On one persistent HTTPS connection from a California client, the median round trip was 211 ms for a one-second speech clip and 297 ms for a 4.05-second clip (30 requests each). These numbers include the network path and vary by client location and connection.
The JSON timings and Server-Timing response header describe server work. Measure elapsed time on your client for upload, routing, and the return trip as well.
Inputs and capacity
| Input | Supported value |
|---|---|
| Sample rate and channels | 16,000 Hz, mono. |
| Duration | 45 ms to 60 seconds. |
| Request body | At most 4 MiB, raw bytes. Multipart forms are not accepted. |
audio/wav | WAV or WAVEX, including PCM16 and float32 WAV. |
audio/pcm | Signed PCM16, little endian, without a WAV header. |
audio/f32le | Float32 PCM, little endian, without a header. Samples must be finite; use the usual −1 to +1 audio range. |
| Concurrency | One active request and one waiting request. Queue wait is limited to 250 ms. |
Send requests serially for the lowest latency. Under load, the service returns 429 rather than growing the queue. Honor Retry-After and add jitter when retrying. This deployment runs on one L4; a worker restart requires model warmup.
Status and errors
| Code | Action |
|---|---|
| 401 | Check the dedicated Spectra-2 bearer key. |
| 403 | The edge rejected the client before inference. Send an identifying User-Agent, especially when using Python's urllib. |
| 408 | The upload exceeded its 15-second origin deadline. |
| 413 | Reduce the upload to 4 MiB or less. |
| 415 | Use one of the supported raw audio content types, without HTTP content encoding. |
| 422 | Check the sample rate, channels, duration, and waveform values. |
| 429 | Capacity is occupied. Wait at least Retry-After seconds. |
| 503 | The worker or private connection is unavailable. Retry with backoff. |
GET /readyz returns {"ready":true} when the worker can accept requests. GET /healthz checks the origin process. GET /v1/models requires your service key and returns the deployed model's capabilities.
Transport and data
Requests use HTTPS and an encrypted private connection to the GPU host. Audio is decoded in memory. The serving application does not store or log audio, transcripts, or label outputs, and responses use Cache-Control: no-store.