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.5.2

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.5.2
File Size Uploaded
speechmarkdown_rust-0.5.2.tar.gz 603.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for speechmarkdown-rust 0.5.2
File
speechmarkdown_rust-0.5.2-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
speechmarkdown_rust-0.5.2-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.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ ARM64 Details
speechmarkdown_rust-0.5.2-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
speechmarkdown_rust-0.5.2-cp313-cp313-macosx_10_12_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.12+ x86-64 Details

Total release size: 2.8 MB

Release files / speechmarkdown_rust-0.5.2.tar.gz

Download URL speechmarkdown_rust-0.5.2.tar.gz
Size 603.0 kB
Tags Source
SHA-256 checksum
How to use checksums
3bba6038d265efa546b2d3e53ddf4bb882333afd08c3ad880ac91ebb800049ae
BLAKE2b-256 checksum
How to use checksums
396bf7e82944543d72775280aed5cf09e5274e6979b6cf34a06ffd901256bc86
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 30, 2026.

Transparency log

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

Download URL speechmarkdown_rust-0.5.2-cp313-cp313-win_amd64.whl
Size 344.1 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
97d66d84dabacef3f89e0129ee41a0b84f94e6452a01faaddb4ce282c3b64398
BLAKE2b-256 checksum
How to use checksums
9ea280fced08b9cb82e0060794e464039a84865b64fe85c6223d4b8c7eaa979a
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 30, 2026.

Transparency log

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

Download URL speechmarkdown_rust-0.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 485.6 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
54c7acb91896dba243f582c8510bbe1f963d5050e264f105da3081728c61666c
BLAKE2b-256 checksum
How to use checksums
5553bab1b36c0332a64f467fbfa2dce0a0072b0ca0cd2dc0c1d62788831a92b1
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 30, 2026.

Transparency log

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

Download URL speechmarkdown_rust-0.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 477.8 kB
Tags CPython 3.13 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
aa95306aa08e86d93c7dbff007abaa04335467456fbb22bbc9125eb5303efef4
BLAKE2b-256 checksum
How to use checksums
faeee71f6cfb4776d637bea1a57ae10f6a2a62b172be556b9adb8b0bdce11aeb
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 30, 2026.

Transparency log

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

Download URL speechmarkdown_rust-0.5.2-cp313-cp313-macosx_11_0_arm64.whl
Size 433.5 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a28527044a2a05f49c3654aefd8c5cce5ebe7d60c4225a28e46ddcbb6a13b135
BLAKE2b-256 checksum
How to use checksums
edd98e4ba6cb087ed646d77e45932cd09bf683a43d793fec26009b7533b77b7a
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 30, 2026.

Transparency log

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

Download URL speechmarkdown_rust-0.5.2-cp313-cp313-macosx_10_12_x86_64.whl
Size 439.2 kB
Tags CPython 3.13 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
a5ecab0975f4b794688f9f2334ed27fdebf2a9236dbf81bb378bdc3a91a48613
BLAKE2b-256 checksum
How to use checksums
c6c3947b1c0b90e2efe09dceb1e19c4b5b93e9c5600f9952852a2757a8fb5896
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 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.2 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