Szybki start: tworzenie niestandardowego asystenta głosowego
W tym przewodniku Szybki start utworzysz niestandardową aplikację asystenta głosowego, która łączy się z botem, który został już utworzony i skonfigurowany za pomocą zestawu SDK usługi Mowa. Jeśli musisz utworzyć bota, zapoznaj się z powiązanym samouczkiem , aby zapoznać się z bardziej kompleksowym przewodnikiem.
Po spełnieniu kilku wymagań wstępnych połączenie niestandardowego asystenta głosowego wykonuje tylko kilka kroków:
- Utwórz
BotFrameworkConfig
obiekt na podstawie klucza subskrypcji i regionu. DialogServiceConnector
Utwórz obiekt przy użyciu obiektu z powyższegoBotFrameworkConfig
.DialogServiceConnector
Za pomocą obiektu uruchom proces nasłuchiwania pojedynczej wypowiedzi.- Sprawdź zwrócone
ActivityReceivedEventArgs
dane.
Uwaga
Zestaw SPEECH SDK dla języków C++, JavaScript, Objective-C, Python i Swift obsługuje niestandardowe asystenty głosowe, ale nie dołączyliśmy jeszcze tutaj przewodnika.
Wszystkie przykłady języka C# zestawu SPEECH SDK można wyświetlić lub pobrać w witrynie GitHub.
Wymagania wstępne
Przed rozpoczęciem upewnij się, że:
- Tworzenie zasobu usługi Mowa
- Konfigurowanie środowiska projektowego i tworzenie pustego projektu
- Tworzenie bota połączonego z kanałem mowy direct line
- Upewnij się, że masz dostęp do mikrofonu na potrzeby przechwytywania dźwięku
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
Otwieranie projektu w programie Visual Studio
Pierwszym krokiem jest upewnienie się, że projekt jest otwarty w programie Visual Studio.
Zacznij od kodu kociołowego
Dodajmy kod, który działa jako szkielet naszego projektu.
W Eksplorator rozwiązań otwórz plik
MainPage.xaml
.W widoku XAML projektanta zastąp całą zawartość następującym fragmentem kodu, który definiuje podstawowe interfejs użytkownika:
<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,0,10,0" Click="EnableMicrophone_ButtonClicked" Height="35"/> <Button x:Name="ListenButton" Content="Talk to your bot" 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>
Widok Projekt jest aktualizowany w celu wyświetlenia interfejsu użytkownika aplikacji.
- W Eksplorator rozwiązań otwórz plik
MainPage.xaml.cs
źródłowy za kodem . (Jest ona pogrupowana w obszarzeMainPage.xaml
.) Zastąp zawartość tego pliku poniższym ciągiem, który obejmuje:
using
instrukcje dlaSpeech
przestrzeni nazw iSpeech.Dialog
Prosta implementacja zapewniająca dostęp do mikrofonu, przewodową do procedury obsługi przycisków
Podstawowe pomocniki interfejsu użytkownika do prezentowania komunikatów i błędów w aplikacji
Punkt docelowy ścieżki kodu inicjowania, która zostanie wypełniona później
Pomocnik do odtwarzania tekstu na mowę (bez obsługi przesyłania strumieniowego)
Pusta procedura obsługi przycisków w celu rozpoczęcia nasłuchiwania, które zostaną wypełnione później
using Microsoft.CognitiveServices.Speech; using Microsoft.CognitiveServices.Speech.Audio; using Microsoft.CognitiveServices.Speech.Dialog; using System; using System.Diagnostics; using System.IO; using System.Text; using Windows.Foundation; using Windows.Storage.Streams; 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 } } }
Dodaj następujący fragment kodu do treści
InitializeDialogServiceConnector
metody . Ten kod tworzy elementDialogServiceConnector
z informacjami o subskrypcji.// Create a BotFrameworkConfig by providing a Speech service subscription key // the botConfig.Language property is optional (default en-US) const string speechSubscriptionKey = "YourSpeechSubscriptionKey"; // Your subscription key const string region = "YourServiceRegion"; // Your subscription service region. var botConfig = BotFrameworkConfig.FromSubscription(speechSubscriptionKey, region); botConfig.Language = "en-US"; connector = new DialogServiceConnector(botConfig);
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
Uwaga
Aby uzyskać informacje na temat konfigurowania bota, zobacz dokumentację platformy Bot Framework dotyczącą kanału mowy direct line.
Zastąp ciągi
YourSpeechSubscriptionKey
iYourServiceRegion
własnymi wartościami dla subskrypcji i regionu mowy.Dołącz poniższy fragment kodu na końcu treści
InitializeDialogServiceConnector
metody . Ten kod konfiguruje programy obsługi zdarzeń, naDialogServiceConnector
których polegają informacje o działaniach bota, wynikach rozpoznawania mowy i innych informacjach.// ActivityReceived is the main way your bot will communicate with the client // and uses bot framework activities 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}"); };
Dodaj następujący fragment kodu do treści
ListenButton_ButtonClicked
metody wMainPage
klasie . Ten kod konfiguruje nasłuchiwanieDialogServiceConnector
, ponieważ już ustanowiono konfigurację i zarejestrowano programy obsługi zdarzeń.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 to your speech-enabled bot var listenTask = connector.ListenOnceAsync(); // You can also send activities to your bot as JSON strings -- // Microsoft.Bot.Schema can simplify this string speakActivity = @"{""type"":""message"",""text"":""Greeting Message"", ""speak"":""Hello there!""}"; await connector.SendActivityAsync(speakActivity); } catch (Exception ex) { NotifyUser($"Exception: {ex.ToString()}", NotifyType.ErrorMessage); }
Kompilowanie i uruchamianie aplikacji
Teraz możesz przystąpić do kompilowania aplikacji i testowania niestandardowego asystenta głosowego przy użyciu usługi Mowa.
Na pasku menu wybierz pozycję Kompiluj>rozwiązanie kompilacji, aby skompilować aplikację. Kod powinien teraz zostać skompilowany bez błędów.
Wybierz pozycję Debuguj>Rozpocznij debugowanie (lub naciśnij F5), aby uruchomić aplikację. Zostanie wyświetlone okno helloworld .
Wybierz pozycję Włącz mikrofon, a po wyświetleniu żądania uprawnień dostępu wybierz pozycję Tak.
Wybierz pozycję Porozmawiaj z botem i powiedz frazę w języku angielskim lub zdanie do mikrofonu urządzenia. Twoja mowa jest przesyłana do kanału mowy direct line i transkrybowana do tekstu, który pojawia się w oknie.
Następne kroki
Możesz wyświetlić lub pobrać wszystkie przykłady języka Java zestawu SDK usługi Mowa w witrynie GitHub.
Wybieranie środowiska docelowego
Wymagania wstępne
Przed rozpoczęciem upewnij się, że:
- Tworzenie zasobu usługi Mowa
- Konfigurowanie środowiska projektowego i tworzenie pustego projektu
- Tworzenie bota połączonego z kanałem mowy direct line
- Upewnij się, że masz dostęp do mikrofonu na potrzeby przechwytywania dźwięku
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
Tworzenie i konfigurowanie projektu
Utwórz projekt środowiska Eclipse i zainstaluj zestaw SPEECH SDK.
Ponadto, aby włączyć rejestrowanie, zaktualizuj plik pom.xml , aby uwzględnić następującą zależność:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
Dodawanie przykładowego kodu
Aby dodać nową pustą klasę do projektu języka Java, wybierz kolejno pozycje Plik>Nowy>Klasa.
W oknie Nowa klasa Java wprowadź ciąg speechsdk.quickstart w polu Pakiet i w polu Nazwa.
Otwórz nowo utworzoną
Main
klasę i zastąp zawartośćMain.java
pliku następującym kodem początkowym:package speechsdk.quickstart; import com.microsoft.cognitiveservices.speech.audio.AudioConfig; import com.microsoft.cognitiveservices.speech.audio.PullAudioOutputStream; import com.microsoft.cognitiveservices.speech.dialog.BotFrameworkConfig; import com.microsoft.cognitiveservices.speech.dialog.DialogServiceConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.SourceDataLine; import java.io.InputStream; public class Main { final Logger log = LoggerFactory.getLogger(Main.class); public static void main(String[] args) { // New code will go here } private void playAudioStream(PullAudioOutputStream audio) { ActivityAudioStream stream = new ActivityAudioStream(audio); final ActivityAudioStream.ActivityAudioFormat audioFormat = stream.getActivityAudioFormat(); final AudioFormat format = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, audioFormat.getSamplesPerSecond(), audioFormat.getBitsPerSample(), audioFormat.getChannels(), audioFormat.getFrameSize(), audioFormat.getSamplesPerSecond(), false); try { int bufferSize = format.getFrameSize(); final byte[] data = new byte[bufferSize]; SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); if (line != null) { line.start(); int nBytesRead = 0; while (nBytesRead != -1) { nBytesRead = stream.read(data); if (nBytesRead != -1) { line.write(data, 0, nBytesRead); } } line.drain(); line.stop(); line.close(); } stream.close(); } catch (Exception e) { e.printStackTrace(); } } }
W metodzie
main
należy najpierw skonfigurować klasęDialogServiceConfig
i użyć jej do utworzeniaDialogServiceConnector
wystąpienia. To wystąpienie łączy się z kanałem mowy direct line w celu interakcji z botem. WystąpienieAudioConfig
służy również do określania źródła danych wejściowych audio. W tym przykładzie domyślny mikrofon jest używany zAudioConfig.fromDefaultMicrophoneInput()
.- Zastąp ciąg
YourSubscriptionKey
kluczem zasobu usługi Mowa, który można pobrać z witryny Azure Portal. - Zastąp ciąg
YourServiceRegion
regionem skojarzonym z zasobem usługi Mowa.
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
final String subscriptionKey = "YourSubscriptionKey"; // Your subscription key final String region = "YourServiceRegion"; // Your speech subscription service region final BotFrameworkConfig botConfig = BotFrameworkConfig.fromSubscription(subscriptionKey, region); // Configure audio input from a microphone. final AudioConfig audioConfig = AudioConfig.fromDefaultMicrophoneInput(); // Create a DialogServiceConnector instance. final DialogServiceConnector connector = new DialogServiceConnector(botConfig, audioConfig);
- Zastąp ciąg
Łącznik
DialogServiceConnector
opiera się na kilku zdarzeniach, aby komunikować swoje działania bota, wyniki rozpoznawania mowy i inne informacje. Dodaj te odbiorniki zdarzeń dalej.// Recognizing will provide the intermediate recognized text while an audio stream is being processed. connector.recognizing.addEventListener((o, speechRecognitionResultEventArgs) -> { log.info("Recognizing speech event text: {}", speechRecognitionResultEventArgs.getResult().getText()); }); // Recognized will provide the final recognized text once audio capture is completed. connector.recognized.addEventListener((o, speechRecognitionResultEventArgs) -> { log.info("Recognized speech event reason text: {}", speechRecognitionResultEventArgs.getResult().getText()); }); // SessionStarted will notify when audio begins flowing to the service for a turn. connector.sessionStarted.addEventListener((o, sessionEventArgs) -> { log.info("Session Started event id: {} ", sessionEventArgs.getSessionId()); }); // SessionStopped will notify when a turn is complete and it's safe to begin listening again. connector.sessionStopped.addEventListener((o, sessionEventArgs) -> { log.info("Session stopped event id: {}", sessionEventArgs.getSessionId()); }); // Canceled will be signaled when a turn is aborted or experiences an error condition. connector.canceled.addEventListener((o, canceledEventArgs) -> { log.info("Canceled event details: {}", canceledEventArgs.getErrorDetails()); connector.disconnectAsync(); }); // ActivityReceived is the main way your bot will communicate with the client and uses Bot Framework activities. connector.activityReceived.addEventListener((o, activityEventArgs) -> { final String act = activityEventArgs.getActivity().serialize(); log.info("Received activity {} audio", activityEventArgs.hasAudio() ? "with" : "without"); if (activityEventArgs.hasAudio()) { playAudioStream(activityEventArgs.getAudio()); } });
Połącz się z
DialogServiceConnector
usługą Direct Line Speech, wywołując metodęconnectAsync()
. Aby przetestować bota, możesz wywołać metodęlistenOnceAsync
wysyłania danych wejściowych audio z mikrofonu. Ponadto można również użyćsendActivityAsync
metody , aby wysłać działanie niestandardowe jako ciąg serializowany. Te niestandardowe działania mogą udostępniać dodatkowe dane używane przez bota w konwersacji.connector.connectAsync(); // Start listening. System.out.println("Say something ..."); connector.listenOnceAsync(); // connector.sendActivityAsync(...)
Zapisz zmiany w
Main
pliku.Aby obsługiwać odtwarzanie odpowiedzi, dodaj dodatkową klasę, która przekształca obiekt PullAudioOutputStream zwrócony z interfejsu API getAudio() do strumienia wejściowego Java w celu ułatwienia obsługi. Jest to
ActivityAudioStream
wyspecjalizowana klasa, która obsługuje odpowiedź audio z kanału mowy direct line. Zapewnia metody dostępu do pobierania informacji o formacie audio, które są wymagane do obsługi odtwarzania. W tym celu wybierz pozycję Plik>Nowa>klasa.W oknie Nowa klasa Java wprowadź ciąg speechsdk.quickstart w polu Pakiet i ActivityAudioStream w polu Nazwa.
Otwórz nowo utworzoną
ActivityAudioStream
klasę i zastąp ją następującym kodem:package com.speechsdk.quickstart; import com.microsoft.cognitiveservices.speech.audio.PullAudioOutputStream; import java.io.IOException; import java.io.InputStream; public final class ActivityAudioStream extends InputStream { /** * The number of samples played per second (16 kHz). */ public static final long SAMPLE_RATE = 16000; /** * The number of bits in each sample of a sound that has this format (16 bits). */ public static final int BITS_PER_SECOND = 16; /** * The number of audio channels in this format (1 for mono). */ public static final int CHANNELS = 1; /** * The number of bytes in each frame of a sound that has this format (2). */ public static final int FRAME_SIZE = 2; /** * Reads up to a specified maximum number of bytes of data from the audio * stream, putting them into the given byte array. * * @param b the buffer into which the data is read * @param off the offset, from the beginning of array <code>b</code>, at which * the data will be written * @param len the maximum number of bytes to read * @return the total number of bytes read into the buffer, or -1 if there * is no more data because the end of the stream has been reached */ @Override public int read(byte[] b, int off, int len) { byte[] tempBuffer = new byte[len]; int n = (int) this.pullStreamImpl.read(tempBuffer); for (int i = 0; i < n; i++) { if (off + i > b.length) { throw new ArrayIndexOutOfBoundsException(b.length); } b[off + i] = tempBuffer[i]; } if (n == 0) { return -1; } return n; } /** * Reads the next byte of data from the activity audio stream if available. * * @return the next byte of data, or -1 if the end of the stream is reached * @see #read(byte[], int, int) * @see #read(byte[]) * @see #available * <p> */ @Override public int read() { byte[] data = new byte[1]; int temp = read(data); if (temp <= 0) { // we have a weird situation if read(byte[]) returns 0! return -1; } return data[0] & 0xFF; } /** * Reads up to a specified maximum number of bytes of data from the activity audio stream, * putting them into the given byte array. * * @param b the buffer into which the data is read * @return the total number of bytes read into the buffer, or -1 if there * is no more data because the end of the stream has been reached */ @Override public int read(byte[] b) { int n = (int) pullStreamImpl.read(b); if (n == 0) { return -1; } return n; } /** * Skips over and discards a specified number of bytes from this * audio input stream. * * @param n the requested number of bytes to be skipped * @return the actual number of bytes skipped * @throws IOException if an input or output error occurs * @see #read * @see #available */ @Override public long skip(long n) { if (n <= 0) { return 0; } if (n <= Integer.MAX_VALUE) { byte[] tempBuffer = new byte[(int) n]; return read(tempBuffer); } long count = 0; for (long i = n; i > 0; i -= Integer.MAX_VALUE) { int size = (int) Math.min(Integer.MAX_VALUE, i); byte[] tempBuffer = new byte[size]; count += read(tempBuffer); } return count; } /** * Closes this audio input stream and releases any system resources associated * with the stream. */ @Override public void close() { this.pullStreamImpl.close(); } /** * Fetch the audio format for the ActivityAudioStream. The ActivityAudioFormat defines the sample rate, bits per sample, and the # channels. * * @return instance of the ActivityAudioFormat associated with the stream */ public ActivityAudioStream.ActivityAudioFormat getActivityAudioFormat() { return activityAudioFormat; } /** * Returns the maximum number of bytes that can be read (or skipped over) from this * audio input stream without blocking. * * @return the number of bytes that can be read from this audio input stream without blocking. * As this implementation does not buffer, this will be defaulted to 0 */ @Override public int available() { return 0; } public ActivityAudioStream(final PullAudioOutputStream stream) { pullStreamImpl = stream; this.activityAudioFormat = new ActivityAudioStream.ActivityAudioFormat(SAMPLE_RATE, BITS_PER_SECOND, CHANNELS, FRAME_SIZE, AudioEncoding.PCM_SIGNED); } private PullAudioOutputStream pullStreamImpl; private ActivityAudioFormat activityAudioFormat; /** * ActivityAudioFormat is an internal format which contains metadata regarding the type of arrangement of * audio bits in this activity audio stream. */ static class ActivityAudioFormat { private long samplesPerSecond; private int bitsPerSample; private int channels; private int frameSize; private AudioEncoding encoding; public ActivityAudioFormat(long samplesPerSecond, int bitsPerSample, int channels, int frameSize, AudioEncoding encoding) { this.samplesPerSecond = samplesPerSecond; this.bitsPerSample = bitsPerSample; this.channels = channels; this.encoding = encoding; this.frameSize = frameSize; } /** * Fetch the number of samples played per second for the associated audio stream format. * * @return the number of samples played per second */ public long getSamplesPerSecond() { return samplesPerSecond; } /** * Fetch the number of bits in each sample of a sound that has this audio stream format. * * @return the number of bits per sample */ public int getBitsPerSample() { return bitsPerSample; } /** * Fetch the number of audio channels used by this audio stream format. * * @return the number of channels */ public int getChannels() { return channels; } /** * Fetch the default number of bytes in a frame required by this audio stream format. * * @return the number of bytes */ public int getFrameSize() { return frameSize; } /** * Fetch the audio encoding type associated with this audio stream format. * * @return the encoding associated */ public AudioEncoding getEncoding() { return encoding; } } /** * Enum defining the types of audio encoding supported by this stream. */ public enum AudioEncoding { PCM_SIGNED("PCM_SIGNED"); String value; AudioEncoding(String value) { this.value = value; } } }
Zapisz zmiany w
ActivityAudioStream
pliku.
Skompiluj i uruchom aplikację
Wybierz pozycję F11 lub wybierz pozycję Uruchom>debugowanie.
Konsola wyświetla komunikat "Powiedz coś". W tym momencie wypowiadaj frazę w języku angielskim lub zdanie, które bot może zrozumieć. Twoja mowa jest przesyłana do bota za pośrednictwem kanału mowy direct line, w którym jest rozpoznawana i przetwarzana przez bota. Odpowiedź jest zwracana jako działanie. Jeśli bot zwraca mowę jako odpowiedź, dźwięk jest odtwarzany przy użyciu AudioPlayer
klasy .
Następne kroki
Możesz wyświetlić lub pobrać wszystkie przykłady języka Go zestawu SDK usługi Mowa w witrynie GitHub.
Wymagania wstępne
Przed rozpoczęciem pracy:
- Tworzenie zasobu usługi Mowa
- Konfigurowanie środowiska projektowego i tworzenie pustego projektu
- Tworzenie bota połączonego z kanałem mowy direct line
- Upewnij się, że masz dostęp do mikrofonu na potrzeby przechwytywania dźwięku
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
Konfigurowanie środowiska
Zaktualizuj plik go.mod przy użyciu najnowszej wersji zestawu SDK, dodając ten wiersz
require (
github.com/Microsoft/cognitive-services-speech-sdk-go v1.15.0
)
Zacznij od kodu kociołowego
Zastąp zawartość pliku źródłowego (np. quickstart.go
) poniższym ciągiem, który obejmuje:
- Definicja pakietu "main"
- importowanie niezbędnych modułów z zestawu Speech SDK
- zmienne do przechowywania informacji o botze, które zostaną zastąpione w dalszej części tego przewodnika Szybki start
- prosta implementacja przy użyciu mikrofonu do wprowadzania dźwięku
- programy obsługi zdarzeń dla różnych zdarzeń, które odbywają się podczas interakcji z mową
package main
import (
"fmt"
"time"
"github.com/Microsoft/cognitive-services-speech-sdk-go/audio"
"github.com/Microsoft/cognitive-services-speech-sdk-go/dialog"
"github.com/Microsoft/cognitive-services-speech-sdk-go/speech"
)
func main() {
subscription := "YOUR_SUBSCRIPTION_KEY"
region := "YOUR_BOT_REGION"
audioConfig, err := audio.NewAudioConfigFromDefaultMicrophoneInput()
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer audioConfig.Close()
config, err := dialog.NewBotFrameworkConfigFromSubscription(subscription, region)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer config.Close()
connector, err := dialog.NewDialogServiceConnectorFromConfig(config, audioConfig)
if err != nil {
fmt.Println("Got an error: ", err)
return
}
defer connector.Close()
activityReceivedHandler := func(event dialog.ActivityReceivedEventArgs) {
defer event.Close()
fmt.Println("Received an activity.")
}
connector.ActivityReceived(activityReceivedHandler)
recognizedHandle := func(event speech.SpeechRecognitionEventArgs) {
defer event.Close()
fmt.Println("Recognized ", event.Result.Text)
}
connector.Recognized(recognizedHandle)
recognizingHandler := func(event speech.SpeechRecognitionEventArgs) {
defer event.Close()
fmt.Println("Recognizing ", event.Result.Text)
}
connector.Recognizing(recognizingHandler)
connector.ListenOnceAsync()
<-time.After(10 * time.Second)
}
YOUR_SUBSCRIPTION_KEY
Zastąp wartości i YOUR_BOT_REGION
rzeczywistymi wartościami z zasobu usługi Mowa.
Przejdź do witryny Azure Portal i otwórz zasób usługi Mowa
W obszarze Klucze i punkt końcowy po lewej stronie znajdują się dwa dostępne klucze subskrypcji
- Użyj jednej z nich jako zamiany
YOUR_SUBSCRIPTION_KEY
wartości
- Użyj jednej z nich jako zamiany
W obszarze Przegląd po lewej stronie zanotuj region i zamapuj go na identyfikator regionu
- Użyj identyfikatora regionu jako wartości zastępczej
YOUR_BOT_REGION
, na przykład:"westus"
dla zachodnich stanów USA
Uwaga
Zapoznaj się z listą obsługiwanych regionów dla asystentów głosowych i upewnij się, że zasoby są wdrażane w jednym z tych regionów.
Uwaga
Aby uzyskać informacje na temat konfigurowania bota, zobacz dokumentację platformy Bot Framework dotyczącą kanału mowy direct line.
- Użyj identyfikatora regionu jako wartości zastępczej
Wyjaśnienie kodu
Klucz subskrypcji usługi Mowa i region są wymagane do utworzenia obiektu konfiguracji mowy. Obiekt konfiguracji jest potrzebny do utworzenia wystąpienia obiektu rozpoznawania mowy.
Wystąpienie rozpoznawania uwidacznia wiele sposobów rozpoznawania mowy. W tym przykładzie mowa jest stale rozpoznawana. Ta funkcja pozwala usłudze Rozpoznawanie mowy wiedzieć, że wysyłasz wiele fraz do rozpoznawania, a gdy program zakończy rozpoznawanie mowy. W miarę zwracania wyników kod zapisze je w konsoli.
Kompilowanie i uruchamianie
Teraz skonfigurujesz projekt i przetestujesz niestandardowy asystent głosowy przy użyciu usługi Mowa.
- Kompilowanie projektu, np. "go build"
- Uruchom moduł i powiedz frazę lub zdanie do mikrofonu urządzenia. Twoja mowa jest przesyłana do kanału mowy direct line i transkrybowana na tekst, który jest wyświetlany jako dane wyjściowe.
Uwaga
Zestaw SDK rozpoznawania mowy będzie domyślnie rozpoznawany przy użyciu języka en-us. Zobacz Jak rozpoznawać mowę , aby uzyskać informacje na temat wybierania języka źródłowego.
Następne kroki
Dodatkowa obsługa języka i platformy
Jeśli klikniesz tę kartę, prawdopodobnie nie widzisz przewodnika Szybki start w ulubionym języku programowania. Nie martw się, mamy dodatkowe materiały szybki start i przykłady kodu dostępne w witrynie GitHub. Skorzystaj z tabeli, aby znaleźć odpowiedni przykład dla języka programowania i kombinacji platformy/systemu operacyjnego.
Język | Przykłady kodu |
---|---|
C# | .NET Framework, .NET Core, UWP, Unity |
C++ | Windows, Linux, macOS |
Java | Android, JRE |
JavaScript | Przeglądarka, Node.js |
Objective-C | iOS, macOS |
Python | Windows, Linux, macOS |
Swift | iOS, macOS |