any book, read aloud and highlighted

A free desktop app, English, Mandarin and Cantonese

Turn any EPUB into an audiobook and read along as it plays.

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.

Hear the read-alongen-US-GuyNeural, 73 seconds

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.

14

sections found in a 45,646-word book, three flagged as likely junk (contents, "Also by", copyright).

~5h 4m

estimated runtime for that book, at about 900 characters a minute for English (300 for Chinese).

3

languages: English, Mandarin (Mainland and Taiwan voices) and Cantonese (Hong Kong voices).

.mp3 / .m4b

per-chapter files with ID3 tags and cover art, or one audiobook file with chapter markers.

Step one

It finds the chapters and flags the junk

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

Timed by the speech engine

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.

86segments timed by edge-tts in one part
77sentences from the app's own splitter for the same part

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.

Crash-safe
Each chapter renders to a .part file and is renamed into place with os.replace; a re-run skips finished chapters
Speed
ffmpeg atempo renders a pitch-preserving copy at the chosen speed, cached
Player
Light and dark themes, font, size and highlight settings, auto-advance, resume, a sleep timer, keyboard shortcuts
Export
Per-chapter .mp3 with ID3 tags and embedded cover (mutagen), or a single .m4b with chapter markers (ffmpeg)

Six versions

V6 is about finding ffmpeg

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

Desktop only, and you bring the books

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

Free and local apart from the voices

Voices
Microsoft edge-tts neural voices, no API key; default en-US-GuyNeural
Languages
English, Mandarin (zh-CN, zh-TW), Cantonese (zh-HK)
EPUB
ebooklib and BeautifulSoup
Interface
Tkinter GUI with the read-along player, plus a command-line version; pygame for playback
Optional
mutagen for tags and cover art; ffmpeg for speed control and .m4b
Related
Podcastify stages the same kind of source for two voices; the Mandarin Learning Reader reuses this EPUB pipeline