Community编程与开发github.com

chinese-tts

让程序把中文(夹英文、数字、链接、代码)念出来时的文本规范化(TN)和语音合成工程:先转念法再切句、流式输出时怎么扣住数字边界、年份/电话/验证码/单位/温度/百分比/范围/分数/网络用语怎么念、念法替换表、念错了怎么查;本机 TTS 引擎(Kokoro、Matcha、CosyVoice、Qwen3-TTS、sherpa-onnx、vLLM、WSL2)的选型、首句延迟、取消、缓存、后备音源、显存;语音输入和插话。附 139 条验收过的「原文 → 念法」对照用例和一个检查脚本。只要用户在做朗读、语音助手、AI 角色说话、有声读物、播报、TTS 前处理,或者抱怨「数字念错了」「年份念成两千零二十六」「电话号码念成几亿」「链接被逐字念」「英文被跳过」「流式念出来和整句不一样」「取消以后下一句很慢」,就用这个 skill,即使用户没说「TN」或「文本规范化」。Also use for English requests about Chinese text normalization for TTS, number/date reading in Mandarin speech synthesis, or streaming TTS latency.

chinese-tts 是什么?

chinese-tts is a Claude Code agent skill that 让程序把中文(夹英文、数字、链接、代码)念出来时的文本规范化(TN)和语音合成工程:先转念法再切句、流式输出时怎么扣住数字边界、年份/电话/验证码/单位/温度/百分比/范围/分数/网络用语怎么念、念法替换表、念错了怎么查;本机 TTS 引擎(Kokoro、Matcha、CosyVoice、Qwen3-TTS、sherpa-onnx、vLLM、WSL2)的选型、首句延迟、取消、缓存、后备音源、显存;语音输入和插话。附 139 条验收过的「原文 → 念法」对照用例和一个检查脚本。只要用户在做朗读、语音助手、AI 角色说话、有声读物、播报、TTS 前处理,或者抱怨「数字念错了」「年份念成两千零二十六」「电话号码念成几亿」「链接被逐字念」「英文被跳过」「流式念出来和整句不一样」「取消以后下一句很慢」,就用这个 skill,即使用户没说「TN」或「文本规范化」。Also use for English requests about Chinese text normalization for TTS, number/date reading in Mandarin speech synthesis, or streaming TTS latency.

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/RedCarpG/redcarpg-skills/tree/HEAD/skills/chinese-tts

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Chinese Text-to-Speech: Text Normalization and Engineering

This skill comes from an AI desktop pet that talks all day (see "Source & Maintenance" at the end): Claude streams responses, sentence by sentence, to a local TTS engine to read aloud. All rules below are tested, and numbers are measured.

One-sentence principle: Convert the pronunciation on your side; the engine just speaks it. If you leave it to the engine, changing the engine changes the pronunciation; even switching to an off-the-shelf TN library causes several regressions. Use off-the-shelf libraries (wetext, PaddleSpeech) as references and to fill gaps.

Workflow

Model stream text
  → ① Filter: remove decorations, emoji, list markers; replace code blocks, tables, links with a one-sentence summary (must recognize split tokens in streaming)
  → ② Convert to pronunciation: numbers, times, units, symbols, pronunciation replacement table (hold boundaries in streaming)
  → ③ Split sentences: first segment at the first comma, then split at commas when exceeding 40 characters
  → ④ Synthesize: only generate ahead by about 20 seconds; truly stop inference on interruption

Order is fixed: convert first, then split. Splitting first then cleaning caused three errors in practice:

OriginalResult after split-firstProblem
下午14:30开会下午14: / 30开会Colon treated as comma; time split
看这里:https://…/pull/7 就行https: / //…/pull/7 就行Link split in half; address read character by character
大概3~5天大概35天~ removed as decoration; read as "thirty-five days"

The half-width : is only treated as a comma when followed by whitespace.

Streaming Must Hold Boundaries

