SSMD 0.8
ttsforge treats SSMD 0.8 as a document format, not as decorated plain text. Generated,
edited, and direct .ssmd documents are validated with the public ssmd APIs and the
pykokoro Kokoro profile before synthesis. Header metadata is never sent to speech.
Basic workflow
ttsforge convert book.epub --generate-ssmd
# edit the .ssmd files in the chapter directory
ttsforge ssmd validate .book_chapters/chapter_001.ssmd --strict
ttsforge convert book.epub
The generated files use truncated SHA-256 content hashes. An edited invalid file stops its chapter and is never silently replaced; an existing audio file is retained until a valid synthesis and its sidecars succeed.
Portable document example
---
title: Review podcast
voice_bindings:
kokoro:
moderator: af_sarah
positive: af_bella
pause_defaults:
enabled: true
sentence: 250ms
paragraph: 700ms
voice_change: 350ms
---
<div voice="moderator">
Welcome to the review.
</div>
<div voice="positive">
The new format is portable. @approved
</div>
title is metadata and is not spoken. Logical roles resolve through
voice_bindings.kokoro. Explicit ...100ms breaks beat implicit defaults; simultaneous
implicit paragraph and voice changes use the longest duration. @approved is retained
as a marker event and exported to marker sidecars.
Syntax
Canonical inline annotations use [text]{key="value"}:
[Hermione]{ph="hɝmˈIni"}
[Bonjour]{lang="fr-FR"}
[100]{as="cardinal"}
[XML]{sub="extensible markup language"}
[fast words]{rate="fast" volume="loud"}
...c ...s ...p ...250ms
Moderate, strong, reduced, and none emphasis are parsed. EPUB processing has three
layers: epub2text performs semantic extraction, TTSForge preserves the resulting
controlled Markdown in SSMD, and the SSMD emphasis policy controls audible rendering.
Emphasis is spoken plainly by default: it does not add automatic gain, rate, or pitch
changes, and its metadata is preserved. Use --emphasis-level 1, 2, or 3 for Light,
Normal, or Strong gain-only audible emphasis; level 2 is the current legacy behavior.
Use --ssmd-emphasis approximate or the deprecated --enable-ssmd-emphasis only as
advanced/compatibility controls, and use warn or error for stricter behavior.
Explicit document prosody such as [fast words]{rate="fast"} remains active in plain
mode. Language, voice, prosody, say-as, substitution, phoneme, break, mark, paragraph,
heading, and supported audio attributes are passed to the renderer.
Automatic written-to-spoken preparation vs explicit say-as
Ordinary unannotated text flows through the PyKokoro/kokorog2p 0.8.x preparation boundary. For supported languages and forms, kokorog2p may prepare dates, times, measurements, currency, ordinals, and abbreviations as speakable text before G2P. TTSForge does not rewrite source SSMD into automatic annotations or duplicate that upstream normalization.
Explicit author intent remains separate: annotations such as [100]{as="cardinal"} and
other SSMD say-as values are document semantics and remain active overrides. The
renderer applies explicit SSMD intent according to its upstream contract rather than
treating every ordinary source form as an author annotation.
Direct SSMD input
An exact leading --- line opens front matter and a matching --- or ... closes it.
A ---- line is ordinary body text. Use --no-ssmd-header when an exact leading block
is literal spoken text.
For a direct .ssmd input, title precedence is explicit --title or API title, then
header title, then the filename stem. The complete source, including front matter, is
preserved for rendering.
Policies and diagnostics
Useful conversion options include:
--ssmd-unknown-header warn|error|ignore
--ssmd-missing-voice error|use-default
--emphasis-level 0|1|2|3
--ssmd-emphasis plain|approximate|warn|error
--enable-ssmd-emphasis
--detect-emphasis
--ssmd-voice narrator=af_sarah
--pause-voice-change 0.35
--ssmd-audio-root ./audio
--ssmd-remote-audio
--ssmd-fail-on-warning
Diagnostics have stable codes and source locations. Inspect without loading ONNX using
ttsforge ssmd inspect FILE or ttsforge ssmd inspect FILE --json. Validate with
ttsforge ssmd validate FILE; --strict promotes warnings to failures.
Prosody method selection
prosody_method is independent of detect_emphasis and ssmd_emphasis_mode. It
chooses the AudioSig algorithm used when an SSMD segment contains rate or pitch
metadata. wsola is the default speech-oriented audiobook choice; esola is an
experimental speech-oriented alternative; psola is accepted as an alias for AudioSig’s
canonical td_psola; and phase_vocoder is a generic reference/fallback path. Keep
fallbacks enabled unless testing strict behavior.
The current emphasis_level profile changes gain only. Selecting ESOLA, WSOLA, or PSOLA
does not change those fixed emphasis gains; the selected prosody method is used for
explicit SSMD rate and pitch annotations. plain disables emphasis approximation but
does not disable explicit rate, pitch, or volume annotations. Omit --emphasis-level
when resuming so the saved renderer policy remains authoritative.
Audio annotations use a document-relative local resolver with byte and duration limits.
Remote audio is disabled by default; when enabled, only bounded HTTPS sources are
accepted. Unresolved audio uses SSMD fallback text and emits an ssmd.audio_fallback or
ssmd.audio_unresolved diagnostic. Audio files are decoded and downmixed to mono before
pykokoro applies SSMD transformations. TTSForge retains source resolution, security
limits, SoundFile decoding, and output orchestration; AudioSig supplies the reusable
array downmix, while PyKokoro remains responsible for SSMD speed, gain, and resampling.
Intentional Kokoro limitations
SSMD voice language, gender, and variant hints are preserved as metadata but do not select a Kokoro voice.
SSMD extensions are rejected by default for the Kokoro profile.
Emphasis is spoken plainly by default. EPUB Markdown extraction and SSMD rendering are independent; use
--epub-content-mode plainonly for legacy comparison,--no-detect-emphasisto unwrap inline emphasis, and--emphasis-levelfor audible strength.Remote audio is opt-in and bounded.
Marks are exported as
chapter_NNN.markers.jsonand an aggregate output sidecar rather than embedded in every audiobook container.