Python SDK for Valence AI Emotion Detection API - Real-time, Async, and Streaming Support
Project description
Valence SDK for Emotion Detection
valenceai is a Python client library for interacting with the Valence AI APIs for emotion detection. It provides a convenient interface to upload audio files, stream real-time audio, and retrieve detected emotional states.
Features
- Discrete audio processing - Real-time analysis for short audio clips (4-10s)
- Asynch audio processing - Multipart parallel upload for long audio files with temporal emotion analysis
- Streaming API - Real-time WebSocket streaming for live audio
- Rate limiting - Monitor API usage and limits
- Environment configuration - Built-in support for environment variables
- Enhanced logging - Configurable log levels
The emotional classification model used in our APIs is optimized for North American English conversational data. The model detects four emotions: angry, happy, neutral, and sad.
API Overview
| API | Best For | Input | Output |
|---|---|---|---|
| Discrete | Real-time analysis | Short audio (4.5-10s) | Single emotion prediction |
| Asynch | Pre-recorded files | Long audio (up to 1GB) | Timeline with emotion changes |
| Streaming | Live audio streams | Audio chunks via WebSocket | Real-time emotion updates |
The DiscreteAPI is built for real-time analysis of emotions in audio data. Small snippets of audio are sent to the API to receive feedback in real-time of what emotions are detected based on tone of voice. This API operates on an approximate per-sentence basis, and audio must be cut to the appropriate size.
The AsynchAPI is built for emotion analysis of pre-recorded audio files. Files of any length, up to 1 GB in size, can be sent to the API to receive a timeline of emotions throughout the file.
The StreamingAPI is built for real-time audio analysis via WebSocket connections. The audio stream is analyzed in real-time and emotions are returned in reference to 5-second chunks of streamed audio.
Audio Input Requirements
Format Specifications
- Format: WAV only
- Recommended sampling rate: 44.1 kHz (44100 Hz)
- Minimum sampling rate: 8 kHz
- Channel: Mono (single channel)
API-Specific Requirements
- Discrete API: 4-10 seconds per file
- Asynch API: Minimum 5 seconds, maximum 1 GB
- Streaming API: Real-time audio chunks (PCM bytes)
For inquiries about custom microphone specifications or stereo/multi-channel support, please contact us.
Installation
pip install valenceai
Configuration
You can configure the SDK using environment variables or by passing parameters directly:
Environment Variables
export VALENCE_API_KEY="api_key_here"
export VALENCE_API_BASE_URL="https://api.getvalenceai.com" # Optional
export VALENCE_WEBSOCKET_URL="wss://api.getvalenceai.com" # Optional
export VALENCE_LOG_LEVEL="INFO" # Optional: INFO, DEBUG, ERROR
Client Configuration
client = ValenceClient(
api_key="your_api_key", # API key (required)
base_url="https://custom.api", # Custom API endpoint (optional)
websocket_url="wss://custom.api", # Custom WebSocket endpoint (optional)
part_size=5*1024*1024, # Upload chunk size (default: 5MB)
show_progress=True, # Show upload progress (default: True)
max_threads=3, # Concurrent upload threads (default: 3)
comprehensive_output=False # When False: returns timestamp, main_emotion, confidence only. When True: also includes all_predictions with all emotion confidences (default: False)
)
Asynch API Processing Workflow
The Asynch API uses a multi-step process to handle long audio files. Understanding this workflow is crucial for proper implementation:
1. Upload Phase (Client-Side)
When you call client.asynch.upload(file_path):
- SDK splits your file into parts (5MB chunks by default)
- Uploads parts in parallel
- Returns a
request_id- This is a tracking identifier, NOT a completion signal - At this point: File is uploaded to our server, but NOT processed yet
2. Background Processing (Server-Side)
After upload completes, the server automatically:
- Checks for new uploads
- Downloads audio when a new File is detected
- Splits audio into 5-second segments
- Processes audio file
- Invokes machine learning model for emotion detection
- Stores results in database
- Updates status to
completed
Processing Time: Varies based on file length and server load.
3. Results Retrieval (Client-Side)
When you call client.asynch.emotions(request_id):
- Polls the status endpoint at regular intervals
- Waits for status progression:
initiated→ Upload startedupload_completed→ File uploaded (processing not started)processing→ Background processing in progresscompleted→ Results ready
- Returns emotion timeline when status is
completed
Status Values
| Status | Meaning | What's Happening |
|---|---|---|
initiated |
Upload started | SDK is uploading file parts to S3 |
upload_completed |
Upload finished | File is in S3, waiting for background processor |
processing |
Processing active | Server is analyzing audio with ML model |
completed |
Results ready | Emotion timeline is available |
Important Notes
- The
request_idis NOT a completion indicator - It's a request tracking ID upload()completing does NOT mean results are ready - It means the file is uploaded- Background processing takes time - Processing time varies based on file length and server load
- You can check status anytime - The
request_idremains valid for retrieving results
Installation
pip install valenceai
Quick Start
from valenceai import ValenceClient
# Initialize client (uses VALENCE_API_KEY environment variable)
client = ValenceClient(api_key="your_api_key", comprehensive_output=True)
# Discrete API - Quick emotion detection
result = client.discrete.emotions(file_path="short_audio.wav")
print(f"Emotion: {result['main_emotion']}")
# Asynch API - Long audio with timeline
# Step 1: Upload file (returns tracking ID)
request_id = client.asynch.upload("long_audio.wav")
# Step 2: Wait for server processing and get results (polls until complete)
result = client.asynch.emotions(request_id, max_attempts=30, interval_seconds=10)
# Step 3: Access emotion data from results
emotions = result['emotions'] # List of emotion predictions with timestamps
# Get summary statistics
majority = client.asynch.majority_emotion(request_id) # Most frequent emotion
counts = client.asynch.emotion_counts(request_id) # {"happy": 10, "sad": 3, ...}
# Streaming API - Real-time audio
stream = client.streaming.connect()
stream.on_prediction(lambda data: print(data['main_emotion']))
stream.connect()
stream.send_audio(audio_bytes)
stream.disconnect()
# Rate Limit API - Monitor usage
status = client.rate_limit.get_status()
health = client.rate_limit.get_health()
API Reference
Discrete API
For short audio files requiring immediate emotion detection.
# File upload
result = client.discrete.emotions(
file_path="audio.wav",
)
# In-memory audio array
result = client.discrete.emotions(
audio_array=[0.1, 0.2, 0.3, ...],
)
Response:
{
"emotions": {
"happy": 0.78,
"sad": 0.12,
"angry": 0.05,
"neutral": 0.05
},
"main_emotion": "happy"
}
Asynch API
For long audio files with timeline analysis.
Status Progression: initiated → upload_completed → processing → completed
Upload Audio
# Upload file
request_id = client.asynch.upload(file_path="long_audio.wav")
Get Emotion Results
# Poll for results until processing completes
result = client.asynch.emotions(
request_id="abc-123",
max_attempts=20, # Max polling attempts (default: 20, range: 1-100)
interval_seconds=5 # Polling interval (default: 5, range: 1-60)
)
# This method waits for server processing to complete
# Returns when status is 'completed'
Response:
{
"emotions": [
{
"timestamp": 0.5,
"start_time": 0.0,
"end_time": 1.0,
"emotion": "happy",
"confidence": 0.9,
"all_predictions": {"happy": 0.9, "sad": 0.1, ...}
},
{
"timestamp": 1.5,
"start_time": 1.0,
"end_time": 2.0,
"emotion": "neutral",
"confidence": 0.85,
"all_predictions": {"neutral": 0.85, "happy": 0.15, ...}
}
],
"status": "completed"
}
Note: The all_predictions field is only included when comprehensive_output=True is set in the client constructor.
Helper Methods
# Get the most frequently occurring emotion across the entire file
majority = client.asynch.majority_emotion(request_id)
# Returns: "happy"
# Get emotion occurrence counts for the entire file
counts = client.asynch.emotion_counts(request_id)
# Returns: {"happy": 10, "sad": 3, "angry": 8, "neutral": 9}
Streaming API
For real-time emotion detection on live audio streams.
# Create streaming connection
stream = client.streaming.connect()
# Register callbacks
stream.on_prediction(lambda data: print(f"Emotion: {data['main_emotion']}"))
stream.on_error(lambda error: print(f"Error: {error}"))
stream.on_connected(lambda info: print(f"Connected: {info['session_id']}"))
# Connect to WebSocket
stream.connect()
# Send audio chunks (PCM bytes)
stream.send_audio(audio_chunk_bytes)
# Check connection status
if stream.connected:
print("Streaming active")
# Wait for events (blocking)
stream.wait()
# Disconnect
stream.disconnect()
Prediction Event:
{
"main_emotion": "happy",
"confidence": 0.87,
"all_predictions": {
"happy": 0.87,
"sad": 0.05,
"angry": 0.03,
"neutral": 0.05
},
"timestamp": 1706486400000 # Unix timestamp (UTC) in milliseconds
}
The timestamp is a Unix timestamp (UTC) in milliseconds representing when the server generated the prediction.
Rate Limit API
Monitor your API usage and limits.
# Get rate limit status
status = client.rate_limit.get_status()
print(status)
# {
# "limits": {
# "second": {"limit": 10, "remaining": 8, "reset": 1234567890},
# "minute": {"limit": 100, "remaining": 95, "reset": 1234567890},
# "hour": {"limit": 1000, "remaining": 950, "reset": 1234567890},
# "day": {"limit": 10000, "remaining": 9500, "reset": 1234567890}
# },
# "current_usage": {
# "second": 2,
# "minute": 5,
# "hour": 50,
# "day": 500
# }
# }
# Check API health
health = client.rate_limit.get_health()
print(health)
# {"status": "healthy", "timestamp": 1234567890}
Error Responses
Discrete API Errors
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | AUDIO_TOO_SHORT |
Audio duration below minimum (4.5 seconds). Response includes min_duration_seconds and actual_duration_seconds |
| 400 | Bad Request | Invalid request format or parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 500 | Server Error | Internal server error |
Asynch API Errors
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | AUDIO_TOO_SHORT |
Audio duration below minimum (5 seconds) |
| 400 | Bad Request | Invalid request format or parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 404 | Not Found | Request ID not found |
| 500 | Server Error | Internal server error |
Asynch Status Values:
| Status | Meaning |
|---|---|
initiated |
Upload in progress |
upload_completed |
Upload finished, awaiting processing |
processing |
Server analyzing audio |
completed |
Results ready |
failed |
Processing failed |
Streaming API Errors
| Event | Description |
|---|---|
error |
Server-side error during streaming |
warning |
Non-fatal warning from server |
connect_error |
WebSocket connection failed |
disconnect |
Connection closed |
Rate Limit API Errors
| HTTP Status | Description |
|---|---|
| 401 | Unauthorized - Invalid API key |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Server Error |
SDK Exception Classes
from valenceai import ValenceSDKException, AudioTooShortError, UploadError, PredictionError
try:
result = client.discrete.emotions(file_path="audio.wav")
except AudioTooShortError as e:
print(f"Audio too short: {e.actual_duration}s (min: {e.min_duration}s)")
except UploadError as e:
print(f"Upload failed: {e}")
except PredictionError as e:
print(f"Prediction failed: {e}")
except ValenceSDKException as e:
print(f"SDK error: {e}")
Additional Examples
Example scripts are available in the examples/ directory:
# Run discrete audio example
python examples/upload_short_audio.py
# Run asynch audio example
python examples/upload_long_audio.py
# Run streaming example
python examples/streaming_audio.py
# Run batch processing example
python examples/batch_processing.py
Migration from v0.x
Key Changes in v1.0.0
- Environment Variable:
VALENCE_API_KEYis now the standard (consistent naming) - Streaming API: New WebSocket-based real-time emotion detection
- Rate Limiting: New API for monitoring usage
- Timeline Data: Asynch API now returns detailed timestamp information
Updating Your Code
# Old (v0.x)
client = ValenceClient()
result = client.discrete.emotions("file.wav")
# New (v1.0.0) - mostly compatible, with new features
client = ValenceClient(api_key="your_key")
result = client.discrete.emotions(
file_path="file.wav",
)
# New streaming capability
stream = client.streaming.connect()
stream.on_prediction(callback)
stream.connect()
Support
- Additional Documentation: API Documentation
- Detailed Usage Examples: SDK Examples
- Issues: GitHub Issues
- Contact: Valence AI Support
License
Private License © 2026 Valence Vibrations, Inc, a Delaware public benefit corporation.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file valenceai-1.0.3-py3-none-any.whl.
File metadata
- Download URL: valenceai-1.0.3-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a2b4d78d74ca32176baa45f66b67f8bb29f92896475f1788bed79d60912105f
|
|
| MD5 |
5a3a97cd381599922eece6a869fc784b
|
|
| BLAKE2b-256 |
7d60d19b6bda25e8ddb9a0b0e33f3fd2384e56963e97d6eb3bd6ef6249e7bcfd
|