This product is a Beta product. This means that it and the information is subject for change, updates or removal.
If you test this product, please let us know your feedback, so that we can make it the best possible product for you. Please share your feedback with us here.
sync to avoid exhausting the audio bufferThe API allows you to buffer up to 30MB of audio data at any given time. The buffer size is chosen to be large enough that you don’t need to worry about it in most normal use cases — any individual audio file will comfortably fit inside the 30MB limit. However, this can become an issue if your application tries to play multiple large audio files in succession, or if you play the same audio file repeatedly in a loop.
In the following example, the application naively plays the same file again and again, looping forever. This will quickly fill the API’s audio buffer and cause the call to end with an error:
# NB: This code does not work
while True:
with open("audio.wav", "rb") as f:
await elks_ws.send(json.dumps({
"t": "sending",
"format": "wav"
}))
for chunk in iter(lambda: f.read(32 * 1024), b""):
await ws.send(json.dumps({
"t": "audio",
"data": base64.b64encode(chunk).decode()
}))
Instead of writing complex timing code in your application, or guessing how
much data is in the API’s buffer at any given moment, you can use the sync
message to synchronize the state between the API and your application.
The sync message acts as a “checkpoint” of sorts that lets your application
know that the API has processed all messages up until that point. When the
API receives a sync message it will reply back with its own sync —
but only after all previous messages have been processed. In other words, if
you send a sync after sending some audio, the API will not respond to it
until all audio sent before the sync has been played.
You can use this to ensure your application doesn’t send “too much” audio at once, as in the following example.
syncThis example plays a WAV file in a loop until the user hangs up.
async def looped_playback(ws):
# Get the call metadata from the hello message
hello = json.loads(await ws.recv())
print(f"Received {hello['to']} <- {hello['from']} ({hello['callid']})")
while True:
# Tell the API the format we'll be sending audio in
await ws.send(json.dumps({
"t": "sending",
"format": "wav"
}))
# Send the WAV file bytes in chunks
with open("audio.wav", "rb") as f:
for chunk in iter(lambda: f.read(32 * 1024), b""):
await ws.send(json.dumps({
"t": "audio",
"data": base64.b64encode(chunk).decode()
}))
# Send the sync message
await ws.send(json.dumps({
"t": "sync"
}))
# Wait for the response from the API.
msg = json.loads(await ws.recv())
# Exit if the call has ended. Else, play the file again.
if msg["t"] == "bye":
print("Call ended:", msg["message"])
break