Correct for full sentences doesn't mean correct for streaming. When character-by-character streaming, "工作了26年" and "80年代" are read as "two-six years" and "eight-zero generation" because the following characters haven't arrived yet; the -10°C part was read as English.

  • Wait 2 more characters after a digit before releasing; recognize units even with a space in between (hold "跑了 5 " and wait for "km").
  • When moving to the next segment, carry over the last few characters (to know "了 26 年" you need the preceding "了").
  • Hold at most 200 characters; for code blocks and tables, hold at most 4000; release when limit is reached.
  • Each test must run both character-by-character and as a full sentence; results must match.

Quick Rule Reference (see references/rules.md for details)

CategoryExamplePronunciation
Year2026年, 2026届, 26年见Digit by digit: èr líng èr liù nián, èr líng èr liù jiè, èr liù nián jiàn
Count of years工作了26年, 80年代, 26年前Numeric: èr shí liù nián, bā shí nián dài, èr shí liù nián qián
NumbersPhone, verification code, 编号27149, 房间1201Digit by digit, 1 read as "yāo", pause at hyphens and spaces
Five-digit number95588 / 价格 12999No quantifier, not ending in 0, not preceded by money → number; otherwise numeric
Internet slang666, 2333, 520 alone / 666个赞, 花了888Digit by digit / numeric (only recognized from a fixed list)
2 before unit2个, 2L, 2℃liǎng gè, liǎng shēng; exception for temperature: èr shè shì dù
Units60km/h, 3kWh, 5min, 10mgměi xiǎo shí liù shí gōng lǐ, sān dù diàn, wǔ fēn zhōng, shí háo kè
Units not to convert4g网络, 5A景区, 16GBPass through as-is to the engine
Ranges, Percentages3~5%, 3-5km, -1.5~2bǎi fēn zhī sān dào wǔ, sān dào wǔ gōng lǐ, fù yī diǎn wǔ dào èr
Time14:30, 13:00, 9:05shí sì diǎn bàn, shí sān diǎn, jiǔ diǎn líng wǔ (24-hour format)
Date, Fraction10/26 交 / 有7/12的观众shí yuè èr shí liù hào / shí èr fēn zhī qī (only fraction when preceded by "有, 占, 约")
Symbols#15, 2x, x3, 100wshí wǔ hào, liǎng bèi, chéng sān, yī bǎi wàn

Validate with Test Cases

references/golden-cases.json contains 115 full-sentence cases and 24 streaming cases, all verified against the original project. scripts/check-tn.mjs tests your implementation:

node scripts/check-tn.mjs ./my-tn.mjs                  # Module must export normalize(text) and (optional) createStream()
node scripts/check-tn.mjs ./my-tn.mjs --only 号码      # Test only one group
  • Comparisons ignore whitespace and common punctuation; only compare pronunciation. Cases with note are "reference" — reported but not counted as failure.
  • Use these as acceptance criteria when writing new TN; run them after any rule change to avoid regressions.
  • Controversial pronunciations (e.g., "this computer 12999" being read as a number) are accepted by the original project. If your product wants different behavior, update the test cases and justify why.

Debugging Mispronunciations

There are four categories: text not converted to pronunciation before synthesis; polyphonic characters guessed wrong by the model; reference audio issues; random (just regenerate).

Use the current voice and two other voices to read the same sentence: if all voices mispronounce the same character, add a pronunciation replacement entry; if only one voice sounds strange, switch voices. Log both original and converted text (jsonl) every time for later analysis.

Engineering (see references/engines.md)

  • First-chunk latency: First segment only up to the first comma. With Matcha, first audio arrives 0.65s after the first character.
  • Most effective speedup is caching: CosyVoice first block 2.6–3s for uncached sentences; 6ms when cached. Pre-synthesize filler phrases ("um", "let me think") when user starts speaking.
  • Cancellation must truly stop inference: Stop vLLM by abort_request on connection drop, otherwise next sentence waits 4.9s (0.8–1.7s after implementing).
  • English may be silently skipped: Some engines don't pronounce GitHub, PR, %; re-validate English before upgrading dependencies.
  • Fallback audio source: If primary source is not ready or fails on first utterance, switch to fallback; don't retry if error occurs mid-sentence. HTTP service being up doesn't mean model is loaded; retry on 503.

