Rev AI Streaming
Simple WebSocket streaming API with access token in the URL and custom vocabulary. Billing counts the longer of stream time and audio time.
Overview
Best for: Teams already on Rev for batch/human transcription who want a straightforward English streaming feed.
At a glance
Free credit is 5 hours of Reverb ASR, not a dollar amount. $0.20/hr is the English Reverb line; pricing page does not confirm it applies to streaming. Billed on max(stream, audio) duration with a 15 s minimum. HIPAA is a vendor claim, not re-verified. Streaming language list not published.
content_type query param, e.g. audio/x-raw;layout=interleaved;rate=16000;format=S16LE;channels=1. Raw, FLAC or WAV recommended.
n/a
language param defaults to en; streaming language list not shown on the API page.
No vendor figure captured.
Rev markets 'global deployments' (EU option); not re-verified.
Rev markets HIPAA support (site navigation lists HIPAA); not re-verified.
Features
- partial and final hypotheses
- custom vocabulary (custom_vocabulary_id)
- profanity filter / options via query params
Pricing
| What | Price | Unit |
|---|---|---|
| Reverb Transcription (English) | $0.20 | per hour |
| Reverb Foreign Language | $0.30 | per hour |
| Billing rule (streaming) | max(stream duration, audio duration) | rounded up per second, 15 s minimum |
Assumes the $0.20-$0.30/hr Reverb lines apply to streaming, which the pricing page does not confirm.
Free tier: Free credits equal to 5 hours of Reverb ASR on Pay As You Go.
Source: rev.ai
Setup
- Generate an access token in the Rev AI dashboard.
- Open wss://api.rev.ai/speechtotext/v1/stream?access_token=...&content_type=...
- Wait for the 'connected' message, then send binary audio.
- Read 'partial' and 'final' messages; send the text 'EOS' to end.
Endpoint
wss://api.rev.ai/speechtotext/v1/stream
Authentication
access_token query parameter (do not expose the long-lived token in browsers; proxy through your server).
Quick start python
import asyncio, json, os, websockets # pip install websockets>=14
from urllib.parse import urlencode
q = urlencode({"access_token": os.environ["REVAI_ACCESS_TOKEN"],
"content_type": "audio/x-raw;layout=interleaved;rate=16000;format=S16LE;channels=1"})
URL = "wss://api.rev.ai/speechtotext/v1/stream?" + q
async def main():
async with websockets.connect(URL) as ws:
async def send():
with open("audio_16k_mono.raw", "rb") as f:
while chunk := f.read(3200): # 100 ms
await ws.send(chunk)
await asyncio.sleep(0.1)
await ws.send("EOS")
async for msg in ws:
d = json.loads(msg)
if d["type"] == "connected":
asyncio.create_task(send())
elif d["type"] == "partial":
print("partial", " ".join(e["value"] for e in d["elements"]))
elif d["type"] == "final":
print("FINAL", "".join(e["value"] for e in d["elements"]))
asyncio.run(main())
Written from the current docs. Check the vendor's SDK version before you ship.
Warnings
Idle connection time is billed
You are charged for the larger of stream duration and audio duration, rounded up per second with a 15-second minimum per stream. An open socket with no audio still costs money.
Streaming price not itemised
rev.ai/pricing lists Reverb at $0.20/hr and foreign languages at $0.30/hr but never labels a streaming line. Confirm the streaming rate with Rev before budgeting.
Low default concurrency
Streaming concurrency defaults to 10 connections per account; request an increase before launch.
Token in the URL
The access token goes in the query string, so it can leak into proxy and server logs. Use a server-side relay rather than putting it in browser code.
Plus 12 warnings that apply to all speech-to-text, live APIs. See category warnings.
Limits
- 3 hours per stream; open a new connection before the limit.
- Default streaming concurrency 10 (support can raise).
- max_connection_wait_seconds default 60.
Models and products
| Name | Status |
|---|---|
| Reverb (streaming) | GA |
Docs and sources
Docs
Sources used
Streaming-specific price, streaming language list and current model name. Message field names in the snippet follow the documented partial/final element format but were not re-read in full.