OpenAI TTS alternative — handling the complete audio file response
OpenAI's audio.speech.create uses HTTP chunked transfer-encoding to begin sending audio bytes as they are synthesized — clients can receive chunks progressively and start playback before the full file arrives. EasyVoice's endpoint works differently: it returns the complete audio file in one response, buffered server-side before delivery. EasyVoice does not currently offer a streaming/chunked TTS endpoint. Because Kokoro synthesis is fast (~1.1 ms/char on GPU), typical requests for standard narration lengths complete in a few seconds — the full-file latency is often acceptable for most TTS use cases. This page covers how to correctly fetch and handle the complete audio file in JavaScript and Python, the right response_format choices (mp3 or wav), and how to play or store the audio once received.
5,000 characters per day free, no credit card. Pro $9.99/mo unlimited vs OpenAI $15/1M (tts-1) / $30/1M (tts-1-hd).
Does EasyVoice support streaming/chunked TTS responses?
No. EasyVoice does not currently offer a streaming/chunked TTS endpoint. The endpoint at https://easyvoice.ae/api/v1/audio/speech buffers the complete audio file server-side and returns it in one HTTP response. The response body contains the complete MP3 or WAV file — there is no Transfer-Encoding: chunked header, no progressive byte delivery, and no ability to begin playback before synthesis is complete.
This differs from OpenAI's audio.speech.create, which does use HTTP chunked transfer-encoding to begin delivering audio bytes before synthesis finishes. If progressive streaming (first-byte before synthesis completes) is a hard requirement for your use case, EasyVoice's current endpoint does not satisfy it.
For the dominant TTS use cases — narration, chatbot responses, IVR prompts, accessibility read-aloud, content audio versions — the Kokoro synthesis speed (~1.1 ms/char on GPU) means the full-file response typically arrives in a few seconds for standard inputs. If full-file latency is acceptable for your application, EasyVoice's flat $9.99/mo plan covers all volumes.
Fetching the complete audio file in JavaScript
In JavaScript (Node.js 18+ or browser), use fetch with await res.arrayBuffer() to receive the complete audio file. The response body contains all audio bytes — call arrayBuffer() once and you have the complete file, ready to write to disk or create a Blob URL for browser playback.
In Node.js, write the buffer to a file with Buffer.from(await res.arrayBuffer()) and fs.writeFileSync. In the browser, create a Blob from the ArrayBuffer and use URL.createObjectURL to set as the src for an Audio element. The pattern is the same as handling any other binary HTTP response — no special streaming configuration needed.
Fetching the complete audio file in Python
In Python, use requests.post() without stream=True — the default behavior buffers the full response in memory, which is correct for a complete-file response. Access the audio bytes via res.content (a bytes object containing the complete file) and write to a file with f.write(res.content).
For asynchronous Python (asyncio / httpx), use httpx.AsyncClient and await response.aread() to get the complete response body. Both patterns receive the complete audio file in one call — there is no iteration or chunk accumulation needed.
Which response_format should I use?
EasyVoice supports mp3 (default) and wav. MP3 is the right choice for web playback, mobile apps, and any context where file size matters — at 128 kbps, a 60-second narration is approximately 1 MB. MP3 is directly playable in all major browsers and media players without additional libraries.
WAV (raw PCM) is the right choice for downstream audio processing pipelines — mixing into a podcast track, applying effects in Audacity, importing into a DAW. WAV files are uncompressed: a 60-second WAV is approximately 10 MB. Use wav when the downstream consumer is an audio processing library, not an end-user media player.
When EasyVoice is and isn't the right fit
EasyVoice is the right fit if your TTS use case can accept a full-file response with a few seconds of synthesis latency — narration, content audio versions, podcast intros, chatbot responses where the answer is computed before the audio starts, accessibility read-aloud, IVR prompts. At $9.99/mo flat with no per-character billing, it covers all volumes.
EasyVoice is not the right fit if your application requires progressive audio — bytes arriving at the client before synthesis is complete — for example a voice chatbot where users perceive the first word before the sentence is finished. OpenAI's audio.speech.create's chunked transfer-encoding satisfies that requirement; EasyVoice's current endpoint does not.
Code samples
Real working code, not pseudo-code. Every request below assumes you've set EASYVOICE_API_KEY and OPENAI_API_KEY as env vars where shown.
Fetch the complete audio — JavaScript (Node.js)
Receives the complete audio file in one response — write to disk or create a Blob URLconst res = await fetch("https://easyvoice.ae/api/v1/audio/speech", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.EASYVOICE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
voice: "af_alloy",
input: "Hello from EasyVoice. The complete audio file arrives in one response.",
response_format: "mp3",
}),
});
if (!res.ok) {
throw new Error(`EasyVoice API error: ${res.status}`);
}
// The response is a complete audio file — all bytes arrive together after synthesis
const buffer = Buffer.from(await res.arrayBuffer());
require("fs").writeFileSync("out.mp3", buffer);
// out.mp3 is ready to play immediatelyFetch the complete audio — Python
Receives the complete audio file in res.content — write directly to diskimport os
import requests
res = requests.post(
"https://easyvoice.ae/api/v1/audio/speech",
headers={
"Authorization": f"Bearer {os.environ['EASYVOICE_API_KEY']}",
"Content-Type": "application/json",
},
json={
"voice": "af_alloy",
"input": "Hello from EasyVoice. The complete audio file arrives in one response.",
"response_format": "mp3",
},
# Do NOT use stream=True — the response is a complete file, not a stream
)
res.raise_for_status() # raises on 401/400/429/5xx
# res.content is the complete audio file (all bytes buffered server-side)
with open("out.mp3", "wb") as f:
f.write(res.content)
# out.mp3 is ready to play immediatelyVoices to try on the free tier
Every voice below is callable via the same voice parameter — preview audio samples and read the full character profile.
Frequently asked questions
Does EasyVoice support streaming/chunked TTS responses?▾
No — EasyVoice's endpoint returns the complete audio file in one response. There is no chunked/streaming TTS endpoint today. The server buffers the full file before delivery; there is no progressive byte delivery as synthesis proceeds. Because Kokoro synthesis is fast (~1.1 ms/char on GPU), the full-file response typically arrives in a few seconds for standard narration lengths.
How do I fetch and save the complete EasyVoice audio response in JavaScript?▾
Call fetch() and await res.arrayBuffer() — that returns the complete audio file. Convert to a Buffer with Buffer.from(await res.arrayBuffer()) and write to a file with fs.writeFileSync. In a browser, create a Blob from the ArrayBuffer and use URL.createObjectURL for an audio element src. No streaming configuration needed.
How do I fetch and save the complete EasyVoice audio response in Python?▾
Use requests.post() without stream=True. Access the audio bytes via res.content (a bytes object containing the complete file) and write with f.write(res.content). Do not use iter_content — the response is a complete file, not a stream.
Which response_format should I use for EasyVoice?▾
mp3 (default) for web playback, mobile apps, or any context where file size matters — 128 kbps, approximately 1 MB per 60 seconds. wav for audio processing pipelines where you need raw PCM for mixing or effects — approximately 10 MB per 60 seconds, uncompressed. EasyVoice does not support opus, aac, flac, or pcm; unsupported formats fall back to mp3.
Related OpenAI migration guides
OpenAI TTS API reference — audio.speech.create mapped to EasyVoice
OpenAI TTS API reference mapped to EasyVoice. audio.speech.create params, error codes 401/400/429/5xx, request/response shapes. OpenAI-compatible endpoint.
OpenAI TTS quickstart — first audio in 5 steps, no credit card
OpenAI TTS quickstart alternative. EasyVoice: 5 steps, no credit card, first audio in under 2 minutes. Account, API key, curl request, mp3 playback — free tier.
Migrate from OpenAI TTS to EasyVoice in 5 lines
OpenAI TTS to EasyVoice migration guide: 5-line code diff in Python + JS. Model, voice, response_format mapping. $9.99 flat vs $15/1M.
Vendor comparison: EasyVoice vs OpenAI TTS
Side-by-side feature comparison covering voices, languages, pricing tiers, free limits, API surface, and the why-people-look / where-each-wins breakdown.
Developer-focused OpenAI migration in /tts-api
The developer-onboarding angle of the same migration — request body compatibility deep-dive, streaming behavior, ChatGPT plugin/Realtime API guidance, and the official OpenAI SDK constraint.
Start migrating off OpenAI TTS today
5,000 characters per day free, no credit card. Pro $9.99/mo unlimited replaces OpenAI's $15-$300/mo bills once you cross 666K characters per month.