Sections
Streaming
Streaming
Send live audio over a WebSocket and get text about a second after the words in seven languages, then the full transcript with speakers and names when you stop.
What you get
Open a WebSocket to wss://stream.meetwave.io/v1/stream, send audio while people talk, and get the words back as they are said. When you stop, the session becomes a transcription like any other: the same transcript JSON, TXT, SRT and VTT, the same webhooks.
If you do not need text during the call, record and send the file instead: it costs from $0.12 an hour.
The first connection after a quiet period can take up to 15 seconds to be ready. The streaming client keeps the audio you send meanwhile and sends it once the server is ready.
Languages
Set language in the config. Whether a session has live text depends on it; the price does not.
| Language | Text | Meaning |
|---|---|---|
en, es, pt, ru | Live | English, Spanish, Portuguese and Russian: text about a second after the words. |
de, fr, it | Live, preview | German, French and Italian: the live text is rougher than the transcript you get at stop. |
auto or any other code | At stop | Every other language the Files API accepts, and auto: no text while the session runs, the transcript when you stop. |
Outside English, live text writes numbers as words. The transcript you get at stop is worked out again from the whole recording, so it has digits, and the live text never replaces it.
Tiers and prices
Every tier has the same live text. They differ in what the transcript holds when you stop.
| Tier | Price | Meaning |
|---|---|---|
text | $0.30 an hour | Live text, then the transcript with word times. In English the transcript is the live text joined, ready in seconds. |
speakers | $0.40 an hour | Live text, then the transcript worked out again from the whole recording, with who said what. |
names | $0.45 an hour | As speakers, plus the speakers’ names when the conversation says them. |
You pay per second of audio the server received. Credits for the next 5 minutes are held while the session runs, and the session is charged once, when its transcript is ready. Audio sent again after a reconnect is not charged again. With less than 5 minutes of credits the connection is refused and nothing is charged.
Stream a file
The quickest way to see it work: send a recording at the pace it was spoken and watch the text come. The streaming client does the waiting, buffering and reconnecting for you. Audio is 16 kHz mono 16-bit PCM; turn any recording into it with ffmpeg -i meeting.mp3 -f s16le -ac 1 -ar 16000 meeting.pcm.
# pip install meetwave-stream (Python 3.10 or later)
# export MEETWAVE_API_KEY=mwk_... (your key, from the console)
import asyncio
import os
import meetwave_stream
def show_ready(ready):
print("Connected, streaming…")
def show_final(final):
print(f"[{final['start']:.1f} s] {final['text']}")
async def main():
session = meetwave_stream.connect(
api_key=os.environ["MEETWAVE_API_KEY"], tier="names", language="en",
)
session.on("ready", show_ready)
session.on("final", show_final)
with open("meeting.pcm", "rb") as file: # 16 kHz mono 16-bit PCM
while chunk := file.read(3200):
# Any size; what is sent before the server is ready is kept for it
session.send(chunk)
await asyncio.sleep(0.1)
result = await session.stop() # waits for the full transcript
for segment in result.transcript["segments"]:
print(segment["speaker"], segment["text"])
asyncio.run(main())A microphone works the same way: send its samples as they come.
Without the client
The same file over a plain WebSocket, in any language that has one. The protocol page has every message.
# pip install websockets requests (Python 3.10 or later)
# export MEETWAVE_API_KEY=mwk_... (your key, from the console)
# Turn any recording into 16 kHz mono PCM first:
# ffmpeg -i meeting.mp3 -f s16le -ac 1 -ar 16000 meeting.pcm
import asyncio
import json
import os
import time
import requests
from websockets.asyncio.client import connect
headers = {"Authorization": f"Bearer {os.environ['MEETWAVE_API_KEY']}"}
FRAME = 3200 # 100 ms of 16 kHz 16-bit mono audio
MIN_FRAME = 640 # 20 ms: the shortest frame the server takes
CONFIG = {
"type": "config", "tier": "text", "language": "en",
"encoding": "pcm_s16le", "sample_rate": 16000,
}
async def send_audio(socket):
with open("meeting.pcm", "rb") as file:
audio = file.read()
for at in range(0, len(audio) - MIN_FRAME + 1, FRAME):
await socket.send(audio[at:at + FRAME])
await asyncio.sleep(0.1) # real-time pace, as a microphone would send
await socket.send('{"type": "stop"}')
async def stream():
"""Prints the live text; returns the transcription id after stop."""
address = "wss://stream.meetwave.io/v1/stream"
options = {"additional_headers": headers, "compression": None}
async with connect(address, **options) as socket:
await socket.send(json.dumps(CONFIG))
sender = None
async for raw in socket:
message = json.loads(raw)
if message["type"] == "ready":
print("Connected, streaming…")
sender = asyncio.create_task(send_audio(socket))
elif message["type"] == "partial":
print("\r…", message["text"], end="", flush=True)
elif message["type"] == "final":
print(f"\r[{message['start']:.1f} s] {message['text']}")
elif message["type"] == "error":
raise SystemExit(f"{message['code']}: {message['message']}")
elif message["type"] == "stopped":
return message["transcript_id"]
raise SystemExit(f"Closed with {socket.close_code} before the end")
transcription_id = asyncio.run(stream())
# The full transcript: at once for English text, in minutes for other tiers and languages
url = f"https://api.meetwave.io/v1/transcriptions/{transcription_id}"
transcription = requests.get(url, headers=headers).json()
while transcription["status"] in ("queued", "processing"):
time.sleep(5)
transcription = requests.get(url, headers=headers).json()
print(transcription["status"], transcription_id)How long it takes
- Live text: in about a second. A phrase becomes final 1.3 to 2.2 seconds after it ends.
- The transcript at stop: in seconds for English text. With speakers, names or another language, about a minute for a session of up to 10 minutes, and about 2 minutes per hour of audio.
From a browser
Never put your key into a web page. Your server asks for a one-time token with its key and hands it to the page, which connects with it within 1 minute:
curl -s -X POST https://api.meetwave.io/v1/stream/tokens \
-H "Authorization: Bearer $MEETWAVE_API_KEY"
# {"token": "mwst_...", "expires_in": 60}The page adds ?token=… to the stream address. A token opens one connection. The streaming client asks your server for a fresh one when it reconnects.