2

Having trouble stopping xamarin essentials text-to-speech in order to start a new text to speech "SpeakAsync" call w/ Xamarin.Forms.

Using this application as a simulated operator for a "practice phone call", I would like to cut off the operator saying "hello this is...." when the user hangs up the call, and use speak async to start saying "This call has ended" immediately after cutting off the previous text to speech

await TextToSpeech.SpeakAsync("Hello this is the operator, thank you for calling, how can I help you?"
    , SpeechTokenSource.Token);

This currently works as expected on android

public void CancelSpeech()
{
    if (SpeechTokenSource?.IsCancellationRequested ?? true)
    return;

    SpeechTokenSource.Cancel();
}

Trying to use cancellation token as listed in the documentation (https://learn.microsoft.com/en-us/xamarin/essentials/text-to-speech) however I cannot get the current "SpeakAsync" speech to stop playing immediately on iOS, or the next speakasync command to start speaking the text on iOS once the initial text-to-speech is cancelled.

   CancelSpeech();

   IsCallActive = false;
   DialedText = null;

   //Reset speech cancellation token
   SpeechTokenSource = new CancellationTokenSource();

   await TextToSpeech.SpeakAsync("This call has ended. Goodbye."
   , SpeechTokenSource.Token);

Error logged in iOS output: "[AXTTSCommon] _BeginSpeaking: couldn't begin playback"

Is there something I am missing? how can I cancel the current text-to-speech that is playing and start the next speech immediately after?

Edit:

This needs to be done on a single button tap (both canceling current speech and starting the "This call has ended" speech)

schwartzdotwork
  • 113
  • 1
  • 16
  • I test it and meet the same problem with you. I can give you a workaround is that you can put an `await Task.Delay(2000);` After `CancelSpeech();` and then it will work as you expect. I get an error called `BeginSpeaking: couldn't begin playback` when try to speak second speech. You can create an issue [here](https://github.com/jamesmontemagno/TextToSpeechPlugin) for more help and I will update you if I found anything. – nevermore Aug 28 '19 at 07:17
  • @JackHua-MSFT You've linked to the wrong GitHub Repo. He is using Xamarin.Essentials and would need to open the issue in the Xamarin.Essentials GitHub Repo: https://github.com/xamarin/Essentials – Brandon Minnick Sep 09 '19 at 01:12
  • @JackHua-MSFT, the task delay for 2 seconds does allow this to function somewhat as-expected, however, it's not going to work as a final solution because we can not have the app pause for 2 seconds before each text-to-speech call in production – schwartzdotwork Sep 09 '19 at 21:11

1 Answers1

0

I am unable to reproduce your problem.

The below code works on both iOS and Android using Xamarin.Essentials v1.3.0 and Xamarin.Forms v4.2.0.709249.

When the speakButton is tapped, text is spoken and when the cancelButton is tapped while the text is being spoken, the speaking stops.

There is one difference when cancelling SpeakAsync on iOS vs Android:

  • On iOS, the current word being spoken is finished and then the speaking stops
  • On Android, the current word being spoken is cut off and the speaking stops

Sample Code

The complete sample app can be found here: https://github.com/brminnick/CancelTextToSpeechSample/tree/master

using System;
using System.Threading;
using Xamarin.Forms;

namespace CancelTextToSpeechSample
{
    public class App : Application
    {
        public App()
        {
            MainPage = new CancelSpeakPage();
        }

        class CancelSpeakPage : ContentPage
        {
            const string _spokenText = "Oh, supercalifragilisticexpialidocious! Even though the sound of it, Is something quite atrocious, If you say it loud enough, You'll always sound precocious, Supercalifragilisticexpialidocious!";

            CancellationTokenSource _speakButtonCancellationTokenSource;

            public CancelSpeakPage()
            {
                var speakButton = new Button { Text = "Sing" };
                speakButton.Clicked += HandleSpeakButtonClicked;

                var cancelButton = new Button { Text = "Cancel Song" };
                cancelButton.Clicked += HandleCancelButtonClicked;

                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    HorizontalOptions = LayoutOptions.Center,

                    Children =
                    {
                        speakButton,
                        cancelButton
                    }
                };
            }

            void HandleCancelButtonClicked(object sender, EventArgs e)
            {
                _speakButtonCancellationTokenSource?.Cancel();
            }

            async void HandleSpeakButtonClicked(object sender, EventArgs e)
            {
                if (_speakButtonCancellationTokenSource?.IsCancellationRequested is false)
                    _speakButtonCancellationTokenSource.Cancel();

                _speakButtonCancellationTokenSource = new CancellationTokenSource();
                await Xamarin.Essentials.TextToSpeech.SpeakAsync(_spokenText, _speakButtonCancellationTokenSource.Token);
            }
        }
    }
}
Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
  • still receiving error on iOS: "[AXTTSCommon] _BeginSpeaking: couldn't begin playback", the first speech gets cut off after a few seconds of hitting the button and the second speech does not play, I am using MVVM pattern and not code-behind. – schwartzdotwork Sep 09 '19 at 13:08
  • Are you getting that error using the sample I created? The sample works both on my iOS Simulator and my iPhone. – Brandon Minnick Sep 09 '19 at 17:57
  • on my iPhone X running iOS 12.4.1, your sample project does not cancel the text-to-speech, nor does it play a second text-to-speech request. The main issue in my situation is the second speech not playing when requested after cancelling the first request. – schwartzdotwork Sep 09 '19 at 21:08
  • @SchwartzBrian I'm unsure of the problem that you're experiencing, because the sample does cancel the text-to-speech and it does play a second text-to-speech. I've uploaded a video to the repo showing the sample speaking, canceling then speaking again: https://github.com/brminnick/CancelTextToSpeechSample/blob/master/CancelTextToSpeechSample.mov – Brandon Minnick Sep 09 '19 at 21:42
  • I am experiencing the problem described in the initial post. When I “cancel” the current speech being spoken, the second text to speech does not start and I receive the error listed on iOS. Your sample has a “sing” button and a “cancel” button (your cancel button only cancels current speech and does not start another text to speech in the same method – schwartzdotwork Sep 10 '19 at 01:25
  • I was able to watch the video, however you are using two button click events( one to start speech, once to cancel) I need to cancel the current speech and start a new speech from one method/click event, that is not desired behavior as stated in initial post – schwartzdotwork Sep 10 '19 at 01:44