Skip to content
Client v5: BLE, BLE Hosting, HTTP, Jobs - Linux, MacOS, & Blazor Support! Full AOT, RX on BLE only & MANY other features! Check It Out

Microsoft.Extensions.AI

DownloadsNuGet downloads for Shiny.Speech.MicrosoftAI
Frameworks
.NET
.NET MAUI
Operating Systems
Android
iOS
Windows

Shiny.Speech.MicrosoftAI exposes your Shiny speech providers as standard Microsoft.Extensions.AI interfaces — ISpeechToTextClient and ITextToSpeechClient. This allows any code written against the M.E.AI abstractions to use Shiny’s cloud providers (Azure, ElevenLabs, OpenAI) and platform audio infrastructure.

Register a cloud provider, then add the M.E.AI adapters:

// 1. Register a cloud provider
builder.Services.AddAzureSpeech("subscription-key", "eastus");
// — or —
builder.Services.AddOpenAiSpeech("api-key");
// — or —
builder.Services.AddElevenLabsTextToSpeech("api-key");
// 2. Add M.E.AI adapters
builder.Services.AddShinySpeechClients();

You can also register them individually:

builder.Services.AddShinySpeechToTextClient(); // ISpeechToTextClient only
builder.Services.AddShinyTextToSpeechClient(); // ITextToSpeechClient only

Inject ISpeechToTextClient or ITextToSpeechClient from Microsoft.Extensions.AI:

using Microsoft.Extensions.AI;
public class TranscriptionService(ISpeechToTextClient sttClient, IAudioSource audioSource)
{
async Task<string?> TranscribeFromMic(CancellationToken ct)
{
await using var source = audioSource;
var audioStream = await source.StartCaptureAsync(ct);
var response = await sttClient.GetTextAsync(audioStream, new SpeechToTextOptions
{
SpeechLanguage = "en"
}, ct);
return response.Text;
}
async Task StreamTranscription(Stream audioStream, CancellationToken ct)
{
await foreach (var update in sttClient.GetStreamingTextAsync(audioStream, cancellationToken: ct))
{
switch (update.Kind)
{
case var k when k == SpeechToTextResponseUpdateKind.TextUpdating:
Console.Write($"\r{update.Text}"); // partial result
break;
case var k when k == SpeechToTextResponseUpdateKind.TextUpdated:
Console.WriteLine($"\n{update.Text}"); // final result
break;
}
}
}
}
using Microsoft.Extensions.AI;
public class SpeechService(ITextToSpeechClient ttsClient)
{
async Task Synthesize(CancellationToken ct)
{
var response = await ttsClient.GetAudioAsync(
"Hello from Shiny!",
new TextToSpeechOptions
{
VoiceId = "en-US-AriaNeural",
Speed = 1.0f,
Pitch = 1.0f,
AudioFormat = "audio/mpeg"
},
ct
);
// response.Contents contains DataContent with the audio bytes
}
}

The M.E.AI options are mapped to Shiny options automatically:

M.E.AI PropertyShiny PropertyNotes
SpeechLanguageSpeechRecognitionOptions.CultureISO-639 string → CultureInfo
ModelIdPassed through to response
M.E.AI PropertyShiny PropertyNotes
VoiceIdTextToSpeechOptions.VoiceMapped to VoiceInfo.Id
LanguageTextToSpeechOptions.CultureBCP 47 string → CultureInfo
SpeedTextToSpeechOptions.SpeechRate1.0 = normal
PitchTextToSpeechOptions.Pitch1.0 = normal
VolumeTextToSpeechOptions.Volume1.0 = normal
AudioFormatUsed as the DataContent media type (default: audio/mpeg)
KindWhen
SessionOpenAudio capture session started
TextUpdatingPartial recognition result (not final)
TextUpdatedFinal recognition result after silence
SessionCloseAudio capture session ended
KindWhen
SessionOpenSynthesis session started
AudioUpdatedComplete audio chunk available
SessionCloseSynthesis session ended