Skip to content
Shiny.NET

Azure AI Speech

Downloads NuGet downloads for Shiny.Speech.Azure
Frameworks
.NET
.NET MAUI
Operating Systems
Android
iOS
Windows

Azure AI Speech provides enterprise-grade cloud speech-to-text and text-to-speech powered by Azure Cognitive Services. It replaces the platform-native ISpeechToTextService and ITextToSpeechService registrations with cloud-backed implementations while still using platform-native audio capture and playback.

Changed files
  • MyApp/
Platforms/Android/AndroidManifest.xml
AndroidManifest.xml
1<?xml version="1.0" encoding="utf-8"?>2<manifest xmlns:android="http://schemas.android.com/apk/res/android">3	<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">4	</application>5	<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>6	<uses-permission android:name="android.permission.BATTERY_STATS" />7	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />8	<uses-permission android:name="android.permission.INTERNET" />9	<uses-permission android:name="android.permission.RECORD_AUDIO" />10	<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />11</manifest>
// In MauiProgram.cs
builder.Services.AddAzureSpeech("your-subscription-key", "eastus");
// IAudioSource and IAudioPlayer are automatically registered for platform audio I/O

Or with a config object and selective services:

builder.Services.AddAzureSpeech(
new AzureSpeechConfig
{
SubscriptionKey = "your-subscription-key",
Region = "eastus"
},
speechToText: true,
textToSpeech: true
);
public record AzureSpeechConfig
{
public required string SubscriptionKey { get; init; }
public required string Region { get; init; }
}
Property Description
SubscriptionKey Your Azure Speech Services subscription key
Region Azure region (e.g., eastus, westus2, westeurope)

Once registered, inject and use ISpeechToTextService and ITextToSpeechService exactly as you would with platform-native speech — the API is identical:

public class MyViewModel(ISpeechToTextService stt, ITextToSpeechService tts)
{
async Task ListenAndRespond(CancellationToken ct)
{
var access = await stt.RequestAccess();
if (access != AccessState.Available)
return;
var text = await stt.ListenUntilSilence(cancellationToken: ct);
if (text != null)
await tts.SpeakAsync($"You said: {text}");
}
}

Azure expresses emotion through SSML, so a portable SpeechTone becomes an mstts:express-as wrapper and any bracketed annotations in the text are stripped rather than spoken aloud:

await tts.SpeakAsync("We just shipped it.", new TextToSpeechOptions
{
Tone = new SpeechTone { Emotion = SpeechEmotion.Excited, Intensity = 1.5f }
});
<prosody rate="+0%" pitch="+0%" volume="100">
<mstts:express-as style="excited" styledegree="1.5">
We just shipped it.
</mstts:express-as>
</prosody>

Intensity maps to styledegree (clamped to Azure’s 0.01–2 range). Style support is per-voice — a voice that doesn’t offer the requested style renders in its default delivery rather than failing, so check the voice list before relying on a particular style. No wrapper is emitted at all when there’s no tone, leaving the SSML byte-identical to before.

You can register Azure for just one service:

// Azure STT only (use platform-native TTS)
builder.Services.AddTextToSpeech(); // Platform-native TTS
builder.Services.AddAzureSpeech("key", "region", speechToText: true, textToSpeech: false);
// Azure TTS only (use platform-native STT)
builder.Services.AddSpeechToText(); // Platform-native STT
builder.Services.AddAzureSpeech("key", "region", speechToText: false, textToSpeech: true);