SpeechMarkdown Rust
High-performance SpeechMarkdown parser written in Rust. Converts SpeechMarkdown syntax to platform-specific SSML for Amazon Alexa, Google Assistant, Microsoft Azure, and more.
Repository Structure
This repository contains the core Rust SpeechMarkdown parser with bindings for multiple languages:
speechmarkdown-rust/
├── src/ # Core Rust library (language-agnostic)
├── bindings/ # Language-specific bindings
│ ├── python/ # Python bindings via PyO3
│ ├── nodejs/ # Node.js bindings via napi-rs
│ ├── dotnet/ # .NET bindings via rust-cpp
│ └── swift/ # Swift bindings via C API + SPM
├── Package.swift # Swift Package Manager configuration (Swift-only)
├── build-swift-package.sh # Swift package build script (Swift-only)
└── Cargo.toml # Rust package configuration
Important Notes for Non-Swift Users:
- Swift-specific files are ignored by other build systems:
Package.swift,build-swift-package.sh, andswift-package-dist/are only used by Swift Package Manager. They do not affect Rust, Python, Node.js, or .NET builds. - Core Rust library unchanged: The
src/directory andCargo.tomlremain the single source of truth for the SpeechMarkdown parser across all languages. - Isolated language bindings: Each language in
bindings/has its own build configuration and doesn't interfere with others.
For Rust/.NET/Python/Node.js Developers: You can safely ignore Swift-specific files. Your respective package managers (Cargo, NuGet, PyPI, npm) only use the core library and your language's binding directory.
Install
| Language | Package | Install |
|---|---|---|
| Rust | speechmarkdown-rust | cargo add speechmarkdown-rust |
| Python | speechmarkdown-rust | pip install speechmarkdown-rust |
| Node.js | speechmarkdown | npm install speechmarkdown |
| .NET | SpeechMarkdown | dotnet add package SpeechMarkdown |
| Swift | Release asset | See Swift section below |
Supported Platforms
| Platform | String ID |
|---|---|
| Amazon Alexa | "amazon-alexa" or "alexa" |
| Google Assistant | "google-assistant" or "google" |
| Microsoft Azure | "microsoft-azure" or "azure" |
| Apple | "apple" |
| W3C | "w3c" |
| Samsung Bixby | "samsung-bixby" or "bixby" |
| ElevenLabs (pre-v3) | "elevenlabs" |
| ElevenLabs v3 | "elevenlabs-v3" |
| IBM Watson | "ibm-watson" or "watson" |
ElevenLabs note
ElevenLabs does not parse SSML documents, so both ElevenLabs platforms emit prompt markup rather than SSML, and the correct dialect depends on the model:
"elevenlabs"— pre-v3 models (eleven_multilingual_v2,eleven_flash_v2_5,eleven_flash_v2,eleven_turbo_v2):<break time="x.xs"/>pauses (max 3s) and<phoneme>for IPA (flash/turbo, English only). No<speak>wrapper."elevenlabs-v3"—eleven_v3/eleven_v3_conversational: bracketed natural-language audio tags ([whispers],[excited],[pause],[long pause],[laughs]), punctuation pauses, and native"/IPA/". Audio tags are model-interpreted direction — best-effort, voice-dependent — and are not understood by pre-v3 models.
API
All bindings expose the same core methods:
| Method | Returns | Description |
|---|---|---|
to_ssml(input, platform) |
string |
Convert SpeechMarkdown to SSML for the given platform |
to_text(input) |
string |
Convert SpeechMarkdown to plain text (strips all markup) |
to_smd(ssml) |
string |
Convert SSML to SpeechMarkdown (best-effort, lossy for unsupported elements) |
parse(input) |
string (JSON) |
Parse SpeechMarkdown and return the AST as JSON |
is_speech_markdown(input) |
bool |
Check if a string contains SpeechMarkdown syntax |
validate(input) |
bool |
Validate that SpeechMarkdown parses without errors |
supported_ssml(platform) |
string (JSON) |
Get supported SSML elements for a platform |
Usage
Rust
use speechmarkdown_rust::{SpeechMarkdownParser, Platform};
// Convert to SSML
let ssml = SpeechMarkdownParser::to_ssml(
"Hello (world)[emphasis:\"strong\"]",
Platform::AmazonAlexa,
)?;
// Convert to plain text
let text = SpeechMarkdownParser::to_text("Hello (world)[emphasis:\"strong\"]")?;
// Parse to AST (JSON string)
let ast = SpeechMarkdownParser::parse("Hello world")?;
// Check if input contains SpeechMarkdown syntax
if SpeechMarkdownParser::is_speech_markdown(&input) {
// ...
}
// Validate input
SpeechMarkdownParser::validate(&input)?;
// Convert SSML back to SpeechMarkdown (best-effort)
let smd = SpeechMarkdownParser::to_smd(r#"<speak><emphasis level="strong">word</emphasis></speak>"#)?;
// Returns: ++word++
Python
from speechmarkdown_rust import to_ssml, to_text, parse, is_speech_markdown, validate
ssml = to_ssml('Hello (world)[emphasis:"strong"]', 'amazon-alexa')
text = to_text('Hello (world)[emphasis:"strong"]')
ast = parse('Hello world')
is_smd = is_speech_markdown('Hello (world)[emphasis:"strong"]') # True
is_smd = is_speech_markdown('Hello world') # False
validate('Hello (world)[emphasis:"strong"]') # raises ValueError if invalid
# Convert SSML to SpeechMarkdown (best-effort)
smd = to_smd('<speak><emphasis level="strong">word</emphasis></speak>')
# Returns: ++word++
Node.js
const { to_ssml, to_text, parse, is_speech_markdown, validate } = require('speechmarkdown')
const ssml = to_ssml('Hello (world)[emphasis:"strong"]', 'amazon-alexa')
const text = to_text('Hello (world)[emphasis:"strong"]')
const ast = parse('Hello world')
is_speech_markdown('Hello (world)[emphasis:"strong"]') // true
is_speech_markdown('Hello world') // false
validate('Hello (world)[emphasis:"strong"]') // throws if invalid
// Convert SSML to SpeechMarkdown (best-effort)
const smd = to_smd('<speak><emphasis level="strong">word</emphasis></speak>')
// Returns: ++word++
.NET (C#)
using SpeechMarkdown;
var parser = new SpeechMarkdownParser();
string ssml = parser.ToSsml("Hello (world)[emphasis:\"strong\"]", Platform.AmazonAlexa);
string text = parser.ToText("Hello (world)[emphasis:\"strong\"]");
string json = parser.ParseToJson("Hello world");
bool isSmd = parser.IsSpeechMarkdown("Hello (world)[emphasis:\"strong\"]"); // true
parser.Validate("Hello (world)[emphasis:\"strong\"]"); // throws on invalid
// Convert SSML to SpeechMarkdown (best-effort)
string smd = parser.ToSmd("<speak><emphasis level=\"strong\">word</emphasis></speak>");
// Returns: ++word++
Swift
The repo root contains a Package.swift with a binary target pointing to a pre-built XCFramework. This enables both local development and Swift Package Index integration.
Option 1 — SPM (recommended):
// In your Package.swift:
.package(url: "https://github.com/AACTools/speechmarkdown-rust", branch: "spm")
Option 2 — Local package:
Download speechmarkdown-swift-package.zip from the latest release, unzip, and add as a local package in Xcode (File > Add Packages > Add Local).
Includes macOS (arm64 + x86_64), iOS device (arm64), and iOS simulator (arm64) slices.
To build from source: ./build-swift-package.sh
import SpeechMarkdown
let parser = SpeechMarkdownParser()
let ssml = try parser.toSsml(input: "Hello (world)[emphasis:\"strong\"]", platform: "amazon-alexa")
let text = try parser.toText(input: "Hello (world)[emphasis:\"strong\"]")
let json = try parser.parseToJson(input: "Hello world")
let isSmd = parser.isSpeechMarkdown(input: "Hello (world)[emphasis:\"strong\"]") // true
try parser.validate(input: "Hello (world)[emphasis:\"strong\"]") // throws on invalid
// Convert SSML to SpeechMarkdown (best-effort)
let smd = try parser.toSmd(ssml: "<speak><emphasis level=\"strong\">word</emphasis></speak>")
// Returns: ++word++
C API
#include "speechmarkdown.h"
// Convert to SSML
const char* ssml = speechmarkdown_to_ssml("Hello (world)[emphasis:\"strong\"]", "amazon-alexa");
speechmarkdown_free((char*)ssml);
// Convert to plain text
const char* text = speechmarkdown_to_text("Hello (world)[emphasis:\"strong\"]");
speechmarkdown_free((char*)text);
// Parse to JSON
const char* json = speechmarkdown_parse("Hello world");
speechmarkdown_free((char*)json);
// Check for SpeechMarkdown syntax
bool is_smd = speechmarkdown_is_speech_markdown("Hello (world)[emphasis:\"strong\"]");
// Validate
bool valid = speechmarkdown_validate("Hello (world)[emphasis:\"strong\"]");
// Convert SSML to SpeechMarkdown (best-effort)
const char* smd = speechmarkdown_to_smd("<speak><emphasis level=\"strong\">word</emphasis></speak>");
speechmarkdown_free((char*)smd);
// Get last error (thread-local)
const char* err = speechmarkdown_get_error();
Building from Source
Core Rust Library
The core Rust parser is built with:
cargo build --release
This produces:
- Windows:
target/release/speechmarkdown_rust.dll - macOS:
target/release/libspeechmarkdown_rust.dylib - Linux:
target/release/libspeechmarkdown_rust.so
Language-Specific Builds
Each language binding has its own build process:
Python:
cd bindings/python
maturin develop
# or for release: maturin build --release
Node.js:
cd bindings/nodejs
npm install
npm run build
.NET:
cd bindings/dotnet
dotnet build
Swift:
# Uses pre-built XCFramework from releases
# Or build from source:
./build-swift-package.sh
Development Workflow
The repository follows a unified development model where all language bindings share the same core Rust parser:
- Core changes: Modify
src/for parser logic changes - Language changes: Modify
bindings/<language>/for binding-specific changes - Testing: Each language has its own test suite
- Releases: All packages are released together with version synchronization
For Contributors:
- Rust developers: Work in
src/and test withcargo test - Python developers: Work in
bindings/python/and test withpytest - Node.js developers: Work in
bindings/nodejs/and test withnpm test - .NET developers: Work in
bindings/dotnet/and test withdotnet test - Swift developers: Work in
bindings/swift/and use SPM for testing
License
MIT
Metadata
Release files for speechmarkdown-rust 0.4.15
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| speechmarkdown_rust-0.4.15.tar.gz | 580.8 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| speechmarkdown_rust-0.4.15-cp313-cp313-win_amd64.whl | CPython 3.13 | CPython 3.13 | Windows x86-64 | Details |
| speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.17+ x86-64 | Details |
| speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.17+ ARM64 | Details |
| speechmarkdown_rust-0.4.15-cp313-cp313-macosx_11_0_arm64.whl | CPython 3.13 | CPython 3.13 | macOS 11.0+ ARM64 | Details |
| speechmarkdown_rust-0.4.15-cp313-cp313-macosx_10_12_x86_64.whl | CPython 3.13 | CPython 3.13 | macOS 10.12+ x86-64 | Details |
Total release size: 2.7 MB
Release files / speechmarkdown_rust-0.4.15.tar.gz
| Download URL | speechmarkdown_rust-0.4.15.tar.gz |
|---|---|
| Size | 580.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ee5c66eeec1808c1147261a504708a88ea159487c652653a25268f7f009e00d2
|
|
BLAKE2b-256 checksum How to use checksums |
745a8be29a5872a16e07fad66db5f5029a265f803955d9d4b27a598bdcba700d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / speechmarkdown_rust-0.4.15-cp313-cp313-win_amd64.whl
| Download URL | speechmarkdown_rust-0.4.15-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 329.4 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
d33332acf6c797d457da96e41bf39463302f0c9d792cd7612c26828a389bf608
|
|
BLAKE2b-256 checksum How to use checksums |
be95356533504094217eb62ba74b18e989bc63392e12db45d508c985eb691165
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 472.1 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
b2423481261ddbec9613a5e8cc7ce7581b07e8875121a41465764633d2e0062d
|
|
BLAKE2b-256 checksum How to use checksums |
9fdfd8d3fa0078edbb447ac8afc9d022d8d45a8ca232d1e4a601b486d746ca08
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | speechmarkdown_rust-0.4.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 461.4 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
965341052926277e7d57ef27848bd708c0d4c5fbc2eac398363d1e95219d95b6
|
|
BLAKE2b-256 checksum How to use checksums |
126b7c541ceb24a94e65926988280a53cbab4b0febd1fa863f58ff212dfb82f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / speechmarkdown_rust-0.4.15-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | speechmarkdown_rust-0.4.15-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 416.6 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7d220f4714f2f9ce5aacdc3f5c7efb2e0dee79be8b0c0b9c07885b0c0711f986
|
|
BLAKE2b-256 checksum How to use checksums |
8c18b8703908be67c64e30ac41dbb848dc633ac0dfdac101ba750a1701dea67c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / speechmarkdown_rust-0.4.15-cp313-cp313-macosx_10_12_x86_64.whl
| Download URL | speechmarkdown_rust-0.4.15-cp313-cp313-macosx_10_12_x86_64.whl |
|---|---|
| Size | 426.0 kB |
| Tags | CPython 3.13 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
63c6b6323acb645e1cf031b8bc48624fd24885b659c9aa00f191edc6f01e460c
|
|
BLAKE2b-256 checksum How to use checksums |
eaa98d8ebc3008c41a0c1820765150bb6ea3d566ad511f62b73590cfb39b47c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency log