Spracherkennung mit Azure Speech Service
Azure Speech Service ist eine cloudbasierte API, die die folgenden Funktionen bietet:
- Speech-to-Text transkribiert Audiodateien oder Streams in Text.
- Text-zu-Sprache wandelt Eingabetext in menschenähnliche synthetisierte Sprache um.
- Die Sprachübersetzung ermöglicht mehrsprachige Echtzeitübersetzungen sowohl für Die Spracherkennung als auch für die Spracherkennung.
- Sprachassistenten können menschenähnliche Konversationsschnittstellen für Anwendungen erstellen.
In diesem Artikel wird erläutert, wie Die Spracherkennung in der Beispielanwendung Xamarin.Forms mithilfe des Azure Speech Service implementiert wird. Die folgenden Screenshots zeigen die Beispielanwendung unter iOS und Android:
Erstellen einer Azure Speech Service-Ressource
Azure Speech Service ist Teil von Azure Cognitive Services, das cloudbasierte APIs für Aufgaben wie Bilderkennung, Spracherkennung und -übersetzung und Bing-Suche bereitstellt. Weitere Informationen finden Sie unter Was sind Azure Cognitive Services?.
Für das Beispielprojekt muss eine Azure Cognitive Services-Ressource in Ihrem Azure-Portal erstellt werden. Eine Cognitive Services-Ressource kann für einen einzelnen Dienst, z. B. Speech Service, oder als Ressource mit mehreren Diensten erstellt werden. Die Schritte zum Erstellen einer Speech Service-Ressource sind wie folgt:
- Melden Sie sich bei Ihrem Azure-Portal an.
- Erstellen Sie eine Ressource mit mehreren oder nur einem Dienst.
- Rufen Sie den API-Schlüssel und die Regionsinformationen für Ihre Ressource ab.
- Aktualisieren Sie die Beispieldatei Constants.cs .
Eine schrittweise Anleitung zum Erstellen einer Ressource finden Sie unter Erstellen einer Cognitive Services-Ressource.
Hinweis
Wenn Sie kein Azure-Abonnement besitzen, erstellen Sie ein kostenloses Konto, bevor Sie beginnen. Sobald Sie über ein Konto verfügen, kann eine einzelne Dienstressource auf dem kostenlosen Tarif erstellt werden, um den Dienst auszuprobieren.
Konfigurieren Ihrer App mit dem Speech-Dienst
Nach dem Erstellen einer Cognitive Services-Ressource kann die Datei Constants.cs mit der Region und dem API-Schlüssel aus Ihrer Azure-Ressource aktualisiert werden:
public static class Constants
{
public static string CognitiveServicesApiKey = "YOUR_KEY_GOES_HERE";
public static string CognitiveServicesRegion = "westus";
}
Installieren des NuGet Speech-Dienstpakets
Die Beispielanwendung verwendet das NuGet-Paket Microsoft.CognitiveServices.Speech , um eine Verbindung mit dem Azure Speech-Dienst herzustellen. Installieren Sie dieses NuGet-Paket im freigegebenen Projekt und in jedem Plattformprojekt.
Erstellen einer IMicrophoneService-Schnittstelle
Jede Plattform erfordert die Berechtigung für den Zugriff auf das Mikrofon. Das Beispielprojekt stellt eine IMicrophoneService
Schnittstelle im freigegebenen Projekt bereit und verwendet den Xamarin.FormsDependencyService
, um Plattformimplementierungen der Schnittstelle abzurufen.
public interface IMicrophoneService
{
Task<bool> GetPermissionAsync();
void OnRequestPermissionResult(bool isGranted);
}
Erstellen des Seitenlayouts
Das Beispielprojekt definiert ein einfaches Seitenlayout in der Datei MainPage.xaml . Die wichtigsten Layoutelemente sind ein Button
, das den Transkriptionsprozess startet, ein Label
, das den transkribierten Text enthält, und ein ActivityIndicator
, das angezeigt wird, wenn die Transkription ausgeführt wird:
<ContentPage ...>
<StackLayout>
<Frame ...>
<ScrollView x:Name="scroll"
...>
<Label x:Name="transcribedText"
... />
</ScrollView>
</Frame>
<ActivityIndicator x:Name="transcribingIndicator"
IsRunning="False" />
<Button x:Name="transcribeButton"
...
Clicked="TranscribeClicked"/>
</StackLayout>
</ContentPage>
Implementieren des Speech-Diensts
Die CodeBehind-Datei MainPage.xaml.cs enthält die gesamte Logik zum Senden von Audiodaten und zum Empfangen von transkribiertem Text aus dem Azure Speech-Dienst.
Der MainPage
Konstruktor ruft eine instance der IMicrophoneService
Schnittstelle von abDependencyService
:
public partial class MainPage : ContentPage
{
SpeechRecognizer recognizer;
IMicrophoneService micService;
bool isTranscribing = false;
public MainPage()
{
InitializeComponent();
micService = DependencyService.Resolve<IMicrophoneService>();
}
// ...
}
Die TranscribeClicked
-Methode wird aufgerufen, wenn auf die transcribeButton
instance getippt wird:
async void TranscribeClicked(object sender, EventArgs e)
{
bool isMicEnabled = await micService.GetPermissionAsync();
// EARLY OUT: make sure mic is accessible
if (!isMicEnabled)
{
UpdateTranscription("Please grant access to the microphone!");
return;
}
// initialize speech recognizer
if (recognizer == null)
{
var config = SpeechConfig.FromSubscription(Constants.CognitiveServicesApiKey, Constants.CognitiveServicesRegion);
recognizer = new SpeechRecognizer(config);
recognizer.Recognized += (obj, args) =>
{
UpdateTranscription(args.Result.Text);
};
}
// if already transcribing, stop speech recognizer
if (isTranscribing)
{
try
{
await recognizer.StopContinuousRecognitionAsync();
}
catch(Exception ex)
{
UpdateTranscription(ex.Message);
}
isTranscribing = false;
}
// if not transcribing, start speech recognizer
else
{
Device.BeginInvokeOnMainThread(() =>
{
InsertDateTimeRecord();
});
try
{
await recognizer.StartContinuousRecognitionAsync();
}
catch(Exception ex)
{
UpdateTranscription(ex.Message);
}
isTranscribing = true;
}
UpdateDisplayState();
}
Die TranscribeClicked
-Methode führt folgende Schritte aus:
- Überprüft, ob die Anwendung Zugriff auf das Mikrofon hat, und wird frühzeitig beendet, falls dies nicht der Fall ist.
- Erstellt eine instance der
SpeechRecognizer
-Klasse, wenn sie noch nicht vorhanden ist. - Beendet die fortlaufende Transkription, wenn sie ausgeführt wird.
- Fügt einen Zeitstempel ein und startet die fortlaufende Transkription, wenn sie nicht ausgeführt wird.
- Benachrichtigt die Anwendung, ihre Darstellung basierend auf dem neuen Anwendungsstatus zu aktualisieren.
Die restlichen MainPage
Klassenmethoden sind Hilfsprogramme zum Anzeigen des Anwendungszustands:
void UpdateTranscription(string newText)
{
Device.BeginInvokeOnMainThread(() =>
{
if (!string.IsNullOrWhiteSpace(newText))
{
transcribedText.Text += $"{newText}\n";
}
});
}
void InsertDateTimeRecord()
{
var msg = $"=================\n{DateTime.Now.ToString()}\n=================";
UpdateTranscription(msg);
}
void UpdateDisplayState()
{
Device.BeginInvokeOnMainThread(() =>
{
if (isTranscribing)
{
transcribeButton.Text = "Stop";
transcribeButton.BackgroundColor = Color.Red;
transcribingIndicator.IsRunning = true;
}
else
{
transcribeButton.Text = "Transcribe";
transcribeButton.BackgroundColor = Color.Green;
transcribingIndicator.IsRunning = false;
}
});
}
Die UpdateTranscription
-Methode schreibt das bereitgestellte newText
string
in das Label
-Element mit dem Namen transcribedText
. Es erzwingt, dass dieses Update im UI-Thread erfolgt, sodass es aus einem beliebigen Kontext aufgerufen werden kann, ohne Ausnahmen zu verursachen. Der InsertDateTimeRecord
schreibt das aktuelle Datum und die aktuelle Uhrzeit in den transcribedText
instance, um den Beginn einer neuen Transkription zu markieren. Schließlich aktualisiert die UpdateDisplayState
Methode die Button
Elemente und ActivityIndicator
, um zu reflektieren, ob die Transkription ausgeführt wird oder nicht.
Erstellen von Plattformmikrofondiensten
Die Anwendung muss über Mikrofonzugriff verfügen, um Sprachdaten zu sammeln. Die IMicrophoneService
Schnittstelle muss auf jeder Plattform implementiert und registriert DependencyService
werden, damit die Anwendung funktioniert.
Android
Das Beispielprojekt definiert eine IMicrophoneService
Implementierung für Android namens AndroidMicrophoneService
:
[assembly: Dependency(typeof(AndroidMicrophoneService))]
namespace CognitiveSpeechService.Droid.Services
{
public class AndroidMicrophoneService : IMicrophoneService
{
public const int RecordAudioPermissionCode = 1;
private TaskCompletionSource<bool> tcsPermissions;
string[] permissions = new string[] { Manifest.Permission.RecordAudio };
public Task<bool> GetPermissionAsync()
{
tcsPermissions = new TaskCompletionSource<bool>();
if ((int)Build.VERSION.SdkInt < 23)
{
tcsPermissions.TrySetResult(true);
}
else
{
var currentActivity = MainActivity.Instance;
if (ActivityCompat.CheckSelfPermission(currentActivity, Manifest.Permission.RecordAudio) != (int)Permission.Granted)
{
RequestMicPermissions();
}
else
{
tcsPermissions.TrySetResult(true);
}
}
return tcsPermissions.Task;
}
public void OnRequestPermissionResult(bool isGranted)
{
tcsPermissions.TrySetResult(isGranted);
}
void RequestMicPermissions()
{
if (ActivityCompat.ShouldShowRequestPermissionRationale(MainActivity.Instance, Manifest.Permission.RecordAudio))
{
Snackbar.Make(MainActivity.Instance.FindViewById(Android.Resource.Id.Content),
"Microphone permissions are required for speech transcription!",
Snackbar.LengthIndefinite)
.SetAction("Ok", v =>
{
((Activity)MainActivity.Instance).RequestPermissions(permissions, RecordAudioPermissionCode);
})
.Show();
}
else
{
ActivityCompat.RequestPermissions((Activity)MainActivity.Instance, permissions, RecordAudioPermissionCode);
}
}
}
}
Der AndroidMicrophoneService
verfügt über die folgenden Features:
- Das
Dependency
-Attribut registriert die -Klasse bei .DependencyService
- Die
GetPermissionAsync
Methode überprüft, ob Berechtigungen basierend auf der Android SDK-Version erforderlich sind, und ruft aufRequestMicPermissions
, wenn die Berechtigung noch nicht erteilt wurde. - Die
RequestMicPermissions
-Methode verwendet dieSnackbar
-Klasse, um Berechtigungen vom Benutzer anzufordern, wenn eine Begründung erforderlich ist, andernfalls fordert sie direkt Audioaufzeichnungsberechtigungen an. - Die
OnRequestPermissionResult
-Methode wird mit einembool
Ergebnis aufgerufen, nachdem der Benutzer auf die Berechtigungsanforderung geantwortet hat.
Die MainActivity
Klasse wird angepasst, um die AndroidMicrophoneService
instance zu aktualisieren, wenn Berechtigungsanforderungen abgeschlossen sind:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
IMicrophoneService micService;
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
Instance = this;
// ...
micService = DependencyService.Resolve<IMicrophoneService>();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
// ...
switch(requestCode)
{
case AndroidMicrophoneService.RecordAudioPermissionCode:
if (grantResults[0] == Permission.Granted)
{
micService.OnRequestPermissionResult(true);
}
else
{
micService.OnRequestPermissionResult(false);
}
break;
}
}
}
Die MainActivity
-Klasse definiert einen statischen Verweis namens Instance
, der AndroidMicrophoneService
vom Objekt beim Anfordern von Berechtigungen benötigt wird. Es überschreibt die OnRequestPermissionsResult
-Methode zum Aktualisieren des AndroidMicrophoneService
Objekts, wenn die Berechtigungsanforderung vom Benutzer genehmigt oder verweigert wird.
Schließlich muss die Android-Anwendung die Berechtigung zum Aufzeichnen von Audio in der AndroidManifest.xml-Datei enthalten:
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
iOS
Das Beispielprojekt definiert eine IMicrophoneService
Implementierung für iOS namens iOSMicrophoneService
:
[assembly: Dependency(typeof(iOSMicrophoneService))]
namespace CognitiveSpeechService.iOS.Services
{
public class iOSMicrophoneService : IMicrophoneService
{
TaskCompletionSource<bool> tcsPermissions;
public Task<bool> GetPermissionAsync()
{
tcsPermissions = new TaskCompletionSource<bool>();
RequestMicPermission();
return tcsPermissions.Task;
}
public void OnRequestPermissionResult(bool isGranted)
{
tcsPermissions.TrySetResult(isGranted);
}
void RequestMicPermission()
{
var session = AVAudioSession.SharedInstance();
session.RequestRecordPermission((granted) =>
{
tcsPermissions.TrySetResult(granted);
});
}
}
}
Der iOSMicrophoneService
verfügt über die folgenden Features:
- Das
Dependency
-Attribut registriert die -Klasse bei .DependencyService
- Die
GetPermissionAsync
-Methode ruft aufRequestMicPermissions
, um Berechtigungen vom Gerätebenutzer anzufordern. - Die
RequestMicPermissions
Methode verwendet die freigegebeneAVAudioSession
instance, um Aufzeichnungsberechtigungen anzufordern. - Die
OnRequestPermissionResult
-Methode aktualisiert dieTaskCompletionSource
instance mit dem angegebenenbool
Wert.
Schließlich muss die iOS-App Info.plist eine Meldung enthalten, die dem Benutzer mitteilt, warum die App zugriff auf das Mikrofon anfordert. Bearbeiten Sie die Datei Info.plist, um die folgenden Tags in das <dict>
Element einzuschließen:
<plist>
<dict>
...
<key>NSMicrophoneUsageDescription</key>
<string>Voice transcription requires microphone access</string>
</dict>
</plist>
UWP
Das Beispielprojekt definiert eine IMicrophoneService
Implementierung für UWP namens UWPMicrophoneService
:
[assembly: Dependency(typeof(UWPMicrophoneService))]
namespace CognitiveSpeechService.UWP.Services
{
public class UWPMicrophoneService : IMicrophoneService
{
public async Task<bool> GetPermissionAsync()
{
bool isMicAvailable = true;
try
{
var mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings();
settings.StreamingCaptureMode = StreamingCaptureMode.Audio;
await mediaCapture.InitializeAsync(settings);
}
catch(Exception ex)
{
isMicAvailable = false;
}
if(!isMicAvailable)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-microphone"));
}
return isMicAvailable;
}
public void OnRequestPermissionResult(bool isGranted)
{
// intentionally does nothing
}
}
}
Der UWPMicrophoneService
verfügt über die folgenden Features:
- Das
Dependency
-Attribut registriert die -Klasse bei .DependencyService
- Die
GetPermissionAsync
-Methode versucht, eineMediaCapture
instance zu initialisieren. Wenn dies fehlschlägt, wird eine Benutzeranforderung gestartet, um das Mikrofon zu aktivieren. - Die
OnRequestPermissionResult
Methode ist vorhanden, um die Schnittstelle zu erfüllen, ist aber für die UWP-Implementierung nicht erforderlich.
Schließlich muss das UWP Package.appxmanifest angeben, dass die Anwendung das Mikrofon verwendet. Doppelklicken Sie auf die Datei Package.appxmanifest, und wählen Sie auf der Registerkarte Funktionen in Visual Studio 2019 die Option Mikrofon aus:
Testen der Anwendung
Führen Sie die App aus, und klicken Sie auf die Schaltfläche Transkribieren . Die App sollte den Mikrofonzugriff anfordern und den Transkriptionsprozess starten. Die ActivityIndicator
wird animiert und zeigt an, dass die Transkription aktiv ist. Während Sie sprechen, streamt die App Audiodaten an die Azure Speech Services-Ressource, die mit transkribiertem Text antwortet. Der transkribierte Text wird im Label
-Element angezeigt, während er empfangen wird.
Hinweis
Android-Emulatoren können die Spracherkennungsdienstbibliotheken nicht laden und initialisieren. Tests auf einem physischen Gerät werden für die Android-Plattform empfohlen.