Microsoft.Extensions.AI
| Downloads |
Frameworks
.NET
.NET MAUI
Operating Systems
Android
iOS
Windows
Overview
Section titled “Overview”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.
Changed files
- MyApp/
MauiProgram.cs
MauiProgram.cs
1#if PLATFORM2using MyApp.Services;34namespace MyApp;56public static class MauiProgram7{8 public static MauiApp CreateMauiApp()9 {10 var builder = MauiApp.CreateBuilder();1112 builder 13 .UseMauiApp<App>()14 .UseShiny()15 .ConfigureFonts(fonts =>16 {17 fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");18 fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");19 });2021 // TODO: once you have localization, add these22 //builder.Services.AddLocalization();23 //builder.Services.AddStronglyTypedLocalizations();24 builder.Services.AddSingleton(TimeProvider.System);25#if DEBUG26 builder.Logging.SetMinimumLevel(LogLevel.Trace);27 builder.Logging.AddDebug();28#endif29 // adapts the speech services to Microsoft.Extensions.AI ISpeechToTextClient & ITextToSpeechClient30 builder.Services.AddShinySpeechClients();3132 // source generated by Shiny.Extensions.DependencyInjection - registers every class marked [Singleton], [Scoped] or [Transient]33 builder.Services.AddGeneratedServices();34 // builder.Services.AddGeneratedAITools(); // https://shinylib.net/di/ai-tools/35 var app = builder.Build();3637 return app;38 }39}40#endifRegister a cloud provider, then add the M.E.AI adapters:
// 1. Register a cloud providerbuilder.Services.AddAzureSpeech("subscription-key", "eastus");// — or —builder.Services.AddOpenAiSpeech("api-key");// — or —builder.Services.AddElevenLabsTextToSpeech("api-key");
// 2. Add M.E.AI adaptersbuilder.Services.AddShinySpeechClients();You can also register them individually:
builder.Services.AddShinySpeechToTextClient(); // ISpeechToTextClient onlybuilder.Services.AddShinyTextToSpeechClient(); // ITextToSpeechClient onlyInject ISpeechToTextClient or ITextToSpeechClient from Microsoft.Extensions.AI:
Speech-to-Text
Section titled “Speech-to-Text”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; } } }}Text-to-Speech
Section titled “Text-to-Speech”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 }}Options Mapping
Section titled “Options Mapping”The M.E.AI options are mapped to Shiny options automatically:
SpeechToTextOptions
Section titled “SpeechToTextOptions”| M.E.AI Property | Shiny Property | Notes |
|---|---|---|
SpeechLanguage |
SpeechRecognitionOptions.Culture |
ISO-639 string → CultureInfo |
ModelId |
— | Passed through to response |
TextToSpeechOptions
Section titled “TextToSpeechOptions”| M.E.AI Property | Shiny Property | Notes |
|---|---|---|
VoiceId |
TextToSpeechOptions.Voice |
Mapped to VoiceInfo.Id |
Language |
TextToSpeechOptions.Culture |
BCP 47 string → CultureInfo |
Speed |
TextToSpeechOptions.SpeechRate |
1.0 = normal |
Pitch |
TextToSpeechOptions.Pitch |
1.0 = normal |
Volume |
TextToSpeechOptions.Volume |
1.0 = normal |
AudioFormat |
— | Used as the DataContent media type (default: audio/mpeg) |
Streaming Update Kinds
Section titled “Streaming Update Kinds”Speech-to-Text
Section titled “Speech-to-Text”| Kind | When |
|---|---|
SessionOpen |
Audio capture session started |
TextUpdating |
Partial recognition result (not final) |
TextUpdated |
Final recognition result after silence |
SessionClose |
Audio capture session ended |
Text-to-Speech
Section titled “Text-to-Speech”| Kind | When |
|---|---|
SessionOpen |
Synthesis session started |
AudioUpdated |
Complete audio chunk available |
SessionClose |
Synthesis session ended |


