This guide walks you through the complete workflow: creating a dataset, uploading audio, adding annotations, training a model, and running inference.
Prerequisites
Step 1: Get your API key
- Sign in to app.relayai.dev
- Navigate to Settings > API Keys
- Click Create API Key
- Copy and save your key securely
API keys are only shown once. Store your key in a secure location.
Set your API key as an environment variable:
export RELAY_API_KEY="your_api_key_here"
Step 2: Create a dataset
A dataset defines what artifact types you want to detect. Create one with the artifact types relevant to your use case:
curl -X POST https://api.relayai.dev/api/v1/datasets \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "TTS Glitch Detection",
"description": "Detect glitches and pauses in TTS output",
"artifact_types": [
{"name": "glitch", "description": "Audio pop or click", "color": "#FF4444"},
{"name": "long_pause", "description": "Unnatural pause > 500ms", "color": "#4444FF"}
]
}'
Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "TTS Glitch Detection",
"description": "Detect glitches and pauses in TTS output",
"artifact_types": [
{"name": "glitch", "description": "Audio pop or click", "color": "#FF4444"},
{"name": "long_pause", "description": "Unnatural pause > 500ms", "color": "#4444FF"}
],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
Save the id from the response. You’ll need it for subsequent steps.
Step 3: Upload audio files
Audio upload uses presigned URLs for direct upload to cloud storage. The flow is:
- Request a presigned upload URL
- Upload the file to the URL
- Confirm the upload
Request upload URL
curl -X POST "https://api.relayai.dev/api/v1/datasets/$DATASET_ID/audio/upload-url" \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "sample_audio.wav",
"content_type": "audio/wav",
"file_size": 1048576
}'
Response:
{
"upload_url": "https://s3.amazonaws.com/...",
"fields": {
"key": "uploads/123/sample_audio.wav",
"policy": "...",
"x-amz-signature": "..."
},
"audio_id": "456e7890-e89b-12d3-a456-426614174001",
"expires_in": 3600
}
Upload the file
# Upload using the presigned URL (multipart form)
curl -X POST "$UPLOAD_URL" \
-F "key=$KEY" \
-F "policy=$POLICY" \
-F "x-amz-signature=$SIGNATURE" \
-F "file=@sample_audio.wav"
Confirm upload
curl -X POST "https://api.relayai.dev/api/v1/datasets/$DATASET_ID/audio/confirm" \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audio_id": "456e7890-e89b-12d3-a456-426614174001"
}'
After confirmation, Relay processes the audio (normalizes to 16kHz mono and computes embeddings). Check the audio file status by polling:
# Wait for processing to complete
import time
while True:
response = requests.get(
f"{BASE_URL}/api/v1/datasets/{dataset_id}/audio/{audio_id}",
headers={"X-API-Key": API_KEY}
)
audio = response.json()
if audio["processing_status"] == "ready":
print("Audio processing complete")
break
elif audio["processing_status"] == "failed":
print(f"Processing failed: {audio['processing_error']}")
break
time.sleep(2)
Step 4: Add annotations
Create an annotation set and add annotations marking where artifacts occur:
Create annotation set
curl -X POST "https://api.relayai.dev/api/v1/datasets/$DATASET_ID/annotation-sets" \
-H "X-API-Key: $RELAY_API_KEY"
Add annotations
Each annotation specifies which audio file, the artifact type, and the start/end timestamps in milliseconds:
curl -X POST "https://api.relayai.dev/api/v1/datasets/$DATASET_ID/annotation-sets/$ANNOTATION_SET_ID/annotations/bulk" \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"annotations": [
{
"audio_file_id": "456e7890-e89b-12d3-a456-426614174001",
"artifact_type": "glitch",
"start_ms": 1200,
"end_ms": 1450,
"confidence": 1.0
},
{
"audio_file_id": "456e7890-e89b-12d3-a456-426614174001",
"artifact_type": "long_pause",
"start_ms": 3500,
"end_ms": 4200,
"confidence": 1.0
}
]
}'
Publish the annotation set
Before training, you must publish the annotation set. Published sets are immutable.
curl -X POST "https://api.relayai.dev/api/v1/datasets/$DATASET_ID/annotation-sets/$ANNOTATION_SET_ID/publish" \
-H "X-API-Key: $RELAY_API_KEY"
Step 5: Train a model
Submit a training job with your dataset and published annotation set:
curl -X POST https://api.relayai.dev/api/v1/training-jobs \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dataset_id": "123e4567-e89b-12d3-a456-426614174000",
"annotation_set_id": "789e0123-e89b-12d3-a456-426614174002",
"config": {
"artifact_types": ["glitch", "long_pause"],
"epochs": 20,
"validation_split": 0.2,
"learning_rate": 0.001,
"batch_size": 32
}
}'
Poll for training completion:
while True:
response = requests.get(
f"{BASE_URL}/api/v1/training-jobs/{job_id}",
headers={"X-API-Key": API_KEY}
)
job = response.json()
print(f"Status: {job['status']} - Progress: {job['progress_percent']}%")
if job["status"] == "completed":
print(f"Training complete! Metrics: {job['metrics']}")
break
elif job["status"] == "failed":
print(f"Training failed: {job['error_message']}")
break
time.sleep(30)
Step 6: Run inference
Once training completes, a model is created automatically. Create an inference job and upload audio to detect artifacts:
Create inference job
curl -X POST https://api.relayai.dev/api/v1/inference-jobs \
-H "X-API-Key: $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model_id": "model-uuid-here",
"config": {
"threshold": 0.5,
"merge_window_ms": 200,
"min_duration_ms": 50
}
}'
Upload audio for inference
Upload audio using the same presigned URL flow:
# Get upload URL
response = requests.post(
f"{BASE_URL}/api/v1/inference-jobs/{inference_job_id}/files/upload-url",
headers={"X-API-Key": API_KEY},
json={
"filename": "test_audio.wav",
"content_type": "audio/wav",
"file_size_bytes": 2097152
}
)
upload_info = response.json()
# Upload file
with open("test_audio.wav", "rb") as f:
requests.post(
upload_info["upload_url"],
data=upload_info["upload_fields"],
files={"file": f}
)
# Confirm upload
requests.post(
f"{BASE_URL}/api/v1/inference-jobs/{inference_job_id}/files/confirm",
headers={"X-API-Key": API_KEY},
json={"file_id": upload_info["file_id"]}
)
Get detection results
curl "https://api.relayai.dev/api/v1/inference-jobs/$INFERENCE_JOB_ID" \
-H "X-API-Key: $RELAY_API_KEY"
Example response:
{
"id": "job-uuid",
"status": "completed",
"total_files": 1,
"processed_files": 1,
"total_detections": 2,
"files": [
{
"original_filename": "test_audio.wav",
"status": "completed",
"detections": [
{
"artifact_type": "glitch",
"start_ms": 1200,
"end_ms": 1450,
"confidence": 0.87
},
{
"artifact_type": "long_pause",
"start_ms": 3500,
"end_ms": 4200,
"confidence": 0.92
}
]
}
]
}
Next steps