Skip to content

Conversation

yeelut
Copy link

@yeelut yeelut commented Aug 11, 2025

system default voice with ios/macos/androids

Note

Are you waiting for the changes in this PR to be merged? Yes
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

For ios/macos, AVSpeechSynthesisVoice.FromIdentifier is added together with FromLanguage. The Locale.Id can now be used along with Locale.Language.

For Android,
Get Locale is based on TTS voices and returns the Locale with their corresponding IDs instead of a Empty value.
tts.Voice is added for when option for speaksync is called with the Locale and its ID

Issues Fixed

Fixes #26853

system default voice with ios/macos/androids
@yeelut yeelut requested a review from a team as a code owner August 11, 2025 03:04
@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Aug 11, 2025
@yeelut
Copy link
Author

yeelut commented Aug 11, 2025

@dotnet-policy-service agree

@yeelut yeelut changed the base branch from main to net10.0 August 11, 2025 03:11
yeelut and others added 3 commits August 11, 2025 13:28
Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
@mattleibow mattleibow changed the title PR-for-issue-26853-Text-to-speech-overwrite-system-default-voice [Essentials: Text to speech] Overwrite system default voice Aug 12, 2025
@yeelut
Copy link
Author

yeelut commented Aug 12, 2025

@MartyIX Anything else that I need to do for this PR to get approved?

@MartyIX
Copy link
Contributor

MartyIX commented Aug 12, 2025

A member of the MAUI team must review this PR. I just help with review when I have a bit of time.

Friendly ping @jfversluis

@@ -30,7 +30,7 @@ static AVSpeechUtterance GetSpeechUtterance(string text, SpeechOptions options)
{
// null voice if fine - it is the default
speechUtterance.Voice =
AVSpeechSynthesisVoice.FromLanguage(options.Locale?.Language) ??
AVSpeechSynthesisVoice.FromIdentifier(identifier: options.Locale?.Id) ?? // select the voice by identifier else set for default
Copy link
Member

Choose a reason for hiding this comment

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

This seems like a breaking change because people will set the Language property in their app now and then suddenly that stops working because they need to use the Id?

I'm wondering about the backwards compatibility of these changes.

Copy link
Author

Choose a reason for hiding this comment

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

Oh.. That's right

speechUtterance.Voice = options.Locale?.Id != null ? AVSpeechSynthesisVoice.FromIdentifier(options.Locale.Id) : AVSpeechSynthesisVoice.FromLanguage(options.Locale?.Language) ?? AVSpeechSynthesisVoice.FromLanguage(AVSpeechSynthesisVoice.CurrentLanguageCode);

Copy link
Author

Choose a reason for hiding this comment

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

@jfversluis thank you so much

Copy link
Author

Choose a reason for hiding this comment

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

Any further update on this review?
This makes the project a lot more meaningful for users to change the Voice setting within the maui app.

@yeelut yeelut requested a review from jfversluis August 13, 2025 13:47
@yeelut
Copy link
Author

yeelut commented Aug 26, 2025

/azp run

Copy link

Commenter does not have sufficient privileges for PR 31105 in repo dotnet/maui

@yeelut
Copy link
Author

yeelut commented Aug 26, 2025

Commenter does not have sufficient privileges for PR 31105 in repo dotnet/maui

@MartyIX Can you help with this?

@MartyIX
Copy link
Contributor

MartyIX commented Aug 26, 2025

I don't have a permission to run azp. @jfversluis Could you run tests please?

@jfversluis
Copy link
Member

/azp run MAUI-public

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jfversluis
Copy link
Member

/azp run MAUI-DeviceTests-public

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@yeelut
Copy link
Author

yeelut commented Aug 27, 2025

I download the artifacts from MAUI-Public.

Updated the reproduction project with .net 10 preview.

Added the downloaded nuget package.

Tried on a macOS build.
This fixes the issue #26853

Will try on iOS and Android.

@yeelut
Copy link
Author

yeelut commented Aug 28, 2025

@jfversluis Thank you for all the azp checks.
One more to go?
azp run MAUI-UITests-public

@jfversluis
Copy link
Member

UI tests are not useful for this, there are no UI tests that will cover this since its not a UI functionality :) Let me know your test results. I'm particularly interested in the backwards compatible scenario. If I have this implemented in my MAUI app today and update to .NET 10, I want to have no change in behavior or code unless I enable something extra.

Can't promise I will still add this in before then, I'm kinda on the fence about it, but let's see if we can make it happen.

@yeelut
Copy link
Author

yeelut commented Aug 29, 2025

UI tests are not useful for this, there are no UI tests that will cover this since its not a UI functionality :) Let me know your test results. I'm particularly interested in the backwards compatible scenario. If I have this implemented in my MAUI app today and update to .NET 10, I want to have no change in behavior or code unless I enable something extra.

Can't promise I will still add this in before then, I'm kinda on the fence about it, but let's see if we can make it happen.

Test on macOS:
removed voice selection in my bug/issue reproduction project.
only Locale.Language (e.g. en-us, ar-001) for selection.
Without specify the voice with the locale.id, the old behavior (my bug) reappear.

`var selectedLocale = locales.FirstOrDefault(locale => locale.Language == selectedLanguage);

var speechOptions = new SpeechOptions {
Pitch = 1f, // 0.0 - 2.0
Volume = 0.75f, // 0.0 - 1.0
Rate = 0.5f, //0.1-2.0
Locale = selectedLocale };

await TextToSpeech.Default.SpeakAsync($"Hello! I am {selectedVoice}. This is a Test! Ceci est un test! ¡Esto es una prueba! هذه تجربة!", speechOptions);

`

@yeelut
Copy link
Author

yeelut commented Aug 29, 2025

ScreenRecording_08-29-2025.23-58-18_1.mov

artifacts from MAUI-Public on iOS
It also fixes the issue

@yeelut
Copy link
Author

yeelut commented Aug 30, 2025

Tested on Android. The GetLocalesAsync() returns all the voices as well.
It works as expected.

Copy link
Author

@yeelut yeelut left a comment

Choose a reason for hiding this comment

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

Hi @jfversluis,

This is the latest commit that handle the backwards compatible scenario for ios.tvos.watchos.cs file

@yeelut yeelut changed the base branch from net10.0 to copilot/fix-31131 August 30, 2025 23:09
@yeelut yeelut changed the base branch from copilot/fix-31131 to net10.0 August 30, 2025 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants