Intégration à une application cliente à l’aide du SDK Speech

Dans cet article, vous apprendrez à effectuer des demandes à une application Commandes personnalisées publiée à partir du Kit de développement logiciel (SDK) Speech exécuté dans une application UWP. Pour établir une connexion avec l’application Commandes personnalisées, vous devez :

  • Publier une application Commandes personnalisées et obtenir un identificateur d’application (ID d’application)
  • Créer une application cliente UWP à l'aide du kit de développement logiciel (SDK) Speech pour vous permettre de parler avec votre application Commandes personnalisées

Prérequis

Vous devez disposer d’une application Commandes personnalisées pour poursuivre cet article. Si vous n’avez pas encore créé d’application Commandes personnalisée, vous pouvez le faire dans les démarrages rapides suivants :

Vous aurez également besoin de ce qui suit :

Étape 1 : Publier une application Commandes personnalisées

  1. Ouvrez votre application Commandes personnalisées précédemment créée

  2. Accédez à Paramètres, sélectionnez Ressource LUIS

  3. Si Ressource de prédiction n’est pas affecté, sélectionnez une clé de prédiction ou créez-en une

    La clé de prédiction de requêtes est toujours requise avant la publication d’une application. Pour plus d’informations sur les ressources LUIS, reportez-vous à Créer une ressource LUIS

  4. Revenez à la modification des commandes, sélectionnez Publier

    Publish application

  5. Copiez l’ID d’application à partir de la notification de publication pour utilisation ultérieure

  6. Copiez la clé de la ressource Speech pour une utilisation ultérieure

Étape 2 : Créer un projet Visual Studio

Pour créer un projet Visual Studio pour le développement UWP, vous devez :

  • Configurer les options de développement de Visual Studio.
  • Créer le projet et sélectionner l’architecture cible.
  • Configurer la capture audio.
  • Installer le kit SDK Speech.

Configurer les options de développement de Visual Studio

Pour commencer, vérifiez que Visual Studio est configuré correctement pour le développement UWP :

  1. Ouvrez Visual Studio 2019 pour afficher la fenêtre de démarrage.

  2. Sélectionnez Continuer sans code pour accéder à l’IDE Visual Studio.

    Screenshot that shows the start window with the action for continuing without code highlighted.

  3. Dans la barre de menus de Visual Studio, sélectionnez Outils>Obtenir les outils et fonctionnalités pour ouvrir Visual Studio Installer et afficher la boîte de dialogue Modification.

  4. Sous l’onglet Charges de travail, sous Windows, recherchez la charge de travail Développement pour la plateforme Windows universelle. Si la case en regard de cette charge de travail est déjà cochée, fermez la boîte de dialogue Modification et passez à l’étape 7.

    Screenshot that shows the Workloads tab of the Modifying dialog, with the workload for Universal Windows Platform development highlighted.

  5. Cochez la case Développement pour la plateforme Windows universelle, puis sélectionnez Modifier.

  6. Dans la boîte de dialogue Avant de démarrer, sélectionnez Continuer pour installer la charge de travail Développement UWP. L’installation de la nouvelle fonctionnalité peut prendre quelques instants.

  7. Fermez Visual Studio Installer.

Créer le projet

Ensuite, créez votre projet et sélectionnez l’architecture cible :

  1. Dans la barre de menus Visual Studio, sélectionnez Fichier>Nouveau>Projet pour afficher la fenêtre Créer un projet.

  2. Recherchez et sélectionnez Application vide (Windows universelle) . Veillez à sélectionner la version C# de ce type de projet (et non pas la version Visual Basic).

  3. Sélectionnez Suivant.

    Screenshot that shows the window for creating a new project, with Blank App (Universal Windows) selected and the Next button highlighted.

  4. Dans la boîte de dialogue Configurer votre nouveau projet, dans Nom du projet, entrez helloworld.

  5. Dans Emplacement, accédez au dossier où vous voulez enregistrer votre projet et sélectionnez-le (ou créez ce dossier).

  6. Sélectionnez Create (Créer).

    Screenshot that shows the dialog for configuring a new project, with boxes for project name and location and the Create button highlighted.

  7. Dans la fenêtre Nouveau projet de plateforme Windows universelle, dans Version minimale (deuxième zone de liste déroulante), sélectionnez Windows 10 Fall Creators Update (10.0, Build 16299). Il s’agit de l’exigence minimale pour le Kit de développement logiciel (SDK) Speech.

  8. DansVersion cible (la première zone de liste déroulante), choisissez une valeur identique ou ultérieure à la valeur figurant dans Version minimale.

    Screenshot that shows the New Universal Windows Platform Project dialog with minimum and target versions selected.

  9. Sélectionnez OK. Vous êtes redirigé vers l’IDE Visual Studio, avec le nouveau projet créé et visible dans le volet Explorateur de solutions.

    Screenshot that shows the helloworld project visible in Visual Studio.

  10. Sélectionnez l’architecture de votre plateforme cible. Dans la barre d’outils Visual Studio, recherchez la zone de liste déroulante Plateformes Solution. Si vous ne la voyez pas, sélectionnezAfficher>Barres d’outils>Standard pour afficher la barre d’outils qui contient Plateformes Solution.

    Si vous exécutez Windows 64 bits, sélectionnez x64 dans la zone de liste déroulante. Windows 64 bits peut aussi exécuter les applications 32 bits : vous pouvez donc choisir x86 si vous préférez.

    Notes

    Le SDK Speech prend en charge tous les processeurs compatibles Intel, mais uniquement les versions x64 des processeurs ARM.

Configurer la capture audio

Autorisez le projet à capturer l’entrée audio :

  1. Dans l’Explorateur de solutions, double-cliquez sur Package.appxmanifest pour ouvrir le manifeste de l’application de package.

  2. Sélectionnez l’onglet Fonctionnalités.

    Screenshot of Visual Studio that shows the Capabilities tab in the package application manifest.

  3. Cochez la case pour la fonctionnalité Microphone.

  4. Dans la barre de menus, sélectionnez Fichier>Enregistrer Package.appxmanifest pour enregistrer vos modifications.

Installer le Kit de développement logiciel (SDK) Speech

Enfin, installez le package NuGet du SDK Speech et référencez le SDK Speech dans votre projet :

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur la solution, puis sélectionnez Gérer les packages NuGet pour la solution pour accéder à la fenêtre NuGet – Solution.

  2. Sélectionnez Parcourir.

  3. Dans Source du package, sélectionnez nuget.org.

    Screenshot that shows the Manage Packages for Solution dialog, with the Browse tab, search box, and package source highlighted.

  4. Dans la zone de recherche, entrez Microsoft.CognitiveServices.Speech. Choisissez ensuite ce package une fois qu’il apparaît dans les résultats de la recherche.

  5. Dans le volet d’état du package en regard des résultats de la recherche, sélectionnez votre projet helloworld.

  6. Sélectionnez Installer.

    Screenshot that shows the Microsoft.CognitiveServices.Speech package selected, with the project and the Install button highlighted.

  7. Dans la boîte de dialogue Aperçu des modifications, sélectionnez OK.

  8. Dans la boîte de dialogue Acceptation de la licence, affichez la licence, puis sélectionnez J’accepte. L’installation du package commence. Une fois l’installation terminée, le volet Sortie affiche un message similaire au texte suivant : Successfully installed 'Microsoft.CognitiveServices.Speech 1.15.0' to helloworld.

Étape 3 : Ajouter un exemple de code

Lors de cette étape, nous ajoutons le code XAML qui définit l’interface utilisateur de l’application, puis ajoutons l’implémentation du code-behind C#.

Code XAML

Créez l’interface utilisateur de l’application en ajoutant le code XAML.

  1. Dans l’Explorateur de solutions, ouvrez MainPage.xaml

  2. Dans la vue XAML du concepteur, remplacez tout le contenu par l’extrait de code suivant :

    <Page
        x:Class="helloworld.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:helloworld"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    
        <Grid>
            <StackPanel Orientation="Vertical" HorizontalAlignment="Center"
                        Margin="20,50,0,0" VerticalAlignment="Center" Width="800">
                <Button x:Name="EnableMicrophoneButton" Content="Enable Microphone"
                        Margin="0,10,10,0" Click="EnableMicrophone_ButtonClicked"
                        Height="35"/>
                <Button x:Name="ListenButton" Content="Talk"
                        Margin="0,10,10,0" Click="ListenButton_ButtonClicked"
                        Height="35"/>
                <StackPanel x:Name="StatusPanel" Orientation="Vertical"
                            RelativePanel.AlignBottomWithPanel="True"
                            RelativePanel.AlignRightWithPanel="True"
                            RelativePanel.AlignLeftWithPanel="True">
                    <TextBlock x:Name="StatusLabel" Margin="0,10,10,0"
                               TextWrapping="Wrap" Text="Status:" FontSize="20"/>
                    <Border x:Name="StatusBorder" Margin="0,0,0,0">
                        <ScrollViewer VerticalScrollMode="Auto"
                                      VerticalScrollBarVisibility="Auto" MaxHeight="200">
                            <!-- Use LiveSetting to enable screen readers to announce
                                 the status update. -->
                            <TextBlock
                                x:Name="StatusBlock" FontWeight="Bold"
                                AutomationProperties.LiveSetting="Assertive"
                                MaxWidth="{Binding ElementName=Splitter, Path=ActualWidth}"
                                Margin="10,10,10,20" TextWrapping="Wrap"  />
                        </ScrollViewer>
                    </Border>
                </StackPanel>
            </StackPanel>
            <MediaElement x:Name="mediaElement"/>
        </Grid>
    </Page>
    

