orukAll documentation ↗

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

FieldMeaning
model, releaseModel name and the serving release used for this request.
transcriptRecognized text.
labels31 label names in score order: 15 emotions and 16 speaking styles.
probabilities31 sigmoid scores aligned with labels. Several labels can apply at once; these scores do not sum to one.
logitsThe corresponding scores before the sigmoid transformation.
native_tdt_token_idsNative transcription token IDs, for exact-output comparisons.
timing_ms.totalCombined model execution time on the server.
timing_ms.requestOrigin request processing time, including upload, decoding, waiting, and model execution.
timing_ms.upload_decode_queueTime 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 lengthModel medianLocal HTTP medianLocal HTTP p95
0.25 s13.8 ms16.1 ms17.4 ms
0.5 s16.6 ms18.9 ms20.5 ms
1 s17.7 ms20.0 ms21.8 ms
2 s20.3 ms22.7 ms25.0 ms
4 s26.3 ms29.1 ms31.6 ms
8 s41.1 ms44.7 ms47.9 ms
16 s84.2 ms88.8 ms92.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

InputSupported value
Sample rate and channels16,000 Hz, mono.
Duration45 ms to 60 seconds.
Request bodyAt most 4 MiB, raw bytes. Multipart forms are not accepted.
audio/wavWAV or WAVEX, including PCM16 and float32 WAV.
audio/pcmSigned PCM16, little endian, without a WAV header.
audio/f32leFloat32 PCM, little endian, without a header. Samples must be finite; use the usual −1 to +1 audio range.
ConcurrencyOne 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

CodeAction
401Check the dedicated Spectra-2 bearer key.
403The edge rejected the client before inference. Send an identifying User-Agent, especially when using Python's urllib.
408The upload exceeded its 15-second origin deadline.
413Reduce the upload to 4 MiB or less.
415Use one of the supported raw audio content types, without HTTP content encoding.
422Check the sample rate, channels, duration, and waveform values.
429Capacity is occupied. Wait at least Retry-After seconds.
503The 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.

Download the OpenAPI schema