Turn PDF, EPUB, DOCX, Markdown, HTML, TXT or RTF into an MP3 audiobook. Free Edge neural TTS needs no API key, OCR recovers scanned pages, 70+ languages are auto-detected, and OpenAI or ElevenLabs voices work with your own key. Long books split into chapter-sized parts.
All notable changes to this Actor will be documented in this file.
[Unreleased]
Pricing
Start fee cut from $0.12 to $0.05 and OCR page fee cut from $0.10 to
$0.03; the $0.04 audio minute is unchanged. Measured platform cost is
$0.0007 for a failing run and $0.28 for a 500-page book, so the old start fee
was 170x the cost it existed to cover and was pure friction on the short calls
AI agents make most often. PRICING.md documents the measured model and the
margin table behind the new numbers.
maxMemoryMbytes lowered from 8192 to 4096. The pipeline runs at 21% CPU, so
more memory buys nothing, and the Apify MCP server rejects Actors that ask for
more than 4 GB.
Cost ceilings now stop the run instead of giving audio away
maxCostUsd no longer delivers a whole audiobook for the capped price. It
used to clamp the charge while still narrating everything, so a caller could
set the floor value on a 500-page book and receive ~18 hours of audio for
$0.12 against $0.28 of platform cost. Narration now stops at the last chunk
the budget covers and the run returns the new status: "capped" with the
audio produced so far.
The run-level "Max total charge" limit is honoured.Actor.charge returns
eventChargeLimitReached and chargedCount; both were discarded, so a run
started with a low platform limit kept synthesizing audio nobody could be
billed for. Both are now read, and either ceiling stops narration.
OCR is bounded by the cost ceiling before it runs. OCR is charged per page
during extraction, before the pre-flight cost gate, so a 500-page scan could
bill past the ceiling before the gate was ever reached.
The start fee mirrored in the cost field now scales with allocated memory,
matching how the platform actually charges it (one event per GB).
Usable as an MCP tool for AI agents
documentUrl gained a default, so a call with no arguments produces audio
rather than an input error. This also gives Apify's daily health check, which
runs with empty input, real work to verify.
Every input description rewritten for an LLM caller and kept inside the MCP
server's 500-character truncation limit.
The dataset row leads with status and a plain-language statusMessage, and
carries audioUrls, durationHuman, sizeBytes, audioFormat, title and
language. parts and failedChunkIndexes are capped so a long book cannot
bloat a tool response. Every audio link is a direct, publicly fetchable MP3
URL, so an agent never pulls a binary through the tool result.
Added an overview dataset view and a field-level dataset schema; the output
schema now points at both views.
README documents the hosted MCP route (https://mcp.apify.com?tools=...), a
Claude Desktop and Claude Code configuration, an example tool call and the
direct API route.
Categories corrected to AI, FOR_CREATORS, EDUCATION (the platform caps
categories at three), and the Actor description shortened to fit the 300-character
platform limit that the previous text exceeded.
Run reliability
Expected outcomes no longer fail the run. A bad URL, an empty input, a
document with no extractable text or a TTS refusal now writes the labelled
status: "failed" dataset row and exits 0. Only an unclassified error exits
non-zero. Crashing on these hid the explanation from the user and reported the
Actor as broken to Apify's daily health check, which runs empty input.
Several document sources no longer conflict.documentUrl carries a demo
prefill, so uploading a file used to fail validation through no fault of the
user. Sources are ranked instead — upload, pasted text, base64, URL — and the
chosen one is logged.
Audio minutes are billed per part as each part is uploaded, not once at the
end, so a run that hits its timeout mid-book still charges for the audio it
already delivered. The running total keeps the bill identical to a single
end-of-run charge.
Live default run options corrected to 7200s / 2048 MB. The 300s default could
not finish a full-length book.
[0.1.1] - 2026-06-08
Production-hardening: OCR, modern PDF engine, security, billing safety
New capabilities
OCR fallback for scanned / image-only PDFs — pages with no text layer are
auto-rendered (poppler pdftoppm) and OCR'd (Tesseract: EN, ES, FR, DE, IT,
PT, NL) and narrated. New ocr-page-processed billing event ($0.10/page),
charged only for pages that actually need OCR. Toggle with enableOcr.
Encrypted PDF support — decrypt password-protected PDFs via pdfPassword.
Proxy support — optional proxyConfiguration for the Document URL fetch.
ID3 tags on every MP3 part (title / album / track / genre=Audiobook).
Engineering
Replaced pdf-parse (2018 PDF.js, unmaintained) with unpdf — current,
serverless-friendly PDF.js. Per-page extraction via a direct array index
(no render-hook page-order invariant to desync).
Real unit test suite (Node test runner) for chunking, page-range parsing,
SSRF address checks, format detection, strippers, key sanitization, voice +
OCR-language mapping. ESLint flat config added.
Security
SSRF guard on Document URL fetch: rejects non-http(s) schemes and any host
resolving to private / loopback / link-local / CGNAT ranges (incl. cloud
metadata 169.254.169.254). Redirects are followed manually and re-validated
at every hop.
Added .dockerignore so .env / secrets / local state never enter image layers.
Pricing (PPE) — simpler + loss-proof
Single value meter: removed pdf-page-narrated; narration is now billed
purely per audio-minute-generated ($0.04/min) so the same value isn't
double-billed on two axes.
apify-actor-start raised to $0.12 (from the $0.00005 platform default):
it's the only revenue on a failed / 0-page run, so it's sized to stay
margin-positive on failures after Apify's 20% cut while remaining trivial
against value events on real documents (and absorbed by free trials).
ocr-page-processed stays $0.10. Net effect: ~90%+ margin on every real run,
no loss on failed runs.
Billing safety
maxCostUsd now also clamps the actual audio-minute charge (not just the
pre-flight estimate), so slow-speech / CJK runs can't bill past the cap.
maxCostUsd floor is now $0.12 (the unavoidable actor-start fee); sub-floor /
zero values are rejected instead of silently disabling the cap.
[0.1.0] - 2026-06-02
Initial public release as Text to Audio Narrator
Multi-format document narration: PDF, Markdown, plain text, and HTML in, MP3 out.
Supported inputs (7 formats)
PDF (.pdf) — native text-layer extraction (no OCR)
DOCX (.docx) — Word documents via mammoth: styles, lists, tables, footnotes
EPUB (.epub) — ebooks via epub2: spine-ordered chapter walk, HTML stripped per chapter
Markdown (.md, .markdown, .mdx) — syntax stripped before TTS so the voice reads natural prose
Plain text (.txt, .text) — UTF-8 with BOM handling
HTML (.html, .htm, .xhtml) — tags stripped, entities decoded