Integrálás ügyfélalkalmazással a Speech SDK használatával
Fontos
Az egyéni parancsok 2026. április 30-án megszűnnek. 2023. október 30-ától nem hozhat létre új Egyéni parancsokat a Speech Studióban. A módosítással kapcsolatban a LUIS 2025. október 1-jén megszűnik. 2023. április 1-től nem hozhat létre új LUIS-erőforrásokat.
Ebből a cikkből megtudhatja, hogyan kérheti le a közzétett Egyéni parancsok alkalmazást az UWP-alkalmazásban futó Speech SDK-ból. Az Egyéni parancsok alkalmazással való kapcsolat létrehozásához a következőkre van szükség:
- Egyéni parancsok közzététele és alkalmazásazonosító (alkalmazásazonosító) lekérése
- Hozzon létre egy Univerzális Windows-platform (UWP) ügyfélalkalmazást a Speech SDK használatával, amely lehetővé teszi az egyéni parancsok alkalmazással való beszélgetést
Előfeltételek
A cikk elvégzéséhez egyéni parancsok alkalmazásra van szükség. Próbálkozzon egy gyorsútmutatóval egy egyéni parancsalkalmazás létrehozásához:
Emellett a következőkre van szükség:
- Visual Studio 2019 vagy újabb verzió. Ez az útmutató a Visual Studio 2019-en alapul.
- Azure AI Speech-erőforráskulcs és -régió: Speech-erőforrás létrehozása az Azure Portalon. További információ: Többszolgáltatásos erőforrás létrehozása.
- Eszköz engedélyezése fejlesztéshez
1. lépés: Egyéni parancsok közzététele alkalmazás
Nyissa meg a korábban létrehozott Egyéni parancsok alkalmazást.
Nyissa meg a Gépház, és válassza a LUIS-erőforrást.
Ha az előrejelzési erőforrás nincs hozzárendelve, válasszon ki egy lekérdezés-előrejelzési kulcsot, vagy hozzon létre egy újat.
Az alkalmazás közzététele előtt mindig szükség van a lekérdezés-előrejelzési kulcsra. A LUIS-erőforrásokról további információt a LUIS-erőforrás létrehozása című témakörben talál .
Lépjen vissza a Parancsok szerkesztéséhez, válassza a Közzététel lehetőséget.
Másolja ki az alkalmazásazonosítót a "közzététel" értesítésből későbbi használatra.
Másolja a Speech Erőforráskulcsot későbbi használatra.
2. lépés: Visual Studio-projekt létrehozása
Hozzon létre egy Visual Studio-projektet az UWP fejlesztéséhez, és telepítse a Speech SDK-t.
3. lépés: Mintakód hozzáadása
Ebben a lépésben hozzáadjuk az alkalmazás felhasználói felületét meghatározó XAML-kódot, és hozzáadjuk a C#-kód mögötti implementációt.
XAML-kód
Hozza létre az alkalmazás felhasználói felületét az XAML-kód hozzáadásával.
Nyissa meg a Megoldáskezelő
MainPage.xaml
A tervező XAML nézetében cserélje le a teljes tartalmat a következő kódrészletre:
<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>
A Tervező nézet frissül az alkalmazás felhasználói felületének megjelenítéséhez.
C# kód mögötti forrás
Adja hozzá a kód mögötti forrást, hogy az alkalmazás a várt módon működjön. A kód mögötti forrás a következőket tartalmazza:
- Kötelező
using
utasítások a névterekhez ésSpeech.Dialog
aSpeech
névterekhez. - Egyszerű implementáció a mikrofonhoz való hozzáférés biztosításához, egy gombkezelőhöz kapcsolva.
- Egyszerű felhasználói felületi segédek az alkalmazás üzeneteinek és hibáinak megjelenítéséhez.
- Az inicializálási kód elérési útjának kezdőpontja.
- Segéd a szöveg visszajátszásához a beszédhez (streamelés támogatása nélkül).
- Egy üres gombkezelő a figyelés megkezdéséhez.
Adja hozzá a kód mögötti forrást az alábbiak szerint:
A Megoldáskezelő nyissa meg a kód mögötti forrásfájlt
MainPage.xaml.cs
MainPage.xaml
(a )Cserélje le a fájl tartalmát a következő kódra:
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 } } }
Feljegyzés
Ha a következő hibaüzenet jelenik meg: "Az "Objektum" típus egy nem hivatkozott szerelvényben van definiálva"
- A megoldás jobb ügyfélalkalmazása.
- Válassza a Megoldáshoz készült NuGet-csomagok kezelése lehetőséget, válassza a Frissítések
- Ha megjelenik a Microsoft.NETCore.UniversalWindowsPlatform a frissítési listában, frissítse a Microsoft.NETCore.UniversalWindowsPlatformot a legújabb verzióra
Adja hozzá a következő kódot a metódus törzséhez:
InitializeDialogServiceConnector
// This code creates the `DialogServiceConnector` with your resource information. // create a DialogServiceConfig by providing a Custom Commands application id and Speech resource 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 Speech resource key const string region = "YourServiceRegion"; // The Speech resource region. var speechCommandsConfig = CustomCommandsConfig.FromSubscription(speechCommandsApplicationId, speechSubscriptionKey, region); speechCommandsConfig.SetProperty(PropertyId.SpeechServiceConnection_RecoLanguage, "en-us"); connector = new DialogServiceConnector(speechCommandsConfig);
Cserélje le a sztringeket
YourApplicationId
,YourSpeechSubscriptionKey
valamint az alkalmazás, a beszédkulcs ésYourServiceRegion
a régió saját értékeitFűzze hozzá a következő kódrészletet a következő metódustörzs végéhez:
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}"); };
Adja hozzá a következő kódrészletet a
ListenButton_ButtonClicked
metódus törzséhez azMainPage
osztályban// 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); }
A menüsávon válassza az Összes fájl>mentése lehetőséget a módosítások mentéséhez
Próba
A menüsávon válassza a Build Solution (Build Solution)>lehetőséget az alkalmazás létrehozásához. A kód fordításának hiba nélkül kell végbe mennie.
Az alkalmazás elindításához válassza a Hibakeresés indítása hibakeresés>(vagy az F5 billentyű lenyomása) lehetőséget. Megjelenik a helloworld ablak.
Válassza a Mikrofon engedélyezése lehetőséget. Ha megjelenik a hozzáférési engedélykérés, válassza az Igen lehetőséget.
Válassza a Talk lehetőséget, és beszéljen egy angol kifejezéssel vagy mondattal az eszköz mikrofonjába. A beszéd a Direct Line Speech csatornára kerül, és át lesz írva a szövegre, amely megjelenik az ablakban.