中文 Mandarin Teacher

A single-user Mandarin learning engine I built for myself — spaced repetition driven by an append-only event log, with speech scoring on my own GPU. One learner, one machine, zero recurring costs.

42
words in training
4
proven solid (passed a retention test)
763
reps logged since August 2026
1.9s
median time to comprehend a sentence
5
study days
14
level · 5,606 points

HSK coverage, by ear

known by listening in the corpus official level size
HSK 1 HSK 1: 150 words in the official list 149 of 150 words have sentences and audio in the corpus 3 known by ear so far 3 / 150 HSK 2 HSK 2: 150 words in the official list 139 of 150 words have sentences and audio in the corpus 0 known by ear so far 0 / 150 HSK 3 HSK 3: 300 words in the official list 184 of 300 words have sentences and audio in the corpus 1 known by ear so far 1 / 300

Denominators are the official HSK level sizes, not the corpus — coverage is only claimed against the real target. The corpus currently spans HSK 1–3: 810 sentences with 6,480 audio clips across 503 words, and it grows ahead of the learning frontier.

How it works

The event log is the source of truth

Every rep is one row in an append-only log — SQLite triggers physically refuse updates and deletes. Scheduling state is a cache rebuilt by replaying the log, so a scheduling bug can never destroy history: fix the code, replay, and the past is reinterpreted rather than lost.

Scheduling that separates skills

FSRS spaced repetition, with a card per (word, skill) pair — hearing 累 and saying 累 are tracked as different memories, because they are. Listening gates speaking: nothing is asked of the mouth before the ear can verify it. New vocabulary is capped per day; past the cap, the system serves practice on known words instead of more novelty.

Speech scoring on local hardware

Attempts are transcribed by faster-whisper (large-v3, CUDA) and pitch-tracked with Praat. Tone feedback does not depend on the transcript: MFCC features aligned by dynamic time warping carry native syllable boundaries onto the learner's audio, so tones are judged even when recognition fails. And a recogniser failure is never graded as a learner failure — undecodable or hallucinated results are discarded, not scored.

Honest grading

The interface commits before it reveals. Quiz answers are graded server-side, dictation withholds the text until the answer is locked in, and replays are counted against the grade automatically — the learner never has to be disciplined enough to self-report.

Local by construction

Everything — database, scheduler, models, audio — runs on one machine. Voice recordings never leave it, and there is no per-request bill anywhere in the loop: the marginal cost of a rep is electricity.

TypeScript · Hono · React · SQLite (node:sqlite) · ts-fsrs · Python · faster-whisper · Praat/parselmouth · CUDA