Skip to content

Python tutorial

Detect emotion from audio in Python

Five minutes from pip install to calibrated emotion scores: no GPU, no model download, no thresholds to tune. This tutorial uses the oruk Speech API, which returns 15 multilabel emotion scores calibrated on held-out audio.

The steps

  1. 01

    Install the SDK. Run pip install oruk. The package is on PyPI and supports Python 3.9+. Alternatively use plain requests — the API is standard multipart REST.

  2. 02

    Get an API key. Create an account at oruk.ai/auth/signup (new accounts include $5 in trial credit, no card required) and create a key in the developer portal. Export it as ORUK_API_KEY.

  3. 03

    Send an audio file. Call client.audio.emotions with a prerecorded English audio file (WAV, FLAC, MP3, M4A, OGG, or WebM; up to 30 MB / 60 minutes).

  4. 04

    Read the calibrated labels. The response scores 15 emotion labels against thresholds calibrated on held-out audio. Labels crossing their threshold are selected; a clip can carry several at once.

  5. 05

    Use segments for long audio. Files longer than one model context include time-local segments, so you can see where in a call frustration rose instead of one average score.

With the SDK

# pip install oruk
import os
from oruk import Oruk

client = Oruk(api_key=os.environ["ORUK_API_KEY"])

with open("call.wav", "rb") as audio:
    result = client.audio.emotions(file=audio, model="oruk-spectra-1")

for emotion in result.emotions:
    print(f"{emotion.label}: {emotion.score:.2f}")
# frustrated: 0.83
# worried: 0.61

print(result.usage.audio_seconds, "seconds analyzed")

Without the SDK

The API is plain multipart REST, so requests works fine:

# No SDK — plain requests
import os, requests

with open("call.wav", "rb") as audio:
    r = requests.post(
        "https://speech-api.oruk.ai/v1/audio/emotions",
        headers={"Authorization": f"Bearer {os.environ['ORUK_API_KEY']}"},
        files={"file": ("call.wav", audio, "audio/wav")},
        data={"model": "oruk-spectra-1"},
        timeout=120,
    )
r.raise_for_status()

for e in r.json()["emotions"]:
    print(e["label"], round(e["score"], 2))

Long audio: transcript + segments

For calls and meetings, request unified analysis instead — one call returns the transcript, emotion, speaking style, and per-span segments:

# Long files: iterate time-local segments
with open("meeting.mp3", "rb") as audio:
    result = client.audio.analysis(file=audio, model="oruk-resonance")

print(result.text)  # full transcript

for seg in result.segments:
    labels = ", ".join(l.label for l in seg.emotions)
    print(f"{seg.start:>7.1f}s–{seg.end:>7.1f}s  {labels}")

Scope, stated plainly

API v1 analyzes prerecorded English audio files — no streaming endpoint, no multilingual support, no intent detection. Outputs are calibrated acoustic annotations of how speech sounds, not facts about a speaker’s inner state; don’t make consequential decisions from them alone. Details: capabilities and responsible use.

FAQ

Do I need a GPU or a model download?
No. Inference runs on oruk’s servers; the Python side is one HTTP request. If you would rather self-host, open models like emotion2vec+ exist — expect to own GPU serving and calibration yourself.
How much does it cost?
Emotion requests on Spectra 1 cost $0.0060 per audio minute (pricing version 2026-07-11), metered per measured second with a one-second minimum. A 5-minute call costs about 3 cents. New accounts include $5 in trial credit.
What accuracy should I expect?
On speech-emotion-bench (64,384 held-out clips, 7 classes, one identical pipeline for 64 systems), oruk Spectra measured 77.6% accuracy — with the stated caveat that the oruk entry is trained in-distribution. Full results are downloadable from the benchmarks page.
Can I get the transcript and emotion in one call?
Yes — use client.audio.analysis (POST /v1/audio/analysis). It returns the English transcript, emotion labels, speaking-style labels, time-local segments, and a tagged transcript from a single request.
Does it work on live microphone streams?
API v1 is file-based: record the audio first (or chunk it), then send files. There is no streaming endpoint. In-browser chunked capture is how the live demo at oruk.ai/tools/voice-emotion-analyzer works.

Full API reference SDK docs Try it live in the browser