- Python 100%
| img | ||
| src/pinyin_mpv | ||
| .gitignore | ||
| CHANGELOG.txt | ||
| LICENSE.txt | ||
| pyproject.toml | ||
| README.md | ||
pinyin mpv
HOWTO play movies with mpv while displaying pinyin and English subtitles
simultaneously, both at the bottom: pinyin above the English.
How it works
- Download — download a video and all of its subtitles with
yt-dlp. Works with any site yt-dlp
supports; on YouTube, extra JavaScript runtime features are enabled when
nodeis installed (see "Requirements" below). All manual and auto-generated subtitles are fetched; YouTube's machine-translated caption variants are skipped on purpose, since mass-requesting them triggers HTTP 429 rate limiting. Playlists are supported; unavailable videos (geo-restricted, deleted, ...) are skipped with a warning instead of aborting the run. Completed videos are recorded in adownload-archive.txtfile in the download directory, so re-running the same command skips them entirely — no re-extraction, no repeated subtitle downloads (delete that file to start over). - Pinyin — subtitles rarely come in a pinyin variant, so one is generated
from the Simplified Chinese (hanzi) subtitles using
pypinyin with the extended
pypinyin-dict phrase
dictionary (better polyphonic-character readings and neutral tones).
Tone marks are used (e.g. "hǎo"), not tone numbers ("hao3"), and
syllables are grouped by word with standard orthography
("péngyou", "xī'ān", not "péng yǒu", "xīān") using
jieba segmentation. Each syllable is
colored by tone (Pleco-style: 1st red, 2nd green, 3rd blue, 4th
purple, neutral gray;
--no-colorfor plain pinyin) via SRT<font color>tags — generated tracks are always.srtregardless of input format, because mpv honors font colors in SRT but strips all styling from WebVTT. The pinyin track is then merged with the reference-language subtitle(s) found next to it (English by default; use--lang es,--lang fr, ..., repeat--langfor several, or--lang allfor every available language), producing one track per language (movie.zh-Hans.pinyin-en.srt, ...) where every cue shows the pinyin line(s) directly above the reference line(s). Cues are extended to stay on screen until the next cue appears (up to 10 seconds), so subtitles don't flash by too fast. This command writes all subtitle files; re-run it whenever the hanzi or reference subtitles change. - Play —
playis read-only: it finds the merged track (movie.zh-Hans.pinyin-en.srt,--lang esselects...pinyin-es.srt, ...) and passes it tompv, which renders it as a single contiguous block at the very bottom of the screen (mpv's default bottom subtitle margin is disabled, so the text bottom really is at the bottom edge). A missing or stale merged track only prints a warning with thepinyincommand to (re)generate it; playback falls back to the pinyin-only track (or uses the stale track as-is).
Requirements
- Python 3.11+
mpvandffmpeg/ffprobeinstalled- Optional: node.js. If
nodeis onPATH, the downloader enables yt-dlp's JavaScript runtime features (--js-runtimes node,--remote-components ejs:github), which YouTube uses for its signature/throttling challenges. If node.js is not installed, those features are simply skipped: downloading still works for yt-dlp sites in general, but some YouTube videos may throttle or fail to download.
Install
python -m venv venv
./venv/bin/pip install .
Usage
# 1. Download a video and all its subtitles (into the current directory)
# (max 1080p by default; use --quality 720p/1440p/4k/best to change)
pinyin-mpv download "https://www.youtube.com/watch?v=..."
# 2. Convert the Chinese subtitles into tone-colored pinyin subtitles
# and merge with the reference language(s) next to them (English
# by default): "movie.zh-Hans.vtt" becomes
# "movie.zh-Hans.pinyin.srt" plus a merged
# "movie.zh-Hans.pinyin-en.srt"
pinyin-mpv pinyin "movie.zh-Hans.vtt"
# ...other languages (repeatable; "all" = every available one):
pinyin-mpv pinyin --lang es --lang fr "movie.zh-Hans.vtt"
pinyin-mpv pinyin --lang all "movie.zh-Hans.vtt"
# (a file with no Chinese characters — e.g. an English fansub
# mislabeled as "zh" — is skipped with a warning)
# 3. Watch: pinyin directly above English (default), at the very bottom
pinyin-mpv play "movie.webm"
# ...or with another reference language, e.g. Spanish (merged in
# step 2):
pinyin-mpv play --lang es "movie.webm"
pinyin writes all subtitle files (always .srt, tone-colored);
play writes none. play
auto-detects *.pinyin.srt, *.pinyin-<lang>.srt and
*.<lang>.vtt/.srt files matching the video filename (--lang selects
the merged track, default en; if English is missing but exactly one
other language is available, it is used). A missing or stale merged
track prints a warning with the pinyin command to (re)generate it and
playback continues — with the pinyin-only track if no merged file
exists, or with the stale file as-is. Pass --pinyin FILE to override
the pinyin file. Any other subtitle files with matching names (e.g. the
original hanzi subtitles) are auto-loaded by mpv too — press j/J to
cycle tracks. Run pinyin-mpv --help or pinyin-mpv <command> --help
for details.
License
Apache 2.0. See LICENSE.txt.
Copyright © 2026 Jeff Moe
