Skip to content

Added Essentials TextToSpeech#178

Open
jsuarezruiz wants to merge 8 commits into
mainfrom
essentials-texttospeech
Open

Added Essentials TextToSpeech#178
jsuarezruiz wants to merge 8 commits into
mainfrom
essentials-texttospeech

Conversation

@jsuarezruiz

Copy link
Copy Markdown
Member

Add an Avalonia implementation of MAUI Essentials TextToSpeech.

image

Changes:

  • Add ITextToSpeech support in Avalonia.Controls.Maui.Essentials
  • Register TextToSpeech.Default through UseAvaloniaEssentials()
  • Add desktop support using espeak-ng with spd-say fallback
  • Add browser support using the Web Speech API
  • Support pitch, rate, volume, and cancellation
  • Added samples
  • Added tests

Copilot AI review requested due to automatic review settings April 7, 2026 07:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Avalonia-backed implementation of MAUI Essentials TextToSpeech, integrating desktop (external TTS tools) and browser (Web Speech API) backends into Avalonia.Controls.Maui.Essentials, along with docs, samples, and tests.

Changes:

  • Introduces AvaloniaTextToSpeech with desktop (espeak-ng / spd-say) and browser (Web Speech API) implementations.
  • Registers TextToSpeech.Default via UseAvaloniaEssentials() and updates docs/status.
  • Adds ControlGallery sample UI and xUnit tests covering validation/cancellation behavior.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/Avalonia.Controls.Maui.Essentials.Tests/AvaloniaTextToSpeechTests.cs Adds unit tests for validation, cancellation behavior, and interface compliance.
STATUS-ESSENTIALS.md Marks TextToSpeech API + supporting types as implemented.
src/Avalonia.Controls.Maui.Essentials/wwwroot/js/speechSynthesis-interop.js Adds JS module wrapping Web Speech API voice listing/speaking/cancel.
src/Avalonia.Controls.Maui.Essentials/TextToSpeech/SpeechSynthesisInterop.Browser.cs Adds JSImport bindings + module import for the JS interop module.
src/Avalonia.Controls.Maui.Essentials/TextToSpeech/AvaloniaTextToSpeech.cs Adds core ITextToSpeech implementation with option validation + serialization lock.
src/Avalonia.Controls.Maui.Essentials/TextToSpeech/AvaloniaTextToSpeech.Default.cs Adds desktop backend using external processes to enumerate locales and speak.
src/Avalonia.Controls.Maui.Essentials/TextToSpeech/AvaloniaTextToSpeech.Browser.cs Adds browser backend using the JS module + voice enumeration.
src/Avalonia.Controls.Maui.Essentials/README.md Documents TextToSpeech support and usage example.
src/Avalonia.Controls.Maui.Essentials/MauiEssentialsBuilderExtensions.cs Registers TextToSpeech.Default to use AvaloniaTextToSpeech.
src/Avalonia.Controls.Maui.Essentials/Avalonia.Controls.Maui.Essentials.csproj Packs wwwroot/** as static web assets for browser interop.
samples/ControlGallery/ControlGallery/Pages/TextToSpeechPage.xaml Adds a sample page UI for speaking text with options/locales.
samples/ControlGallery/ControlGallery/Pages/TextToSpeechPage.xaml.cs Adds sample page logic for locale loading, speaking, and cancellation.
samples/ControlGallery/ControlGallery/MainPage.xaml.cs Adds TextToSpeech sample to navigation/menu.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Avalonia.Controls.Maui.Essentials/TextToSpeech/AvaloniaTextToSpeech.cs Outdated
Comment thread src/Avalonia.Controls.Maui.Essentials/TextToSpeech/AvaloniaTextToSpeech.cs Outdated
@drasticactions

Copy link
Copy Markdown
Collaborator
image

This is what I get in Safari

image

This is what I get in Firefox, Edge, and Chrome. I can't get it to run in any browser. Debug or Release mode.

For Desktop, I'm not sure of the approach. https://github.com/dotnet/maui/tree/63d534adcce8fc4bea557db56a72216b2fa767b5/src/Essentials/src/TextToSpeech

MAUI includes an implementation for all platforms except Linux and WASM. With what's here, if you ran this on any other platform, you get

image

Since the MAUI ones use the SDK bindings, we can't necessarily use them out of the box (And I would rather not reimplement them wholesale here, too, when they'll basically be the same thing, but with PInvokes). For the Linux stuff, I'm not sure how I feel about wrapping existing programs through new Process calls. Developers would need to direct users to ensure they have one of those engines installed already, and I'm not sure you're given a choice over which one you should use; for example, if you have both installed, you can't force your app to choose one.

This is a situation where I think we should wrap a cross-platform TTS library (at least for Desktop use) and map it to the essentials API, like how Maps would have worked. That would make it easier to bundle a dependency (or direct devs to what they need to bundle) and not require installed apps to exist on the users machine.

@jsuarezruiz

Copy link
Copy Markdown
Member Author
image This is what I get in Safari image This is what I get in Firefox, Edge, and Chrome. I can't get it to run in any browser. Debug or Release mode.

For Desktop, I'm not sure of the approach. https://github.com/dotnet/maui/tree/63d534adcce8fc4bea557db56a72216b2fa767b5/src/Essentials/src/TextToSpeech

MAUI includes an implementation for all platforms except Linux and WASM. With what's here, if you ran this on any other platform, you get

image Since the MAUI ones use the SDK bindings, we can't necessarily use them out of the box (And I would rather not reimplement them wholesale here, too, when they'll basically be the same thing, but with PInvokes). For the Linux stuff, I'm not sure how I feel about wrapping existing programs through `new Process` calls. Developers would need to direct users to ensure they have one of those engines installed already, _and_ I'm not sure you're given a choice over which one you should use; for example, if you have both installed, you can't force your app to choose one.

This is a situation where I think we should wrap a cross-platform TTS library (at least for Desktop use) and map it to the essentials API, like how Maps would have worked. That would make it easier to bundle a dependency (or direct devs to what they need to bundle) and not require installed apps to exist on the users machine.

Originally did tests on Ubuntu (24.04.4 LTS). Fixed an issue with the incorrect browser voice deserialization. Tested on Chrome, Edge from macOS and works.

image Should get correct voice and do the text to speech.

@drasticactions

Copy link
Copy Markdown
Collaborator

@jsuarezruiz Can you try clearing all your bin/obj's and try testing again in WASM?

Testing it on my Arch install, on Firefox, Edge, and Chrome, I got

Loading module from “http://localhost:5235/_content/Avalonia.Controls.Maui.Essentials/js/speechSynthesis-interop.js” was blocked because of a disallowed MIME type (“”).. It would always fail to load the js, although it did exist in the folder. I installed Ubuntu 24.04.4 and did the same thing and got the same errors. If you call the file endpoint, it does return a blank MIME type, but I do know that if you include your own files in the wwwroot folder directly in the application browser project, it does correctly resolve with the right types, which I believe is due to the ASP.NET WebAssembly SDK properly typing the files. The Essentials Library we have is standard, and we're just copying the JS to the file location, so it does "exist" and will resolve, but it will fail when invoked in code.

My guess is it may have worked for you because it either happened to exist in the wwwroot folder in ControlGallery when you were testing it, or whatever ASP.NET saw when it was setting up the file resolves happened to get it right, but I've tried this now on several computers and OSs, and I can't get it working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants