Отправить аргументы распознавания речи. Результат в качестве параметра в пакете UWP desktop-bridge - PullRequest
6 голосов
/ 10 июля 2019

Я пытаюсь выяснить, можно ли отправить using Windows.Media.SpeechRecognition; args.Result.Text в качестве параметра из UWP в Консоль приложение.

Например, по следующему сценарию я отправляю TextToSpeech(args.Result.Text); со значением args.Result.Text;, где using Windows.Media.SpeechSynthesis; преобразование текста в речь произносит результат распознавания каждый раз, когда появляется args.Result.Text;. textBlock2.Text = args.Result.Text; также отображает результат:

 private async void ContinuousRecognitionSession_ResultGenerated(
            SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
        {
            await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {               
                textBlock1.Text = args.Result.Text;    

                TextToSpeech(args.Result.Text);               
            });
        }

но если я пытаюсь отправить args.Result.Text; в качестве параметра в консольное приложение, входит в комплект UWP в Desktop-Bridge пакет:

    private async void ContinuousRecognitionSession_ResultGenerated(
        SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
    {
        await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {                            
          textBlock1.Text = args.Result.Text; 

          SendTTSResult(args.Result.Text);
        });
    }

на запрошенную функцию:

 private async void SendTTSResult(string res)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
            {
                ApplicationData.Current.LocalSettings.Values["parameters"] = res;
                await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
            }
        });
    }

Поведение неудачи выглядит мне не очень понятным:

С первым результатом распознавания он отправляет параметр в консольное приложение, которое успешно загружает, получает и отображает этот параметр. Но со вторым запросом проблема отступает от этого уровня обработки, даже если функция отправки параметров однозначно является причиной сбоя SendTTSResult(args.Result.Text); функция не получает args.Result.Text, но это происходит уже до того, как функция вступит в действие, потому что предыдущий вывод выводится textBlock1.Text = args.Result.Text; также больше не получает событие.

При async() => поведение немного отличается, оно успешно принимает событие и отправляет значение в качестве параметра на консоль, в этом случае это происходит 2-3 раза с начала выполнения и голосового запроса, затем событие исчезает, когда оно не даже пройденный через SendTTSResult(string res), чтобы представить, что что-то в SendTTSResult(string res) не позволяет передавать строку из распознавания, а просто останавливается, даже если я поставлю это в конце функции TextToSpeech(string text), преобразование текста в речь также останавливает событие получения:

private async void SendTTSResult(string res)
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() =>
            {
                if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
                {
                    ApplicationData.Current.LocalSettings.Values["parameters"] = res;
                    await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
                }
            });
        }

Похоже, что отправка значения args.Result.Text в качестве параметра с функцией SendTTSResult(string res) работает нормально, успешно отправляет строку, но в то же время наличие этой функции в ContinuousRecognitionSession_ResultGenerated как-то влияет на получение внутри нее события. В то же время поведение ContSpeechRecognizer_HypothesisGenerated выглядит совершенно иначе, событие args.Hypothesis.Text появляется каждый раз, и результат успешно передается как параметр с тем же SendTTSResult(string res).

Что может помешать выполнению события, когда функция отправки параметра участвует в его процессе, и как это исправить, если это возможно?

Полный код непрерывного распознавания речи добавлен к моему вопросу в Центре разработки Windows Отправить аргументы распознавания речи. Результат в качестве параметра в пакете UWP desktop-bridge

РЕДАКТИРОВАТЬ 1: ************************************** ************************************************** **********

За функцией параметра консоль Connector.exe показывает только параметр без запуска какого-либо приложения или чего-либо еще:

static void Main(string[] args)
        {
            string result = Assembly.GetExecutingAssembly().Location;
            int index = result.LastIndexOf("\\");
            string rootPath = $"{result.Substring(0, index)}\\..\\";
            if (args.Length > 2)
            {
                switch (args[2])
                {
                    case "/parameters":
                        string parameters = ApplicationData.Current.LocalSettings.Values["parameters"] as string;
                        Console.WriteLine("Parameter: " + parameters);
                        Console.ReadLine();
                        break;
                }
            }
        }

Packeage.appxmanifest:

<uap:Extension Category="windows.appService">
  <uap:AppService Name="SampleInteropService" />
</uap:Extension>

<desktop:Extension Category="windows.fullTrustProcess" Executable="Connector\Connector.exe">
  <desktop:FullTrustProcess>
    <desktop:ParameterGroup GroupId="Parameters" Parameters="/parameters" />
  </desktop:FullTrustProcess>
</desktop:Extension>

РЕДАКТИРОВАТЬ 2: ************************************** ************************************************** **********

Я пробовал SendTTSResult(SpeechRecogVal); с изменением значения переменной:

 private async void ContinuousRecognitionSession_ResultGenerated(
        SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
    {
        await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {               
            SpeechRecogVal = args.Result.Text;
        });
    }

но это то же самое поведение tbRec.Text = SpeechRecogVal; показывает вывод успешно, пока я не добавлю SendTTSResult(SpeechRecogVal);,

   private string _srVal;

    public string SpeechRecogVal
    {
        get
        {
            return _srVal;
        }

        set
        {
            _srVal = value;
            ValueChanged();
        }
    }

    void ValueChanged()
    {
        tbRec.Text = SpeechRecogVal;
        // SendTTSResult(SpeechRecogVal);
    }

