Text to Speech - Bulk TTS to MP3, Subtitles, Articles & Texts
Pricing
from $6.40 / 1,000 1,000 characters spokens
Text to Speech - Bulk TTS to MP3, Subtitles, Articles & Texts
Turn texts and article URLs into natural speech: one MP3 (or Opus, WAV) file per text with optional SRT/VTT subtitles, in English, Spanish, French, Chinese, Japanese or Korean. $0.008 per 1,000 characters; empty and failed items are free; no start fee.
Pricing
from $6.40 / 1,000 1,000 characters spokens
Rating
0.0
(0)
Developer
Yukai Lin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Text to Speech: Bulk TTS to MP3 with Subtitles, for Texts and Articles
Turn texts, scripts and web articles into natural-sounding speech. Paste one long text, a list of texts, or article URLs, and get one MP3 file per item (or Ogg Opus, or WAV) in the run's key-value store, optionally with SRT and WebVTT subtitles, and a dataset row holding the file links, the length in seconds and the number of characters read.
- Small files that play everywhere: MP3 at 64 kbit/s is about 0.5 MB per minute (11x smaller than WAV); Ogg Opus at 32 kbit/s about 0.25 MB per minute (20x smaller). WAV is still available.
- Subtitles:
.srtand.vttfiles timed from the generated speech itself, ready for video editors and web players. No extra charge. - 6 languages: English, Spanish, French, Chinese (Mandarin), Japanese, Korean. Set a default, or a language per text.
- Long texts welcome: texts are split at sentence ends, spoken part by part and joined into one file with natural pauses. Up to 100,000 characters per text.
- Articles from URLs: the page's main article text is read (title first), without menus, link lists, image captions in brackets, citation marks or code blocks.
- Fast: in our tests about 4,000 characters (almost 4 minutes of English speech) took 11–27 seconds to speak; compressing a minute of speech takes 1–3 seconds more.
- Pay only for what is read: $0.008 per 1,000 characters, whatever the format and with or without subtitles. Empty texts, unreadable pages, invalid items and failures are free. No start fee.
Speech is generated with the open MeloTTS model (MyShell.ai) on Cloudflare Workers AI. Every plan, including Apify's free plan, uses the same voice and formats.
Input
One text (the "Text" field), as MP3 with subtitles:
{ "text": "Hello from TidyTools. This text was turned into speech in a few seconds.", "subtitles": true }
A list of texts, each with an optional id (names the file and the row) and language:
{"texts": [{ "id": "zh-news", "text": "今天台北天氣晴朗,氣溫攝氏二十五度。", "language": "zh" },{ "id": "ja-greeting", "text": "おはようございます。本日の会議は午後三時から始まります。", "language": "ja" },"A plain string uses the default language."],"language": "en","audioFormat": "opus"}
Article URLs:
{ "urls": ["https://en.wikipedia.org/wiki/Speech_synthesis"], "maxCharsPerText": 4000 }
| Field | Default | Meaning |
|---|---|---|
text | – | One text to read aloud. |
texts | – | Several texts: strings, or { "id", "text", "language" } objects. |
urls | – | Web pages whose main article text is read aloud (one file per page). |
language | en | en, es, fr, zh, ja or ko. The text should be written in that language. |
audioFormat | mp3 | mp3 (64 kbit/s mono, plays everywhere), opus (Ogg Opus, 32 kbit/s mono, smallest; plays in browsers, Android, VLC) or wav (16-bit mono, uncompressed). Same price. |
subtitles | false | Also save <file>.srt and <file>.vtt subtitles for each item. Same price. |
sampleRate | 44100 | WAV only: 44100 (as generated, about 5.3 MB per minute) or 22050 (half the size). |
maxCharsPerText | 20,000 | Longer texts and pages are cut at the last sentence before the limit (truncated: true). Only the characters read are charged. |
maxConcurrency | 2 | Items spoken in parallel (1–5). |
httpVia, proxyConfiguration | auto / none | Only for urls: how pages are fetched when a site blocks data centers. |
All three sources can be combined in one run (up to 1,000 items).
Output
One audio file per item in the default key-value store (audio-001-<name>.mp3, .opus or .wav), with audio-001-<name>.srt and .vtt next to it when subtitles is on, and one dataset row per item.
An MP3 row with subtitles (the layout of every successful row; the size is what our encoder writes for this 4.25-second sentence):
{"index":0,"input":"text","source":"text","success":true,"language":"en","chars":72,"durationSec":4.25,"audioUrl":"https://api.apify.com/v2/key-value-stores/<store>/records/audio-001-Hello-from-TidyTools-This-text-was-turn.mp3","fileKey":"audio-001-Hello-from-TidyTools-This-text-was-turn.mp3","format":"mp3","sampleRate":44100,"bitrateKbps":64,"bytes":34272,"srtUrl":"https://api.apify.com/v2/key-value-stores/<store>/records/audio-001-Hello-from-TidyTools-This-text-was-turn.srt","vttUrl":"https://api.apify.com/v2/key-value-stores/<store>/records/audio-001-Hello-from-TidyTools-This-text-was-turn.vtt","cueCount":2,"truncated":false,"textPreview":"Hello from TidyTools. This text was turned into speech in a few seconds.","synthesisSec":2,"charged":true,"chargedUnits":1}
A real WAV row from our test runs ("audioFormat": "wav", "sampleRate": "22050"):
{"index":0,"input":"https://en.wikipedia.org/wiki/Speech_synthesis","source":"url","title":"Speech synthesis - Wikipedia","success":true,"language":"en","chars":3983,"originalChars":48538,"truncated":true,"durationSec":230.21,"fileKey":"audio-001-Speech-synthesis-Wikipedia.wav","format":"wav","sampleRate":22050,"bytes":10152498,"synthesisSec":26.9,"charged":true,"chargedUnits":4}
The same 230 seconds as MP3 would be about 1.8 MB, as Opus about 0.9 MB.
{"input":"german","id":"german","success":false,"errorType":"invalid_input","charged":false,"error":"language \"de\" is not supported (use en, es, fr, zh, ja, ko) (not charged)"}
Subtitles (.srt; the .vtt has the same cues):
100:00:00,000 --> 00:00:01,395Hello from TidyTools.200:00:01,395 --> 00:00:04,250This text was turned intospeech in a few seconds.
| Field | Meaning |
|---|---|
audioUrl, fileKey | Download link and key of the audio file in the run's key-value store. |
format, bitrateKbps, sampleRate, bytes | mp3, opus or wav; bitrate (MP3 and Opus); sample rate of the file (MP3 44,100, Opus 48,000, WAV 44,100 or 22,050); file size. |
srtUrl, vttUrl, cueCount | With subtitles: links to the SRT and WebVTT files and the number of cues. |
durationSec | Length of the speech in seconds. |
chars | Characters read aloud (after clean-up and any truncation); originalChars when truncated. |
language | Voice language. |
source, input, id, index | Where the item came from (text or url), the original input, your id, its position. |
title, url, finalUrl | For URLs: the page title and address. |
textPreview | The first 200 characters that were read. |
synthesisSec | Seconds taken to speak and encode the item. |
charged, chargedUnits | Whether the item was charged, and how many 1,000-character units. |
errorType, error | On free rows: invalid_input (empty text, unsupported language, not a URL), no_text (page without article text), not_found, blocked, timeout, failed… |
SUMMARY (key-value store) has status (SUCCESS, PARTIAL_RESULTS, FAILED, LIMIT_REACHED…), spoken, failed, charactersSpoken, audioSeconds, chargedUnits, audioFormat, bitrateKbps or sampleRate, audioBytes, encodeSeconds, subtitles, costPlan, notProcessed (when the max charge stopped the run) and failuresByErrorType.
How the subtitles are timed
The speech service reports the measured length of every chunk it speaks (about 400 characters, cut at sentence ends), and the pauses between chunks and parts are known, so each chunk's subtitles start exactly where its audio starts. Inside a chunk, the cues (a sentence, or a phrase that fits two lines of 42 characters; 16 for Chinese, Japanese and Korean) share the chunk's time in proportion to their length, so a cue can drift by a fraction of a second within its chunk. MP3 files start with the usual 25 ms of encoder delay.
Control your cost
- $0.008 per started 1,000 characters read aloud, per item: a 72-character sentence is 1 unit ($0.008), a 3,983-character article is 4 units ($0.032). The format and the subtitles do not change the price. No start fee.
- About 1,000 English characters make one minute of speech (measured: 3,983 characters → 230 s). Chinese, Japanese and Korean are denser: about 5–6 characters per second, so 1,000 characters make roughly 3 minutes.
- Free: empty texts, text with nothing to read, unsupported languages, invalid URLs, pages without readable text, failed items.
- At the start the log and status show the worst case (units × price; URL pages are counted at up to 10,000 characters until read). When your max charge per run is reached, the remaining items are not processed and are listed in
SUMMARY.notProcessed. - For comparison (checked October 2026):
marielise.dev/pdf-to-mp3on Apify charges $0.04 per audio minute plus $0.05 per run.
Use with AI agents (MCP)
Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/text-to-speech) to Claude, Cursor or any MCP client, then ask e.g. "Read this article aloud and give me an MP3 with subtitles: https://…". Minimal input: {"text":"Hello world."}. Failed items are not charged and carry an errorType.
Works well with
- Audio to Text (audio-transcriber): transcribe a recording, edit the text, and turn it back into clean speech.
- Page Summarizer: summarize long articles first, then listen to the summary.
FAQ
Can I clone a voice or pick a different speaker? No. There is one standard voice per language (the speech model offers no speaker or speed choice).
Which format should I pick? MP3 for anything (podcast hosts, video editors, phones). Opus for the smallest files in browsers and apps. WAV when an editor needs uncompressed audio.
How are MP3 and Opus made? In the Actor, in pure JavaScript and WebAssembly: our own MP3 encoder (MPEG-1 Layer III, built from the standard's tables) and libopus (BSD license). No ffmpeg or LAME.
Can I use the audio commercially? MeloTTS is released under the MIT license; check your own use case and the source text's rights.
Is there a length limit? maxCharsPerText (default 20,000, up to 100,000) per text; up to 1,000 items per run.
Limits
- Voice quality is good and clear but below premium voices such as ElevenLabs; names, abbreviations and mixed-language text may be mispronounced.
- One voice per language (no speed, pitch or speaker choice).
- Subtitle timing is exact at chunk boundaries and estimated within a chunk (see above).
- Pages that need a login, or block automated reading, return a free failed row.