Spracherkennung mit Azure Speech Service

Beispiel herunterladen Das Beispiel herunterladen

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:

Screenshots der 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:

  1. Melden Sie sich bei Ihrem Azure-Portal an.
  2. Erstellen Sie eine Ressource mit mehreren oder nur einem Dienst.
  3. Rufen Sie den API-Schlüssel und die Regionsinformationen für Ihre Ressource ab.
  4. 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:

  1. Überprüft, ob die Anwendung Zugriff auf das Mikrofon hat, und wird frühzeitig beendet, falls dies nicht der Fall ist.
  2. Erstellt eine instance der SpeechRecognizer -Klasse, wenn sie noch nicht vorhanden ist.
  3. Beendet die fortlaufende Transkription, wenn sie ausgeführt wird.
  4. Fügt einen Zeitstempel ein und startet die fortlaufende Transkription, wenn sie nicht ausgeführt wird.
  5. 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 newTextstring 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:

  1. Das Dependency -Attribut registriert die -Klasse bei .DependencyService
  2. Die GetPermissionAsync Methode überprüft, ob Berechtigungen basierend auf der Android SDK-Version erforderlich sind, und ruft auf RequestMicPermissions , wenn die Berechtigung noch nicht erteilt wurde.
  3. Die RequestMicPermissions -Methode verwendet die Snackbar -Klasse, um Berechtigungen vom Benutzer anzufordern, wenn eine Begründung erforderlich ist, andernfalls fordert sie direkt Audioaufzeichnungsberechtigungen an.
  4. Die OnRequestPermissionResult -Methode wird mit einem bool 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:

  1. Das Dependency -Attribut registriert die -Klasse bei .DependencyService
  2. Die GetPermissionAsync -Methode ruft auf RequestMicPermissions , um Berechtigungen vom Gerätebenutzer anzufordern.
  3. Die RequestMicPermissions Methode verwendet die freigegebene AVAudioSession instance, um Aufzeichnungsberechtigungen anzufordern.
  4. Die OnRequestPermissionResult -Methode aktualisiert die TaskCompletionSource instance mit dem angegebenen bool 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:

  1. Das Dependency -Attribut registriert die -Klasse bei .DependencyService
  2. Die GetPermissionAsync -Methode versucht, eine MediaCapture instance zu initialisieren. Wenn dies fehlschlägt, wird eine Benutzeranforderung gestartet, um das Mikrofon zu aktivieren.
  3. 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:

Screenshot des Manifests in Visual Studio 2019

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.