AI Text to Speech Voiceover - MP3, WAV, Opus and AAC
Pricing
from $38.50 / 1,000 voiceovers
AI Text to Speech Voiceover - MP3, WAV, Opus and AAC
Turn a script, or a batch of them, into a voiceover file: MP3, WAV, Opus or AAC, six voices, any speed from 0.25 to 4.0. Long scripts are split and joined for you. Runs on your own OpenAI key. Each row holds the file link, length and voice. $40.00 per 1,000 voiceovers ($0.04 each).
Pricing
from $38.50 / 1,000 voiceovers
Rating
5.0
(2)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
13
Total users
3
Monthly active users
8 days ago
Last modified
Categories
Share
Turn a script, or a whole batch of them, into a text to speech voiceover you can download: one MP3, WAV, Opus or AAC file per script, in one of six voices, at the speed you set. Each file lands in the run's key-value store with a direct link, next to a row giving the voice, the length and how many characters were read.
The part to know before you start: this runs on your own OpenAI key. You paste the key in, OpenAI bills you for the speech itself, and without a key the run hands back a free demo record instead of audio.
| Input | A script in text, or a list of them in texts |
| Output | One audio file per script, and a row with its link, length, voice and character count |
| Ceiling | No item cap. Long scripts are split and joined back, so the run's timeout is the real limit |
| Account needed | Your own OpenAI API key. Without one you get a free demo record |
| Price | $40.00 per 1,000 voiceovers, so 4 cents each, flat on every plan. The free plan's $5 a month covers about 125. OpenAI bills your key for the speech separately |
🔍 What AI Text to Speech Voiceover does
It reads your text out loud and hands you the file. Six voices, four formats, and a speed dial from 0.25 to 4.0.
A long script does not need splitting by hand. Anything over about 3,500 characters is cut at
sentence boundaries, each piece is voiced on its own, and the pieces are joined back into a single
file without re-encoding. The row tells you how many pieces went into it, in chunks.
texts is the batch door. Give it an array of strings and you get one file per string. Give it an
array of objects and it reads whichever of script, scriptText, text or narration is present.
An object with none of those four keys is dropped quietly, which is worth knowing if a batch comes
back shorter than you sent.
Items are done one after another rather than all at once, so a long list takes a while.
📋 What data you get from each voiceover
| What you get | Field |
|---|---|
| The audio file, saved in the run's key-value store | audioKey |
| A direct link to that file | audioUrl |
| Its length in seconds, measured off the finished file | durationSeconds |
| The voice, model and format actually used, after defaults | voice, model, format |
| How long the text was, and how many pieces it was voiced in | characters, chunks |
| The first 160 characters of what was read, so rows are easy to tell apart | textPreview |
| Which item of your batch it was, counting from 1 | index |
▶️ How to turn text into speech
- Open AI Text to Speech Voiceover and click Try for free.
- Paste your OpenAI key into OpenAI API key (BYO).
- Put your script in Text / script, or a list of scripts in Texts (batch).
- Pick the Voice and the Audio format, then click Start.
- Take the files from the run's Storage tab, or follow
audioUrlfrom each dataset row.
Start it once with no key and you get the free demo record, so you can see the shape first.
💰 How much does it cost to turn text into speech?
$0.04 per voiceover, which is $40.00 per 1,000. Flat on every Apify plan, no volume tiers. Fifty narration blocks in one batch run come to $2.00, and on the free plan the $5 Apify gives you each month covers about 125 voiceovers.
You pay per delivered file. The keyless demo record and any item that failed are not charged.
OpenAI bills your own key separately for the speech itself, and tts-1-hd costs you more there
than tts-1.
📥 What you give it
{"text": "Welcome back to the channel. Today we are looking at one of the strangest mysteries of the deep ocean.","voice": "onyx","format": "mp3","speed": "1.0"}
| Field | Default | What it is |
|---|---|---|
text | none | One script, as a single string. The form opens with an example sentence filled in, which is a starting point rather than a default. |
texts | none | Batch mode. An array of strings, or of objects keyed script, scriptText, text or narration. One audio file per item. |
voice | onyx | One of alloy, echo, fable, onyx, nova, shimmer. onyx is the deep male one, nova and shimmer are female. |
model | tts-1 | tts-1 is quick, tts-1-hd sounds better and costs you more on your own OpenAI bill. |
format | mp3 | mp3, wav, opus or aac. |
speed | 1.0 | Playback speed between 0.25 and 4.0. It is a text field, so type a number: anything that is not one quietly becomes 1.0. |
openaiApiKey | none | Your own OpenAI key. Marked secret, so it is not written into the run's visible input. |
baseUrl | none | Advanced. Any OpenAI-compatible /audio/speech host. Left empty it uses https://api.openai.com/v1. |
Give it a key but no text and no texts and the run fails, because there is nothing to read.
📤 What you get back
One dataset row per finished voiceover, and the audio itself in the run's key-value store under a
key like voiceover-1-1757000000000.mp3.
No run on record has delivered a voiceover with a customer's key, so rather than type out a
plausible row, here is the real demo record a keyless run wrote on 2 October 2026, notice cut short.
A delivered row has the same fields, with audioKey, audioUrl and a real durationSeconds
filled in, and no _demo or _notice.
{"_demo": true,"_notice": "SAMPLE OUTPUT ... Supply \"openaiApiKey\" to generate real voiceover audio.","ok": true,"index": 1,"voice": "onyx","model": "tts-1","format": "mp3","characters": 103,"chunks": 1,"durationSeconds": 0,"audioKey": null,"audioUrl": null,"textPreview": "Welcome back to the channel. Today, we're diving into one of the strangest mysteries of the deep ocean."}
| Field | How to read it |
|---|---|
ok | true on a delivered voiceover. |
chunks | How many separate pieces were voiced and joined. 1 means the script fitted in one. |
durationSeconds | Measured off the finished file. It reads 0 when that measurement failed, not when the audio is empty. |
audioUrl | A direct link to the file. audioKey is its name in the key-value store. |
characters | The length of the text you sent for that item. |
🧾 Reading the output
Three kinds of record come out of a run, and only one of them is in the dataset.
| Record | Where it lands | Billed |
|---|---|---|
| A finished voiceover | A dataset row, ok: true | yes |
| The keyless demo | Key-value store, SAMPLE_AND_NOTICES, _demo: true | no |
| An item that failed | Key-value store, SAMPLE_AND_NOTICES, ok: false | no |
So everything in the dataset is audio you can use. One failed item does not stop the batch: it is recorded in the store and the run moves on to the next item.
Worth knowing, because it is the thing that confuses people: if every item fails, the run still
finishes green with an empty dataset. The reasons are all sitting in SAMPLE_AND_NOTICES in the
key-value store.
The Overview table shows index, voice, format, durationSeconds, characters, audioUrl and
textPreview. model and chunks are real fields but not among the columns, so open the row or
download the JSON if you want them.
💡 What people use it for
- Narration for faceless video channels, where a week of scripts goes in as one
textsbatch. - Audiobook and long-article reading, leaning on the automatic splitting so nothing has to be cut up by hand.
- Phone-menu prompts, where WAV is usually the format the phone system wants.
- Trying the same script in several voices before committing to one.
From a written post to a narrated slideshow, in three runs:
- Run Reddit Text Cleaner on the post and copy
the
cleanedtext it returns. - Paste that text here into Text / script and take the
audioUrlfrom the row. - Put the
audioUrlinto Audio URL on Storyboard Video Generator, with your images in Image URLs, and you get an MP4 with your voiceover laid over it.
🚧 What it does not do
- No voice cloning, and no custom voices. Six voices, listed above, and that is the list.
- No SSML. There are no tags for pauses, emphasis or pronunciation. Punctuation and
speedare the only controls over delivery. - A rejected key stops the batch, rather than retrying its way down your whole list.
durationSecondscan read0when the finished file could not be measured. The audio is still there, and the row is still charged.- Joined
opusandaacfiles are less proven than MP3. Long scripts in those two formats are stitched the same way, but MP3 is the one with playback evidence behind it. Use MP3 or WAV if a long script has to be right first time. - No video, no captions, no music bed. This is the audio track only.
- It is not an official tool of any platform or company named on this page. Dami's Studio is independent and is not affiliated with or endorsed by any of them.
🧭 Which AI media actor do you need?
| If you want | Use |
|---|---|
| A script read out loud as an audio file | This one |
| A finished vertical video with script, voice and captions | AI Faceless Video Generator |
| An existing video re-voiced in another language | AI Video Dubber |
| Images turned into a slideshow video, with your voiceover laid over it | Storyboard Video Generator |
| Scene images for a story before you voice it | AI Storyboard Generator |
| Word by word captions burned onto a video you already have | Auto Caption Burner |
| The other direction: speech in a video or audio file written out as text | Video & Audio Transcriber |
| A Reddit post cleaned up so a voice can read it | Reddit Text Cleaner |
❓ Questions people ask
Do I need my own OpenAI key for text to speech?
Yes. There is no shared key behind this, and without one you get the demo record rather than audio.
Is my OpenAI key safe here?
It is a secret field, so it is not stored in the run's visible input. Use one you can revoke, as with anything you paste into a tool you did not write.
Can I use something other than OpenAI?
If it speaks the same /audio/speech shape, point baseUrl at it. Anything else will not work.
Why is my dataset empty when the run went green?
Every item failed. The reasons are in SAMPLE_AND_NOTICES in the run's key-value store.
Can I call it from code or connect it to an AI assistant?
Yes. The API tab has ready-made code
for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect
https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/ai-tts-voiceover. Either way the run
happens on your Apify account at the same price, and the speech is billed to your OpenAI key as
usual.
🆘 If something breaks
Open the Issues tab on the actor page. Include the run ID and which format and voice you used,
and check SAMPLE_AND_NOTICES in the run's key-value store first, since the per-item reason is
usually already written there.