Le mode Création est mis à jour pour afficher l’interface utilisateur de l’application.

Source du code-behind C#

Ajoutez la source du code-behind pour que l’application fonctionne comme prévu. La source du code-behind inclut :

  • Instructions using requises pour les espaces de noms Speech et Speech.Dialog
  • Une implémentation simple pour garantir l’accès au microphone, couplé à un gestionnaire de bouton
  • Des assistances d’interface utilisateur de base pour présenter des messages et des erreurs dans l’application
  • Un point d’arrivée du chemin du code d’initialisation qui sera rempli plus tard
  • Une assistance pour lire la synthèse vocale (sans prise en charge du streaming)
  • Un gestionnaire de bouton vide pour commencer l’écoute qui sera rempli plus tard

Ajoutez la source du code-behind en procédant comme suit :

  1. Dans l’Explorateur de solutions, ouvrez le fichier source code-behind MainPage.xaml.cs (regroupé sous MainPage.xaml).

  2. Remplacez le contenu du fichier par le code suivant :

    using Microsoft.CognitiveServices.Speech;
    using Microsoft.CognitiveServices.Speech.Audio;
    using Microsoft.CognitiveServices.Speech.Dialog;
    using System;
    using System.IO;
    using System.Text;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    
    namespace helloworld
    {
        public sealed partial class MainPage : Page
        {
            private DialogServiceConnector connector;
    
            private enum NotifyType
            {
                StatusMessage,
                ErrorMessage
            };
    
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void EnableMicrophone_ButtonClicked(
                object sender, RoutedEventArgs e)
            {
                bool isMicAvailable = true;
                try
                {
                    var mediaCapture = new Windows.Media.Capture.MediaCapture();
                    var settings =
                        new Windows.Media.Capture.MediaCaptureInitializationSettings();
                    settings.StreamingCaptureMode =
                        Windows.Media.Capture.StreamingCaptureMode.Audio;
                    await mediaCapture.InitializeAsync(settings);
                }
                catch (Exception)
                {
                    isMicAvailable = false;
                }
                if (!isMicAvailable)
                {
                    await Windows.System.Launcher.LaunchUriAsync(
                        new Uri("ms-settings:privacy-microphone"));
                }
                else
                {
                    NotifyUser("Microphone was enabled", NotifyType.StatusMessage);
                }
            }
    
            private void NotifyUser(
                string strMessage, NotifyType type = NotifyType.StatusMessage)
            {
                // If called from the UI thread, then update immediately.
                // Otherwise, schedule a task on the UI thread to perform the update.
                if (Dispatcher.HasThreadAccess)
                {
                    UpdateStatus(strMessage, type);
                }
                else
                {
                    var task = Dispatcher.RunAsync(
                        Windows.UI.Core.CoreDispatcherPriority.Normal,
                        () => UpdateStatus(strMessage, type));
                }
            }
    
            private void UpdateStatus(string strMessage, NotifyType type)
            {
                switch (type)
                {
                    case NotifyType.StatusMessage:
                        StatusBorder.Background = new SolidColorBrush(
                            Windows.UI.Colors.Green);
                        break;
                    case NotifyType.ErrorMessage:
                        StatusBorder.Background = new SolidColorBrush(
                            Windows.UI.Colors.Red);
                        break;
                }
                StatusBlock.Text += string.IsNullOrEmpty(StatusBlock.Text)
                    ? strMessage : "\n" + strMessage;
    
                if (!string.IsNullOrEmpty(StatusBlock.Text))
                {
                    StatusBorder.Visibility = Visibility.Visible;
                    StatusPanel.Visibility = Visibility.Visible;
                }
                else
                {
                    StatusBorder.Visibility = Visibility.Collapsed;
                    StatusPanel.Visibility = Visibility.Collapsed;
                }
                // Raise an event if necessary to enable a screen reader
                // to announce the status update.
                var peer = Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer.FromElement(StatusBlock);
                if (peer != null)
                {
                    peer.RaiseAutomationEvent(
                        Windows.UI.Xaml.Automation.Peers.AutomationEvents.LiveRegionChanged);
                }
            }
    
            // Waits for and accumulates all audio associated with a given
            // PullAudioOutputStream and then plays it to the MediaElement. Long spoken
            // audio will create extra latency and a streaming playback solution
            // (that plays audio while it continues to be received) should be used --
            // see the samples for examples of this.
            private void SynchronouslyPlayActivityAudio(
                PullAudioOutputStream activityAudio)
            {
                var playbackStreamWithHeader = new MemoryStream();
                playbackStreamWithHeader.Write(Encoding.ASCII.GetBytes("RIFF"), 0, 4); // ChunkID
                playbackStreamWithHeader.Write(BitConverter.GetBytes(UInt32.MaxValue), 0, 4); // ChunkSize: max
                playbackStreamWithHeader.Write(Encoding.ASCII.GetBytes("WAVE"), 0, 4); // Format
                playbackStreamWithHeader.Write(Encoding.ASCII.GetBytes("fmt "), 0, 4); // Subchunk1ID
                playbackStreamWithHeader.Write(BitConverter.GetBytes(16), 0, 4); // Subchunk1Size: PCM
                playbackStreamWithHeader.Write(BitConverter.GetBytes(1), 0, 2); // AudioFormat: PCM
                playbackStreamWithHeader.Write(BitConverter.GetBytes(1), 0, 2); // NumChannels: mono
                playbackStreamWithHeader.Write(BitConverter.GetBytes(16000), 0, 4); // SampleRate: 16kHz
                playbackStreamWithHeader.Write(BitConverter.GetBytes(32000), 0, 4); // ByteRate
                playbackStreamWithHeader.Write(BitConverter.GetBytes(2), 0, 2); // BlockAlign
                playbackStreamWithHeader.Write(BitConverter.GetBytes(16), 0, 2); // BitsPerSample: 16-bit
                playbackStreamWithHeader.Write(Encoding.ASCII.GetBytes("data"), 0, 4); // Subchunk2ID
                playbackStreamWithHeader.Write(BitConverter.GetBytes(UInt32.MaxValue), 0, 4); // Subchunk2Size
    
                byte[] pullBuffer = new byte[2056];
    
                uint lastRead = 0;
                do
                {
                    lastRead = activityAudio.Read(pullBuffer);
                    playbackStreamWithHeader.Write(pullBuffer, 0, (int)lastRead);
                }
                while (lastRead == pullBuffer.Length);
    
                var task = Dispatcher.RunAsync(
                    Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    mediaElement.SetSource(
                        playbackStreamWithHeader.AsRandomAccessStream(), "audio/wav");
                    mediaElement.Play();
                });
            }
    
            private void InitializeDialogServiceConnector()
            {
                // New code will go here
            }
    
            private async void ListenButton_ButtonClicked(
                object sender, RoutedEventArgs e)
            {
                // New code will go here
            }
        }
    }
    

    Notes

    Si vous voyez l'erreur : « Le type "Object" est défini dans un assembly qui n'est pas référencé »

    1. Cliquez avec le bouton droit sur votre solution.
    2. Sélectionnez Gérer les packages NuGet de la solution, puis Mises à jour.
    3. Si Microsoft.NETCore.UniversalWindowsPlatform figure dans la liste des mises à jour, mettez à jour Microsoft.NETCore.UniversalWindowsPlatform vers la dernière version.
  3. Ajoutez le code suivant au corps de la méthode de InitializeDialogServiceConnector

    // This code creates the `DialogServiceConnector` with your subscription information.
    // create a DialogServiceConfig by providing a Custom Commands application id and Cognitive Services subscription key
    // the RecoLanguage property is optional (default en-US); note that only en-US is supported in Preview
    const string speechCommandsApplicationId = "YourApplicationId"; // Your application id
    const string speechSubscriptionKey = "YourSpeechSubscriptionKey"; // Your subscription key
    const string region = "YourServiceRegion"; // The subscription service region. 
    
    var speechCommandsConfig = CustomCommandsConfig.FromSubscription(speechCommandsApplicationId, speechSubscriptionKey, region);
    speechCommandsConfig.SetProperty(PropertyId.SpeechServiceConnection_RecoLanguage, "en-us");
    connector = new DialogServiceConnector(speechCommandsConfig);
    
  4. Remplacez les chaînes YourApplicationId, YourSpeechSubscriptionKey et YourServiceRegion par vos propres valeurs pour votre application, votre abonnement Speech et votre région

  5. Ajoutez l’extrait de code suivant à la fin du corps de la méthode InitializeDialogServiceConnector

    //
    // This code sets up handlers for events relied on by `DialogServiceConnector` to communicate its activities,
    // speech recognition results, and other information.
    //
    // ActivityReceived is the main way your client will receive messages, audio, and events
    connector.ActivityReceived += (sender, activityReceivedEventArgs) =>
    {
        NotifyUser(
            $"Activity received, hasAudio={activityReceivedEventArgs.HasAudio} activity={activityReceivedEventArgs.Activity}");
    
        if (activityReceivedEventArgs.HasAudio)
        {
            SynchronouslyPlayActivityAudio(activityReceivedEventArgs.Audio);
        }
    };
    
    // Canceled will be signaled when a turn is aborted or experiences an error condition
    connector.Canceled += (sender, canceledEventArgs) =>
    {
        NotifyUser($"Canceled, reason={canceledEventArgs.Reason}");
        if (canceledEventArgs.Reason == CancellationReason.Error)
        {
            NotifyUser(
                $"Error: code={canceledEventArgs.ErrorCode}, details={canceledEventArgs.ErrorDetails}");
        }
    };
    
    // Recognizing (not 'Recognized') will provide the intermediate recognized text
    // while an audio stream is being processed
    connector.Recognizing += (sender, recognitionEventArgs) =>
    {
        NotifyUser($"Recognizing! in-progress text={recognitionEventArgs.Result.Text}");
    };
    
    // Recognized (not 'Recognizing') will provide the final recognized text
    // once audio capture is completed
    connector.Recognized += (sender, recognitionEventArgs) =>
    {
        NotifyUser($"Final speech-to-text result: '{recognitionEventArgs.Result.Text}'");
    };
    
    // SessionStarted will notify when audio begins flowing to the service for a turn
    connector.SessionStarted += (sender, sessionEventArgs) =>
    {
        NotifyUser($"Now Listening! Session started, id={sessionEventArgs.SessionId}");
    };
    
    // SessionStopped will notify when a turn is complete and
    // it's safe to begin listening again
    connector.SessionStopped += (sender, sessionEventArgs) =>
    {
        NotifyUser($"Listening complete. Session ended, id={sessionEventArgs.SessionId}");
    };
    
  6. Ajoutez l’extrait de code suivant au corps de la méthode ListenButton_ButtonClicked dans la classe MainPage

    // This code sets up `DialogServiceConnector` to listen, since you already established the configuration and
    // registered the event handlers.
    if (connector == null)
    {
        InitializeDialogServiceConnector();
        // Optional step to speed up first interaction: if not called,
        // connection happens automatically on first use
        var connectTask = connector.ConnectAsync();
    }
    
    try
    {
        // Start sending audio
        await connector.ListenOnceAsync();
    }
    catch (Exception ex)
    {
        NotifyUser($"Exception: {ex.ToString()}", NotifyType.ErrorMessage);
    }
    
  7. Dans la barre de menus, choisissez Fichier>Enregistrer tout pour enregistrer vos modifications

Faites un essai

  1. Dans la barre de menus, choisissez Générer>Générer la solution pour générer l’application. Le code doit se compiler sans erreur.

  2. Choisissez Déboguer>Démarrer le débogage (ou appuyez sur F5) pour démarrer l’application. La fenêtre helloworld s’affiche.

    Sample UWP virtual assistant application in C# - quickstart

  3. Sélectionnez Activer le microphone. Si la demande d’autorisation d’accès apparaît, sélectionnez Oui.

    Microphone access permission request

  4. Sélectionnez Talk (Parler) et prononcez une phrase ou quelques mots en anglais dans le micro de votre appareil. Votre production orale est transmise au canal Direct Line Speech, et transcrite en texte qui apparaît dans la fenêtre.

Étapes suivantes