Похоже, проблема в том, что между await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => и (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0)) и await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => из private async voidContinuousRecognitionSession_ResultGenerated(SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)

Также я попробовал:

private async void ContinuousRecognitionSession_ResultGenerated(
    SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
{
       await  SendTTSResult(args.Result.Text);        
}

as Task:

async Task SendTTSResult(string res)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
            {
                ApplicationData.Current.LocalSettings.Values["parameters"] = res;
                await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
            }
        });
    }

И он также успешен только при первом ответе экземпляра события запроса, затем идет вполне. Похоже, что ContinuousRecognitionSession_ResultGenerated чем-то отличается от других параметров в Пространстве имен Windows.Media.SpeechRecognition и не совместимо с чем-то в async Task SendTTSResult(string res) или, скорее, с содержимым строк кода:

 ApplicationData.Current.LocalSettings.Values["parameters"] = args.Result.Text;
 await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");

1 Ответ

1 голос
/ 12 июля 2019

System.NullReferenceException происходит сценарий отключения appservice. Не могли бы вы проверить подключение apservice перед отправкой сообщения?

Для объяснения этого я создаю пример проекта, который ссылается на Stefanwick блог .И я также воспроизвожу вашу проблему, когда я не вызываю метод InitializeAppServiceConnection в клиенте WPF.Если вы хотите отправить текст в wpf, вы можете вызвать метод Connection.SendMessageAsync, как показано ниже SendMesssage click envent.

Возможность

      <Extensions>
        <uap:Extension Category="windows.appService">
          <uap:AppService Name="SampleInteropService" />
        </uap:Extension>
        <desktop:Extension Category="windows.fullTrustProcess" Executable="AlertWindow\AlertWindow.exe" />
      </Extensions>
    </Application>
  </Applications>
  <Capabilities>
    <Capability Name="internetClient" />
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>

WPF

private AppServiceConnection connection = null;
public MainWindow()
{
    InitializeComponent();
    InitializeAppServiceConnection();
}
private async void InitializeAppServiceConnection()
{
    connection = new AppServiceConnection();
    connection.AppServiceName = "SampleInteropService";
    connection.PackageFamilyName = Package.Current.Id.FamilyName;
    connection.RequestReceived += Connection_RequestReceived;
    connection.ServiceClosed += Connection_ServiceClosed;

    AppServiceConnectionStatus status = await connection.OpenAsync();
    if (status != AppServiceConnectionStatus.Success)
    {
        MessageBox.Show(status.ToString());
        this.IsEnabled = false;
    }
}

private void Connection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
    {
        Application.Current.Shutdown();
    }));
}

private async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
    // retrive the reg key name from the ValueSet in the request
    string key = args.Request.Message["KEY"] as string;

    if (key.Length > 0)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
        {
            InfoBlock.Text = key;

        }));
        ValueSet response = new ValueSet();
        response.Add("OK", "SEND SUCCESS");
        await args.Request.SendResponseAsync(response);
    }
    else
    {
        ValueSet response = new ValueSet();
        response.Add("ERROR", "INVALID REQUEST");
        await args.Request.SendResponseAsync(response);
    }
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
    ValueSet response = new ValueSet();
    response.Add("OK", "AlerWindow Message");
    await connection.SendMessageAsync(response);
}

UWP

 protected async override void OnNavigatedTo(NavigationEventArgs e)
 {
     base.OnNavigatedTo(e);

     if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
     {
         App.AppServiceConnected += MainPage_AppServiceConnected;
         App.AppServiceDisconnected += MainPage_AppServiceDisconnected;
         await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
     }
 }

 private async void MainPage_AppServiceDisconnected(object sender, EventArgs e)
 {
     await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
     {
         Reconnect();
     });
 }



private void MainPage_AppServiceConnected(object sender, AppServiceTriggerDetails e)
 {
     App.Connection.RequestReceived += AppServiceConnection_RequestReceived;

 }
 private async void AppServiceConnection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
 {
     string value = args.Request.Message["OK"] as string;
     await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
      {
          InfoBlock.Text = value;
      });


 }     
 private async void Reconnect()
 {
     if (App.IsForeground)
     {
         MessageDialog dlg = new MessageDialog("Connection to desktop process lost. Reconnect?");
         UICommand yesCommand = new UICommand("Yes", async (r) =>
         {
             await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
         });
         dlg.Commands.Add(yesCommand);
         UICommand noCommand = new UICommand("No", (r) => { });
         dlg.Commands.Add(noCommand);
         await dlg.ShowAsync();
     }
 }
 private int count = 0;
 private async void SendMesssage(object sender, RoutedEventArgs e)
 {
     count++;
     ValueSet request = new ValueSet();
     request.Add("KEY", $"Test{count}");
     AppServiceResponse response = await App.Connection.SendMessageAsync(request);

     // display the response key/value pairs

     foreach (string value in response.Message.Values)
     {
         await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
         {
             StatusBlock.Text = value;
         });

     }
 }

Это полный код образец .

...