Spracherkennung mit Azure Speech Service
Azure Speech Service ist eine cloudbasierte API, die die folgenden Funktionen bietet:
- Sprach-zu-Text transkribiert Audiodateien oder Datenströme in Text.
- Text-zu-Sprache wandelt Eingabetext in eine synthetisierte Sprache des Menschen um.
- Die Sprachübersetzung ermöglicht die Echtzeitübersetzung, multisprachige Übersetzung sowohl für Sprache zu Text als auch für Sprache zu Sprache.
- Sprachassistenten können benutzerähnliche Unterhaltungsschnittstellen für Anwendungen erstellen.
In diesem Artikel wird erläutert, wie Sprach-zu-Text in der Beispielanwendung Xamarin.Forms mithilfe des Azure-Sprachdiensts 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 Multi-Service-Ressource erstellt werden. Die Schritte zum Erstellen einer Speech Service-Ressource lauten wie folgt:
- Melden Sie sich bei Ihrem Azure-Portal an.
- Erstellen Sie eine Mehrdienst- oder Einzeldienstressource.
- Rufen Sie den API-Schlüssel und die Regionsinformationen für Ihre Ressource ab.
- Aktualisieren Sie das Beispiel Constants.cs Datei.
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 Einzeldienstressource auf der kostenlosen Ebene erstellt werden, um den Dienst auszuprobieren.
Konfigurieren Ihrer App mit dem Spracherkennungsdienst
Nach dem Erstellen einer Cognitive Services-Ressource kann die Constants.cs Datei mit dem Region- und 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 Service-Pakets
Die Beispielanwendung verwendet das Microsoft.CognitiveServices.Speech NuGet-Paket, um eine Verbindung mit dem Azure Speech Service herzustellen. Installieren Sie dieses NuGet-Paket im freigegebenen Projekt und 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 die Xamarin.FormsDependencyService
Plattformimplementierungen der Schnittstelle.
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
Element, das den Transkriptionsprozess startet, einen Label
, der den transkribierten Text enthält, und eine ActivityIndicator
, die angezeigt werden soll, wann 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 Sprachdiensts
Die MainPage.xaml.cs CodeBehind-Datei enthält alle Logik zum Senden von Audio und Empfangen von transkribiertem Text vom Azure Speech Service.
Der MainPage
Konstruktor ruft eine Instanz der IMicrophoneService
Schnittstelle aus dem DependencyService
:
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
Instanz 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 frühzeitig auf das Mikrofon zugreifen kann und beendet, wenn dies nicht der Fall ist.
- Erstellt eine Instanz 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 eine fortlaufende Transkription, wenn sie nicht ausgeführt wird.
- Benachrichtigt die Anwendung, ihre Darstellung basierend auf dem neuen Anwendungszustand 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
Element mit dem Label
Namen transcribedText
. Sie erzwingt diese Aktualisierung im UI-Thread, sodass sie aus einem beliebigen Kontext aufgerufen werden kann, ohne dass Ausnahmen auftreten. Das InsertDateTimeRecord
aktuelle Datum und die aktuelle Uhrzeit werden in die transcribedText
Instanz geschrieben, um den Beginn einer neuen Transkription zu markieren. Schließlich aktualisiert die UpdateDisplayState
Methode die Button
elemente und ActivityIndicator
gibt an, ob die Transkription ausgeführt wird.
Erstellen von Plattformmikrofondiensten
Die Anwendung muss über Mikrofonzugriff verfügen, um Sprachdaten zu sammeln. Die IMicrophoneService
Schnittstelle muss auf jeder DependencyService
Plattform implementiert und registriert 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);
}
}
}
}
Die AndroidMicrophoneService
folgenden Features sind verfügbar:
- Das
Dependency
Attribut registriert die Klasse mit derDependencyService
. - Die
GetPermissionAsync
Methode überprüft, ob Berechtigungen basierend auf der Android SDK-Version erforderlich sind, und AufrufeRequestMicPermissions
, wenn noch keine Berechtigung erteilt wurde. - Die
RequestMicPermissions
Methode verwendet dieSnackbar
Klasse, um Berechtigungen vom Benutzer anzufordern, wenn eine Begründung erforderlich ist, andernfalls werden direkt Audioaufzeichnungsberechtigungen angefordert. - Die
OnRequestPermissionResult
Methode wird mit einembool
Ergebnis aufgerufen, nachdem der Benutzer auf die Berechtigungsanforderung geantwortet hat.
Die MainActivity
Klasse wird so angepasst, dass die AndroidMicrophoneService
Instanz aktualisiert wird, 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, Instance
der AndroidMicrophoneService
beim Anfordern von Berechtigungen vom Objekt benötigt wird. Sie setzt die OnRequestPermissionsResult
Methode außer Kraft, um das AndroidMicrophoneService
Objekt zu aktualisieren, 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);
});
}
}
}
Die iOSMicrophoneService
folgenden Features sind verfügbar:
- Das
Dependency
Attribut registriert die Klasse mit derDependencyService
. - Die
GetPermissionAsync
Methode ruft aufRequestMicPermissions
, um Berechtigungen vom Gerätebenutzer anzufordern. - Die
RequestMicPermissions
Methode verwendet die freigegebeneAVAudioSession
Instanz, um Aufzeichnungsberechtigungen anzufordern. - Die
OnRequestPermissionResult
Methode aktualisiert dieTaskCompletionSource
Instanz mit dem bereitgestelltenbool
Wert.
Schließlich muss die iOS-App Info.plist eine Meldung enthalten, die dem Benutzer angibt, 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
}
}
}
Die UWPMicrophoneService
folgenden Features sind verfügbar:
- Das
Dependency
Attribut registriert die Klasse mit derDependencyService
. - Die
GetPermissionAsync
Methode versucht, eineMediaCapture
Instanz zu initialisieren. Wenn dies fehlschlägt, wird eine Benutzeranforderung zum Aktivieren des Mikrofons gestartet. - 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 "Transcribe ". Die App sollte den Mikrofonzugriff anfordern und den Transkriptionsprozess starten. Die ActivityIndicator
Animation 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 beim Empfang im Label
Element angezeigt.
Hinweis
Android-Emulatoren können die Sprachdienstbibliotheken nicht laden und initialisieren. Tests auf einem physischen Gerät werden für die Android-Plattform empfohlen.