Skip to main content

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, and swift-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 and Cargo.toml remain 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:

  1. Core changes: Modify src/ for parser logic changes
  2. Language changes: Modify bindings/<language>/ for binding-specific changes
  3. Testing: Each language has its own test suite
  4. Releases: All packages are released together with version synchronization

For Contributors:

  • Rust developers: Work in src/ and test with cargo test
  • Python developers: Work in bindings/python/ and test with pytest
  • Node.js developers: Work in bindings/nodejs/ and test with npm test
  • .NET developers: Work in bindings/dotnet/ and test with dotnet test
  • Swift developers: Work in bindings/swift/ and use SPM for testing

License

MIT

Metadata

Release files for speechmarkdown-rust 0.4.16

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for speechmarkdown-rust 0.4.16
File Size Uploaded
speechmarkdown_rust-0.4.16.tar.gz 582.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for speechmarkdown-rust 0.4.16
File
speechmarkdown_rust-0.4.16-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
speechmarkdown_rust-0.4.16-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.16-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.16-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
speechmarkdown_rust-0.4.16-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.16.tar.gz

Download URL speechmarkdown_rust-0.4.16.tar.gz
Size 582.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a3ade177f0ae7da487b0dd45a645147c913f1156e9ac56f614cc55dc2c0f6f86
BLAKE2b-256 checksum
How to use checksums
3983d5b8d186664665758802d23c39d77b10df8c5eb6aba9aaf978df8e70c289
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 9, 2026.

Transparency log

Release files / speechmarkdown_rust-0.4.16-cp313-cp313-win_amd64.whl

Download URL speechmarkdown_rust-0.4.16-cp313-cp313-win_amd64.whl
Size 330.2 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
3eff3b801ff545745f67d9eafdb265b1ad317556482a870203687037737a5393
BLAKE2b-256 checksum
How to use checksums
432c8a877255d6e81db38c00448420489cc5d80aada634dcf32625d712db3753
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 9, 2026.

Transparency log

Release files / speechmarkdown_rust-0.4.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL speechmarkdown_rust-0.4.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 472.5 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
9905b15808af29de4c9321ab090a2cdecc576934ac8f40b64ae837f7cb9f2183
BLAKE2b-256 checksum
How to use checksums
77b9fe120bf5a5e4fe1b2411c5a66fb50257a33ac6c8d50709b75a31470f143e
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 9, 2026.

Transparency log

Release files / speechmarkdown_rust-0.4.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL speechmarkdown_rust-0.4.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 462.3 kB
Tags CPython 3.13 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
816c6dcd348ab099b86f84ab2223f5348bf7148d850e9a76114e7e78c7f37d9b
BLAKE2b-256 checksum
How to use checksums
f9cd5fdb44bc217860f72fb23fd886348cd6a6008f938aa91c588ce3a350da30
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 9, 2026.

Transparency log

Release files / speechmarkdown_rust-0.4.16-cp313-cp313-macosx_11_0_arm64.whl

Download URL speechmarkdown_rust-0.4.16-cp313-cp313-macosx_11_0_arm64.whl
Size 417.1 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e58027d5a7473e4e4c2ad2684a339c88815c47f4df46d7e0850075029a9718ae
BLAKE2b-256 checksum
How to use checksums
1e8f351bd3bec7963e686ccc9a909d91338e31101a910aeda7c54925108c113a
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 9, 2026.

Transparency log

Release files / speechmarkdown_rust-0.4.16-cp313-cp313-macosx_10_12_x86_64.whl

Download URL speechmarkdown_rust-0.4.16-cp313-cp313-macosx_10_12_x86_64.whl
Size 426.8 kB
Tags CPython 3.13 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
114c724aceacb202c669363966a2dd983ab1b2d87dcd81ead3219706f76bf383
BLAKE2b-256 checksum
How to use checksums
ecce924d206f0362ee0b9e333c7eae6d4b03fb9c7de8742aeda6326862e8b612
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 9, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.2

6 release files

This release

0.4.16 This release

6 release files

0.4.13

6 release files

0.4.12

6 release files

0.4.11

6 release files

0.4.10

6 release files

0.4.9

6 release files

0.4.8

6 release files

0.4.7

6 release files

0.4.6

6 release files

0.4.5

6 release files

0.4.4

6 release files

0.4.3

6 release files

0.4.2

6 release files

0.4.1

6 release files

0.4.0

6 release files

0.3.1

6 release files

0.3.0

6 release files

0.2.9

6 release files

0.2.8

6 release files

0.2.7

6 release files

0.2.6

6 release files

0.2.5

6 release files

0.2.4

6 release files

0.2.3

6 release files

0.2.2

6 release files

0.2.1

6 release files

0.2.0

6 release files

0.1.18

6 release files

0.1.17

6 release files

0.1.16

6 release files

0.1.15

6 release files

0.1.14

6 release files

0.1.13

6 release files

0.1.12

6 release files

0.1.10

6 release files

0.1.9

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page