Source & Maintenance

  • Source: Cirra (AI desktop pet, RedCarpG/cirra-deskpet) and its voice service cirra-voice, 2026-10 to 2026-11.
    • Code: sidecar/src/tts/speech/ (numbers.ts, units.ts, links.ts, filter.ts, overrides.ts, speech.test.ts), sidecar/src/tts/splitter.ts, sidecar/src/tts/pronunciations.ts.
    • Documentation: docs/speech.md, docs/speech-tn.md (119 three-way comparisons), docs/tts.md, docs/voices.md, docs/voice-chat.md, docs/voice-chat-2.md, docs/voice-install.md, docs/perf-checkup.md.
    • Lessons: Private repo lessons/chinese-tts.md.
  • Origin: skills/chinese-tts/ in RedCarpG/redcarpg-skills. The copy in ~/.claude/skills/ is an installed copy; do not modify directly. references/golden-cases.json was extracted from Cirra's speech.test.ts on 2026-11-10 via script; the two are not automatically synced.
  • How to modify:
    • Modify in redcarpg-skills via PR; increment version in manifest.json, validate with node scripts/validate.mjs, release with tag chinese-tts-v<version>, then reinstall local copy. Check lessons/chinese-tts.md for new items to incorporate.
    • When Cirra's TN rules change, re-extract test cases (extract [original, pronunciation] pairs from readNumbers and "streaming" groups in speech.test.ts) and use an adapter module with Cirra's compiled sidecar/dist/tts/ to run check-tn.mjs; all should pass.
    • Engine metrics (latency, real-time factor, VRAM) were measured on a machine with 8 GB VRAM and CPU lacking VNNI in 2026-10; re-measure on different hardware.
  • Changelog:
    • 2026-11-12 · 1.0.0, moved to redcarpg-skills for public release. Removed local absolute paths; source project written as links; content unchanged.
    • 2026-11-10 · Cirra · Initial version: workflow & order, streaming boundaries, quick rules and details, mispronunciation debugging, engine engineering; 139 test cases and check-tn.mjs (passed with Cirra's implementation); two test prompts in evals/.

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

frontend-verification

改完网页/前端界面(CSS、布局、组件、动画、响应式、深色模式、打印)之后怎样验证并拿出证据:先用内置浏览器预览,覆盖不到时用无头 Chrome 截图或读 DOM(预览面板被隐藏、批量截多个视口、要先进入某个状态、要拿 DOM 结果),附可直接运行的 shot.sh / shot.mjs 脚本。还收录无头 Chrome 的坑(requestAnimationFrame 动画停在第一帧、375 宽被撑成 500、深色模式跟随系统)、字体不显示或像宋体的排查、整页截图里滚动动画区块空白、vitest 排除 .claude worktree,以及桌面/手机/英文/繁體/深浅色/打印的核对清单。只要改了界面、要截图、要查响应式或深色模式、动画不动,或者准备说“界面改好了”,就用这个 skill,哪怕用户只说“看看效果”。Use after any UI/CSS/layout/animation change to verify it, take screenshots at several viewports, check dark mode / mobile / print, or debug animations frozen in headless Chrome.

immersive-cultural-ui

做重氛围、带东方古典或神秘学气质的沉浸式网页:深色夜空、细金线、薄雾、宣纸纹理、竖排中文、书法批注、景深视差、开场时逐层亮起。适用于命理排盘(八字、紫微、占星、塔罗)、黄历与二十四节气、星图、典籍诗词、博物馆展品、节庆和有仪式感的产品页。只要用户想要「有氛围、沉浸、古风、国风、东方、神秘、仪式感」的页面,或者要竖排、书法字体、星空、水墨、宣纸效果,即使没有点名风格,也用这个 skill。它提供一套带具体数值的风格配方(天书),装饰、动效、竖排和字体的做法,可复用代码和交付前检查清单。和 web-design-engineer 配合:那边管通用流程,这里管这一种风格。Also use for English requests for immersive, mystical, Chinese-classical, almanac, astrology, tarot or museum-exhibit pages.

RedCarpG/animation-capture

把会动的东西按固定时间一帧一帧录下来,做成左右对比的 GIF 或逐帧对照图,给人验收、对比改动前后、放进说明或 PR:网页的 CSS 过渡和动画、element.animate()、requestAnimationFrame 写的 JS 动画、canvas 游戏、three.js / VRM 角色、PixiJS / Live2D 角色都适用。附脚本:record.mjs(无头 Chrome + 假时钟,页面不用改,渲染多慢时间轴都准,两次录的逐帧一样)、make_gif.py(几个变体并排、标签、共用调色板)、clock-shim.js。还讲先逐帧记数值再录 GIF、开关前后怎么做变体、怎么取景,以及实测过的坑(Chrome 虚拟时间不可靠、等加载时别推时钟、Vite 首次打开会刷新页面、Live2D 运行库要先加载、无头 Chrome 用完要关、别人模型的许可)。只要用户想「录个 GIF」「做个动图给我看」「对比一下改之前和改之后的动画」「把动作录下来」「验收一下动画效果」,或者要给动画、动效、角色动作拿出能看的证据,就用这个 skill,即使没提 GIF。Also use for English requests to record an animation as frames or a GIF, make a before/after comparison of motion, or capture deterministic frames from a web page, canvas, three.js, VRM or Live2D scene.

RedCarpG/live2d-vrm-animation

在网页或桌面应用里让 Live2D(Cubism,PixiJS)和 VRM(three.js + @pixiv/three-vrm)角色动起来:加载顺序、程序姿势和动作片段互相覆盖、在物理之前叠加、VTube Studio 模型补齐(没有 Idle、没眨眼、头角度是物理输出、8K 贴图、包围盒被特效带偏)、动作通道和定住、表情存取和道具冲突、three.js AnimationMixer 的坑(不写没变的值、LoopOnce 提前关掉)、程序「带动层」让手 K 和 AI 动作不僵、动捕片段只取上半身、弹簧骨骼延迟和跟节拍、裙子穿模、让 AI 生成表情和动作的数据格式与校验规则,以及逐帧记录的验证方法。只要用户在做虚拟形象、桌宠、VTuber 工具、数字人,提到 Live2D、Cubism、model3.json、motion3、exp3、physics3、VTube Studio、VRM、VRMA、three-vrm、Mixamo、动捕、SpringBone,或者抱怨「动作一顿一顿的」「动作僵」「手放下又抬起来闪一下」「头不跟着动」「定不住」「表情看不出来」「做动作脸上没表情」「手指僵、直板手」「托腮够不到下巴」「眼睛呆、一直盯着」「腿站不稳、脚滑」,就用这个 skill。Also use for English requests about animating Live2D or VRM avatars, procedural idle motion, physics, expressions, or AI-generated character motions.

vrm-model-conversion

把带骨架的 3D 人物模型(FBX、PMX/MMD、XPS、glTF/GLB、.blend;来自 Mixamo、MMD、Unity/VRChat、Daz Genesis、Auto-Rig Pro、Rigify、3ds Max Biped、游戏提取)在 Blender 后台转成 VRM 1.0,给 three-vrm 网页、桌宠、VTuber 软件、VRChat 外的应用用。管:解压和挑哪份源文件、各格式怎么导入、骨头名自动对应到 VRM 标准骨骼、A-pose 转 T-pose、表情(已有形态键直接绑;只有脸部骨头的烘成形态键)、头发和衣服的弹簧骨骼(没有物理骨的就加骨链、按位置重新分权重)、碰撞体、MToon 材质和发片透明、贴图缩小、VRM meta 和许可,以及一份检查清单。附可复用的 Blender 脚本 vrm_kit.py(参数化,不写死文件名)、模板 build_template.py、不用 Blender 的检查脚本 inspect_vrm.py。只要用户想「把这个模型转成 VRM」「这个 FBX/PMX 能不能给 three-vrm 用」「给模型加表情、加头发物理、加弹簧骨」「VRM 的表情不动、头发不飘、裙子穿模、碰撞体没用」「下载了个模型想当桌宠/虚拟形象」,就用这个 skill,即使没说 VRM。Also use for English requests to convert FBX/PMX/glTF/blend avatars to VRM, set up VRM expressions, spring bones or colliders, or debug a VRM export from Blender.

相关技能