HeadVox
Script → voiceover + word‑aligned SRT/VTT captions, in one command. Open‑source Python CLI & library for talking‑head videos, explainers and Shorts. Chinese · English · Japanese.
HeadVox is a free, MIT‑licensed command‑line tool and Python library that turns a plain‑text or Markdown script into a natural‑sounding neural text‑to‑speech voiceover, and writes SRT and WebVTT captions timed to the actual spoken words plus a JSON manifest with per‑word timestamps. It can then put the voiceover and captions onto a video clip with ffmpeg — looping the clip to length and ducking background music under the voice. It is built for people who make talking‑head videos, explainers, course lessons, product demos and YouTube Shorts / TikTok / Bilibili / Douyin clips, and who are tired of hand‑timing subtitles.
pip install "headvox[edge]"
headvox script.md -o out/ --voice en-female --video avatar.mp4
# out/voiceover.mp3 voiceover.srt voiceover.vtt voiceover.json voiceover.mp4
▶ Hear real, unedited output (Chinese and English, captions scrolling from the generated VTT): https://huggingface.co/spaces/headvox/headvox
Contents
- Why HeadVox · Features · How it compares
- Install · Quick start · Writing a script
- Recipes · Python API · Timing manifest
- Voices · Troubleshooting · FAQ · How it works
Why HeadVox
A short narrated video normally takes three separate, fiddly jobs: generate the audio, time the subtitles by hand, and mux both onto the picture. Change one sentence and you redo all three. Generic TTS tools give you an MP3 and, at best, one caption per sentence — fine for an audiobook, too long and too late for a vertical video, and awkward for Chinese or Japanese where lines must break by width, not by spaces.
HeadVox treats audio, captions and timing as one artifact, generated from one script, so they cannot drift apart.
Features
| 🎯 Word‑aligned captions | Cues come from the TTS engine's real word‑boundary timestamps, not from estimating by character count — so the 40th caption is as tight as the first. |
| 🀄 CJK‑aware line breaking | Chinese/Japanese characters count as two columns; lines break at punctuation inside a width budget (--caption-chars), so mixed 中文 + English never runs off a 9:16 screen. |
| ⏸️ Pacing you control | Automatic sentence (250 ms) and paragraph (700 ms) pauses, plus [pause], [pause 1.5s], [pause 400ms] anywhere in the script. |
| 📝 Markdown‑aware | Headings, emphasis, links, code fences and list markers are reduced to the words a narrator would actually say. |
| 🧭 Per‑word JSON manifest | Start/end milliseconds for every segment and word — ready for lip‑sync / avatar tools, kinetic typography, or your own caption styling. |
| 🎬 One‑step video | Loop a talking‑head clip to the voiceover length, duck a music bed with sidechain compression, attach soft subtitles or burn them in. |
| ⚡ Clip cache | Every segment is cached by text + voice settings; re‑rendering after a one‑word edit only re‑synthesizes that sentence. |
| 🧩 Pluggable backends | edge (free online neural voices, no API key) and sine (offline, for tests and dry runs). Add your own engine in ~10 lines. |
| 🪶 Tiny footprint | Pure Python, zero required dependencies; needs ffmpeg. No model weights are bundled or downloaded. |
How it compares
Honest positioning — pick the tool that fits the job:
| You want… | Good fit |
|---|---|
| One‑liner TTS of a short string to MP3 | the edge-tts CLI itself |
| A full "topic → AI script → stock footage → video" generator | an end‑to‑end short‑video pipeline |
| Subtitles for a video that already has speech | a Whisper‑based transcription tool |
| Your own script → voiceover + captions that match it word‑for‑word, CJK‑friendly, with pause control, a reusable timing file, and optional mux onto your own clip | HeadVox |
HeadVox is deliberately the focused, composable piece: it does one job well and hands clean files (MP3/SRT/VTT/JSON/MP4) to whatever editor or pipeline you already use.
Install
pip install "headvox[edge]" # with free online neural voices (recommended)
pip install headvox # library + offline 'sine' backend only
Requirements: Python 3.9+, and ffmpeg with ffprobe on your PATH (https://ffmpeg.org/download.html; macOS brew install ffmpeg, Ubuntu sudo apt install ffmpeg, Windows winget install ffmpeg).
Quick start
headvox talk.md -o out/ # script in, files out
headvox talk.md -o out/ --voice zh-male --rate +8 # different voice, a bit faster
headvox talk.md --dry-run # preview segmentation, no TTS call
echo "Hello from HeadVox." | headvox - -o out/ --voice en-female
Main options (headvox --help for all):
| Option | Default | What it does |
|---|---|---|
-v, --voice |
zh-female |
preset (zh-female, zh-male, en-female, en-male, ja-female, ja-male) or any edge‑tts voice id |
--rate / --pitch / --volume |
0 |
speed %, pitch Hz, volume % (e.g. +8, -5) |
--format |
mp3 |
mp3, wav, m4a |
--sentence-pause / --paragraph-pause |
250 / 700 |
silence in ms |
--caption-chars |
42 |
caption width budget (CJK char = 2) |
--video |
– | clip to put the voiceover on |
--fit |
loop |
loop the clip to the audio length, or cut to audio |
--music / --music-volume |
– / 0.12 |
background bed, looped and ducked |
--burn-subs / --no-subs |
off | burn captions into the picture / attach none |
--proxy |
– | HTTP proxy for the online backend (or HEADVOX_PROXY) |
Writing a script that sounds good
- One idea per sentence. Shorter sentences give shorter, punchier captions and more natural breathing.
- Use blank lines between paragraphs — they become longer pauses (
--paragraph-pause). - Add beats deliberately:
That's it. [pause 0.8s] Now the fun part. - Spell out what should be said: write "two thousand twenty‑six" or "v zero point one" if the engine mispronounces a token.
- Markdown is fine —
# Headingsare spoken as plain sentences,**bold**loses its asterisks, code fences are skipped. - For vertical video (9:16) try
--caption-chars 28; for 16:9 the default 42 works well.
Recipes
YouTube Shorts / TikTok / Douyin (9:16, burned‑in captions)
headvox short.md -o out/ --voice en-male --rate +6 --caption-chars 28 \
--video portrait_avatar.mp4 --burn-subs --music bed.mp3
Course lesson with toggleable subtitles (16:9)
headvox lesson-03.md -o lesson-03/ --voice zh-female --video slides.mp4 --fit audio
Bilingual versions from two scripts
headvox intro.zh.md -o out/zh --voice zh-female
headvox intro.en.md -o out/en --voice en-female
Import into an editor — drop voiceover.mp3 + voiceover.srt into Premiere Pro, DaVinci Resolve, Final Cut (via SRT import) or CapCut/剪映; the captions land on the right frames.
Batch a folder
for f in scripts/*.md; do headvox "$f" -o "out/$(basename "$f" .md)"; done
Unchanged sentences come from the cache, so re‑runs are fast.
Python API
from headvox import synthesize, Script, VoiceSettings
res = synthesize(
Script.from_file("talk.md"),
"out/",
backend="edge",
settings=VoiceSettings(voice="zh-CN-XiaoxiaoNeural", rate_pct=5),
)
print(res.duration_ms, "ms,", len(res.cues), "captions")
for cue in res.cues:
print(cue.start_ms, cue.end_ms, cue.text)
synthesize() returns the paths of the audio, SRT, VTT and manifest, the total duration, the caption cues and per‑segment word timings.
Custom backend
from headvox.backends import SegmentAudio, WordMark, register_backend
class MyBackend:
name = "mine"
def synthesize_segment(self, text, settings):
audio, fmt, dur = my_tts(text, settings.voice) # bytes, "wav"/"mp3", ms
return SegmentAudio(audio, fmt, dur, [WordMark("hi", 0, 200)])
register_backend("mine", lambda **kw: MyBackend())
Then headvox script.md -b mine. Any engine that can report word timings (or that you align afterwards) gets HeadVox's captioning, pacing, caching and muxing for free.
Timing manifest
voiceover.json holds everything downstream tools need:
{
"tool": "headvox",
"backend": "edge",
"duration_ms": 19600,
"segments": [
{"index": 0, "text": "Hi everyone, and welcome back.",
"start_ms": 250, "end_ms": 2232,
"words": [{"text": "Hi", "start_ms": 250, "end_ms": 412}]}
],
"cues": [{"index": 1, "start_ms": 250, "end_ms": 2232, "text": "Hi everyone, and welcome back."}]
}
Use it to drive mouth shapes on an avatar, highlight the active word (karaoke‑style captions), cut B‑roll on sentence boundaries, or generate chapter markers.
Voices
| Preset | edge‑tts voice |
|---|---|
zh-female |
zh-CN-XiaoxiaoNeural |
zh-male |
zh-CN-YunxiNeural |
en-female |
en-US-AvaMultilingualNeural |
en-male |
en-US-AndrewMultilingualNeural |
ja-female |
ja-JP-NanamiNeural |
ja-male |
ja-JP-KeitaNeural |
Any other edge‑tts voice id works too (edge-tts --list-voices), which opens up many more languages and accents; caption line‑breaking is tuned for CJK and Latin scripts.
Troubleshooting
| Symptom | Fix |
|---|---|
ffmpeg not found |
install ffmpeg and make sure ffmpeg and ffprobe are on PATH |
NoAudioReceived from edge |
the voice id is wrong or temporarily unavailable — try another voice, or retry |
| Network blocked / corporate proxy | --proxy http://host:port or export HEADVOX_PROXY=... |
--burn-subs fails |
your ffmpeg lacks libass; use soft subtitles (default) or install a full ffmpeg build |
| Captions too long on vertical video | lower --caption-chars (e.g. 24–28) |
FAQ
Is HeadVox free? Yes. HeadVox is MIT‑licensed. The default edge backend uses the free online service behind Microsoft Edge's read‑aloud via the edge-tts package; it needs internet but no API key or account.
Does it work offline? Parsing, stitching, captioning and video muxing are fully local. Speech synthesis with edge needs internet; plug in a local engine through the backend API for a fully offline setup.
Why are the captions more accurate than splitting by sentence? HeadVox uses the word‑boundary events the engine emits while speaking, trims the leading/trailing silence some engines add, and then places line breaks — so each cue starts when its first word is actually heard.
Can it generate a talking‑head avatar? No — HeadVox doesn't render faces. It produces the voiceover, captions and per‑word timings that an avatar or lip‑sync tool consumes, and it can put the result on an avatar clip you already have.
Can I use the output commercially? HeadVox's code is MIT. Rights to synthesized speech depend on the TTS service you use — check its terms for your use case.
Is this affiliated with Microsoft or edge‑tts? No. HeadVox is an independent, original project that uses edge-tts as one optional backend.
How it works
- Parse — split the script into speakable segments, strip Markdown, honour
[pause]directives. - Synthesize — call the backend per segment, cached by text + voice settings.
- Assemble — build one 24 kHz track, trimming engine padding so pauses are exact.
- Caption — build cues from word boundaries, breaking at punctuation within a CJK‑aware width budget.
- Mux (optional) — ffmpeg puts it on video, loops the clip, ducks music, adds soft or burned‑in subtitles.
Development
git clone https://github.com/yyert123/headvox.git
cd headvox
pip install -e ".[dev]"
pytest # runs fully offline via the 'sine' backend
Issues and pull requests are welcome — especially new backends, more languages' line‑breaking rules, and caption styles.
Citation
If HeadVox helps your research or course, see CITATION.cff.
License
MIT. HeadVox is original work and is not affiliated with Microsoft or the edge-tts project.
Metadata
Release files for headvox 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| headvox-0.1.1.tar.gz | 30.8 kB | Without provenance | Details for headvox-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| headvox-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for headvox-0.1.1-py3-none-any.whl |
Total release size: 56.0 kB
Release files / headvox-0.1.1.tar.gz
| Download URL | headvox-0.1.1.tar.gz |
|---|---|
| Size | 30.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f374740f69beb694ebe46c8d780e6dad85fbdec4ca021987f57794ae9c38ef51
|
|
BLAKE2b-256 checksum How to use checksums |
3da8c8edc5ccfa215543a968ce2642365dddd0620bfc046e7d6a4250870baff3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / headvox-0.1.1-py3-none-any.whl
| Download URL | headvox-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
799d1b5a5e67a613e3b3f2eb0ac58676e7f6f0d28ad564b0d4cd545cad241029
|
|
BLAKE2b-256 checksum How to use checksums |
3e32d46fe6a4d72585cfc693f280546b94b8e5f582e8b90946d000c4cb0272e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Security for headvox 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.