A free desktop app, English, Mandarin and Cantonese
Point it at a .epub and it detects the chapters, flags front and
back matter, and renders chapter-named MP3s (or one .m4b with
chapter markers) with Microsoft's free edge-tts neural voices. The player
then highlights each sentence as it is spoken, timed by the boundary events
edge-tts emits with the audio. It needs no API key and costs nothing to run.
The opening of Alice's Adventures in Wonderland (public domain),
rendered on 2026-10-28 by the V6 engine's synthesize_chapter() with chapter
announcements on. The highlight is driven by the
readalong-sample.subs.json sidecar it wrote, the same file the desktop player
reads: nine units, each the span edge-tts timed. Select a unit to jump to it.
sections found in a 45,646-word book, three flagged as likely junk (contents, "Also by", copyright).
estimated runtime for that book, at about 900 characters a minute for English (300 for Chinese).
languages: English, Mandarin (Mainland and Taiwan voices) and Cantonese (Hong Kong voices).
per-chapter files with ID3 tags and cover art, or one audiobook file with chapter markers.
Step one
Before synthesizing anything, --list parses the book and prints
what it found: chapters, front and back matter, word counts, an
estimated runtime, and how many parts each chapter will be split into.
$ python "App V6/epub_to_audiobook_v6.py" --list "What I Talk About When I Talk About Running.epub" [*] Loading: What I Talk About When I Talk About Running.epub Title : What I Talk About When I Talk About Running Author: Haruki Murakami Voice : en-US-GuyNeural Rate: +0% Subs: on [*] 14 chapters - ~45,646 words - ~5h 4m estimated - ~12 min/part 1 Contents ~ 95 w (1 file) [junk?] 2 Foreword ~ 751 w (1 file) 3 Chapter One ~ 5,326 w (3 parts) 4 Chapter Two ~ 6,294 w (4 parts) 5 Chapter Three ~ 5,281 w (3 parts) 6 Chapter Four ~ 4,817 w (3 parts) 7 Chapter Five ~ 3,679 w (2 parts) 8 Chapter Six ~ 4,990 w (3 parts) 9 Chapter Seven ~ 3,133 w (2 parts) 10 Chapter Eight ~ 4,002 w (2 parts) 11 Chapter Nine ~ 5,832 w (3 parts) 12 Afterword ~ 1,221 w (1 file) 13 Also by Haruki Murakami ~ 62 w (1 file) [junk?] 14 Copyright ~ 163 w (1 file) [junk?] (dry run, nothing synthesised)
Output of the V6 command-line tool on an EPUB of Haruki Murakami's memoir, which is not in the repo. The tool's last line prints an em dash, shown here as a comma.
The [junk?] flags come from title and filename patterns plus a
minimum length. Nothing is dropped silently; the GUI lets you untick flagged
sections, and --skip-junk drops them on the command line.
Read-along
V2 split each chapter into sentences with its own splitter, then matched those sentences to edge-tts's boundary events by greedy text matching. The two rarely produced the same number of segments, so the highlight drifted further out of sync the longer a track ran.
Since V3 the player uses edge-tts's boundary events directly as the highlight
units, so each highlighted span is exactly the span the engine timed. The sample
at the top shows the mismatch on a small scale: edge-tts timed nine units for that
passage, and the engine's own split_sentences() finds six. Units
are made contiguous so the highlight never flickers between sentences, and
each file's audio duration is stored for an exact seek bar. The timings live in
a .subs.json sidecar next to each MP3.
Chinese needed its own handling: splitting on 。!?;, sizing parts by characters at about 300 a minute, and switching the reader to PingFang SC, HK or TC. edge-tts's own Chinese sentence timing keeps Mandarin and Cantonese in sync the same way.
.part file and is renamed into place with os.replace; a re-run skips finished chaptersatempo renders a pitch-preserving copy at the chosen speed, cached.mp3 with ID3 tags and embedded cover (mutagen), or a single .m4b with chapter markers (ffmpeg)Six versions
V1 was the pipeline (extraction, chapter detection, synthesis, atomic writes
and resume), and V2 added the timing sidecars, tags and .m4b.
V3 and V4 brought the interface and the drift fix; V5 added Chinese.
V6 is almost entirely ffmpeg discovery. It looks in the usual install
locations (winget, Chocolatey, Scoop, Homebrew, /usr/bin, a
bundled ffmpeg/ folder, or FFMPEG_DIR) as well as
PATH, prints the exact install command for your OS when ffmpeg is missing, and
will use an ffmpeg shipped next to the app. Speed control and .m4b
export now work on a fresh machine.
Limitations
It is a Python desktop app with a Tkinter interface. The read-along at the top
of this page replays the engine's real output in the browser, but the app itself
does not run there. Launchers are included for Windows and macOS, plus a script
that builds a double-clickable macOS .app.
Synthesis needs an internet connection, because the voices are Microsoft's
hosted edge-tts service. ffmpeg is optional and needed only for speed control
and .m4b. The repository ships no books, and its only audio is the
73-second public-domain sample above; use books you own or public-domain titles,
for personal listening.
There are no screenshots of the player on this page. A capture of the desktop window was blocked by a macOS screen-recording permission prompt and has not been retaken. The command-line listing and the read-along sample are the captured output shown here.
Built with
.m4b