npx skills add ...
npx skills add chanjing-ai/framevideo --skill framevideo-voiceover-ssml
Create narration from project subtitles or AI analysis output, then author SSML-style voice scripts with phoneme, break, and ttnumber markup for FrameVideo voiceovers. Use when the user wants subtitles linked to voice generation, automatic narration from transcript/content, pronunciation fixes, pause insertion, or text normalization before TTS.
npx skills add chanjing-ai/framevideo --skill framevideo-voiceover-ssml
Generate narration scripts from existing project content (subtitles, transcripts, AI analysis) and enhance them with SSML-style markup for pronunciation fixes, pauses, and number reading control.
framevideo-media (tts) directlychanjing-digital-humanframevideo-mediaMinimal workflow:
Find the source text in this order:
Why subtitles first? They're already timed to the visual beats and match what viewers see on screen.
Three tags for delivery control:
| Tag | Purpose | Example |
|---|---|---|
<phoneme> | Fix pronunciation | <phoneme alphabet="ipa" ph="tʃæn.dʒɪŋ">Chanjing</phoneme> |
<break> | Insert pause | <break time="0.5s"/> |
<ttnumber> | Control number reading | <ttnumber pronounce="twenty twenty-six">2026</ttnumber> |
Markup is authoring-layer only. Keep it in your script file, but strip it before sending to TTS providers that don't support SSML.
Not all TTS providers support SSML tags:
phoneme, break, ttnumber — pass through unchangedAlways save both versions:
script-marked.txt — original with SSML tagsscript-fallback.txt — clean text for non-SSML providersExpand terse subtitles:
Keep alignment with visible text:
Text normalization rules:
& to "and"$99 → "ninety-nine dollars"Use sparingly. Only add markup where TTS misreads or pacing is critical.
Chinese names and brands:
English technical terms:
Product names:
When to use:
Alphabets:
ipa — International Phonetic Alphabet (universal)py — Pinyin for Mandarin Chinesex-sampa — Extended SAMPA (ASCII-safe IPA)Dramatic pauses:
List separation:
Transition markers:
Timing guidelines:
0.2s — natural comma pause0.3-0.5s — sentence boundary, breath0.6-0.8s — dramatic pause, emphasis1.0s+ — scene transition, major shiftWhen to use:
When NOT to use:
Years:
Product codes:
Prices:
Dates:
When to use:
Decision tree:
Provider SSML support:
| Provider | Phoneme | Break | Ttnumber | Invoke via |
|---|---|---|---|---|
| Kokoro | ❌ | ❌ | ❌ | framevideo-media |
| Chanjing TTS | ✅ | ✅ | ✅ | chanjing-digital-human |
| ElevenLabs | ✅ | ✅ | ⚠️ | External API |
With SSML support (Chanjing):
Without SSML support (Kokoro):
Stripping SSML tags:
File structure:
Why save both?
Generate transcript from audio:
Use in composition:
Sync captions (see framevideo skill for caption patterns):
Input subtitles.txt:
Output script-marked.txt:
DESIGN.md snippet:
Apply in script:
For product walkthroughs:
English narration with Chinese brand:
Pricing and metrics:
<break> instead of rewriting awkward phrasing1. Check SSML syntax:
2. Test fallback stripping:
3. A/B test TTS output:
4. Verify transcript alignment:
framevideo-media skill — TTS generation and transcriptionchanjing-digital-human skill — SSML-aware TTS via Chanjing platformframevideo skill — audio element conventions and caption timing# Check for existing subtitles
ls subtitles.txt captions.json transcript.json
# Check AI analysis output (if using website-to-framevideo)
cat STORYBOARD.md SCRIPT.md
# Check existing narration drafts
ls narration-draft.txt script.txtSource: "New feature: AI search"
Narration: "Introducing our new feature: AI-powered search that understands your intent."<phoneme alphabet="py" ph="chan1 jing4">蝉镜</phoneme>
<phoneme alphabet="py" ph="xi1">茜</phoneme> (name: "Xi", not "qi")<phoneme alphabet="ipa" ph="dʒiː.sæp">GSAP</phoneme> (not "guh-sap")
<phoneme alphabet="ipa" ph="weɪ.ˈeɪ.ˈeɪ.ˈpiː">WAAPI</phoneme> (spell it out)<phoneme alphabet="ipa" ph="freɪm.ˈvɪd.i.oʊ">FrameVideo</phoneme>Introducing our new product. <break time="0.8s"/> Built for creators.Three reasons: speed<break time="0.4s"/>, quality<break time="0.4s"/>, and ease of use.In the past<break time="0.3s"/>, this took hours. Now? Seconds.<ttnumber pronounce="twenty twenty-six">2026</ttnumber>
<ttnumber pronounce="nineteen fifty-five">1955</ttnumber>Model <ttnumber pronounce="A X dash three hundred">AX-300</ttnumber>Only <ttnumber pronounce="ninety-nine dollars">$99</ttnumber>Launch date: <ttnumber pronounce="July seventeenth">7/17</ttnumber>Does user require Chanjing platform voices?
├─ YES → Use chanjing-digital-human skill (supports SSML)
└─ NO
├─ Need offline/free → Kokoro via framevideo-media (strip SSML)
└─ Need high quality → ElevenLabs (check SSML support)# Pass marked script directly
npx framevideo chanjing tts script-marked.txt \
--voice-id <voice-id> \
--output narration.wav# Strip tags first
sed 's/<[^>]*>//g' script-marked.txt > script-fallback.txt
# Generate clean
npx framevideo tts script-fallback.txt \
--voice af_heart \
--output narration.wav# Simple regex (removes all XML-like tags)
sed 's/<[^>]*>//g' input.txt > output.txt
# Or Python for precise control
python3 << 'EOF'
import re
with open('script-marked.txt') as f:
text = f.read()
# Remove SSML tags but keep inner text
text = re.sub(r'<phoneme[^>]*>(.*?)</phoneme>', r'\1', text)
text = re.sub(r'<break[^>]*/?>', ' ', text)
text = re.sub(r'<ttnumber[^>]*>(.*?)</ttnumber>', r'\1', text)
with open('script-fallback.txt', 'w') as f:
f.write(text)
EOFproject/
├── script-marked.txt # Original with SSML
├── script-fallback.txt # Stripped for non-SSML TTS
├── narration.wav # Generated audio
└── transcript.json # Re-transcribed with timestampsnpx framevideo transcribe narration.wav --output transcript.json<audio
src="narration.wav"
data-start="0"
data-duration="12.4"
data-track-index="10"
data-volume="1.0">
</audio>// transcript.json → caption timing
const WORDS = [
{ text: "Introducing", start: 0.2, end: 0.8 },
{ text: "FrameVideo", start: 0.9, end: 1.4 },
// ...
];🚀 New: AI Search
50% faster
Try it nowIntroducing our newest feature:<break time="0.4s"/> AI-powered search.
<break time="0.3s"/>
It's fifty percent faster than traditional search.
<break time="0.5s"/>
Try it now at <phoneme alphabet="ipa" ph="tʃæn.dʒɪŋ">chanjing</phoneme> dot AI.## Brand Voice
- Company: "Chanjing" (IPA: tʃæn.dʒɪŋ, NOT "chan-jing")
- Product: "FrameVideo" (one word, capital F, capital V)Welcome to <phoneme alphabet="ipa" ph="tʃæn.dʒɪŋ">Chanjing</phoneme>.
<phoneme alphabet="ipa" ph="freɪm.ˈvɪd.i.oʊ">FrameVideo</phoneme> makes video simple.First, click the Timeline button.<break time="0.6s"/>
Then drag the <phoneme alphabet="ipa" ph="dʒiː.sæp">GSAP</phoneme> animation track.<break time="0.5s"/>
Notice the seek time updates in real-time.This is <phoneme alphabet="py" ph="chan1 jing4">蝉镜</phoneme><break time="0.3s"/>, the AI video platform from China.Available in three tiers:<break time="0.4s"/>
Starter at <ttnumber pronounce="forty-nine dollars">$49</ttnumber>,<break time="0.3s"/>
Pro at <ttnumber pronounce="ninety-nine dollars">$99</ttnumber>,<break time="0.3s"/>
and Enterprise at <ttnumber pronounce="four ninety-nine">$499</ttnumber>.# This skill: create marked script
echo '<phoneme>...</phoneme> text' > script-marked.txt
# framevideo-media: generate TTS
npx framevideo tts script-fallback.txt --voice af_heart --output narration.wav
# framevideo-media: transcribe
npx framevideo transcribe narration.wav --output transcript.json
# framevideo skill: use in composition# This skill: create marked script with SSML
cat script-marked.txt
# chanjing-digital-human: generate with SSML support
npx framevideo chanjing tts script-marked.txt --voice-id <id> --output narration.wavStep 3 (Storyboard) → produces SCRIPT.md
↓
This skill → adds SSML markup to SCRIPT.md content
↓
Step 4 (VO) → generates audio via framevideo-media or chanjing-digital-human
↓
Step 5 (Build) → uses transcript.json for caption timing# No unclosed tags
grep -o '<[^/>]*>' script-marked.txt | sort | uniq -c
# Phoneme has alphabet attribute
grep '<phoneme' script-marked.txt | grep -v 'alphabet='
# (should return nothing)sed 's/<[^>]*>//g' script-marked.txt > test-fallback.txt
cat test-fallback.txt
# Verify: readable, no XML artifacts, natural grammar# Generate without markup
npx framevideo tts script-fallback.txt --voice af_heart -o no-markup.wav
# Generate with markup (if supported)
npx framevideo chanjing tts script-marked.txt --voice-id <id> -o with-markup.wav
# Compare audio quality and pronunciationnpx framevideo transcribe narration.wav --output transcript.json
# Check: word timing matches intended beats