session.speaker is audio output: play a URL, speak text, or stream live PCM. Playback follows the phone’s media route, including connected Bluetooth audio glasses. For audio input (mic frames, voice activity), use session.mic instead.
src/background/index.ts

Methods

Playing a URL

play streams an audio URL through the phone’s playback service and resolves when it finishes.
PlayAudioOptions:

Text-to-speech

speak sends the text to the phone, which streams cloud TTS when connected and falls back to local offline TTS when the cloud is unavailable. It resolves when playback completes. Offline playback may segment longer text internally to reduce latency; callers use the same speak() API and receive the same interruption behavior in either mode.
SpeakOptions: SpeakResult has one field, completed: true if playback finished, false if it was interrupted.

Live PCM streaming

Use createStream() when audio arrives incrementally and cannot be exposed as a complete file or URL—for example, live meeting audio received over a WebSocket. The stream accepts signed 16-bit little-endian mono PCM on Android and iOS.
Live PCM requires Mentra App 2.13.0 or newer. Set minHostVersion: "2.13.0" in a miniapp that depends on createStream() so older hosts reject installation instead of failing during a call.
src/background/index.ts
SpeakerStreamOptions: The returned SpeakerStreamWriter has:
Always await writes and call either close() or abort(). The host also aborts the stream when the miniapp disconnects, but explicit teardown gives the best call-end latency. Compressed MP3, AAC, and Opus frames are not accepted; decode them to PCM before writing.

Errors

speak rejects with an object carrying a code field on cloud-side TTS failure. Catch it and branch on code:

State

Five states, read synchronously via state or isPlaying, or observed as transitions via onStateChange: A request moves idleloadingplayingstopped. On failure the speaker fires error once with errorCode set, then settles to stopped so isPlaying reads false.
SpeakerStateEvent:
onStateChange does not fire immediately with the current value. Read state separately if you want the starting value. Audio input (mic frames and voice-activity detection) lives on session.mic.