Reconocimiento de voz con el servicio de voz de Azure

Ejemplo de descarga Descarga del ejemplo

Azure Speech Service es una API basada en la nube que ofrece la siguiente funcionalidad:

  • La voz a texto transcribe archivos de audio o secuencias en texto.
  • Texto a voz convierte el texto de entrada en voz sintetizada de tipo humano.
  • La traducción de voz permite la traducción en tiempo real en varios idiomas para la conversión de voz a texto y de voz a voz.
  • Los asistentes de voz pueden crear interfaces de conversación similares a las humanas para las aplicaciones.

En este artículo se explica cómo se implementa la voz a texto en la aplicación de Xamarin.Forms ejemplo mediante el servicio Voz de Azure. En las capturas de pantalla siguientes se muestra la aplicación de ejemplo en iOS y Android:

Capturas de pantalla de la aplicación deejemplo en iOS y Android

Creación de un recurso de Azure Speech Service

Azure Speech Service forma parte de Azure Cognitive Services, que proporciona API basadas en la nube para tareas como el reconocimiento de imágenes, el reconocimiento de voz y la traducción, y Bing búsqueda. Para obtener más información, vea ¿Qué Azure Cognitive Services?.

El proyecto de ejemplo requiere que se cree Azure Cognitive Services recurso en el Azure Portal. Se Cognitive Services un recurso de servicio único para un único servicio, como el servicio voz, o como un recurso de varios servicios. Los pasos para crear un recurso del servicio voz son los siguientes:

  1. Inicie sesión en el Azure Portal.
  2. Cree un recurso de varios servicios o de un solo servicio.
  3. Obtenga la información de la clave de API y la región del recurso.
  4. Actualice el archivo Constants.cs de ejemplo.

Para obtener una guía paso a paso sobre cómo crear un recurso, consulte Creación de un Cognitive Services recurso.

Nota:

Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar. Una vez que tenga una cuenta, se puede crear un recurso de un solo servicio en el nivel gratis para probar el servicio.

Configuración de la aplicación con el servicio Voz

Después de crear Cognitive Services recurso, el archivo Constants.cs se puede actualizar con la región y la clave de API del recurso de Azure:

public static class Constants
{
    public static string CognitiveServicesApiKey = "YOUR_KEY_GOES_HERE";
    public static string CognitiveServicesRegion = "westus";
}

Instalación NuGet del servicio Voz

La aplicación de ejemplo usa el paquete de NuGet Microsoft.CognitiveServices.Speech para conectarse al servicio Voz de Azure. Instale este NuGet en el proyecto compartido y en cada proyecto de plataforma.

Creación de una interfaz IMicrophoneService

Cada plataforma requiere permiso para acceder al micrófono. El proyecto de ejemplo proporciona una IMicrophoneService interfaz en el proyecto compartido y usa para obtener Xamarin.FormsDependencyService implementaciones de plataforma de la interfaz.

public interface IMicrophoneService
{
    Task<bool> GetPermissionAsync();
    void OnRequestPermissionResult(bool isGranted);
}

Creación del diseño de página

El proyecto de ejemplo define un diseño de página básico en el archivo MainPage.xaml. Los elementos de diseño clave son un que inicia el proceso de transcripción, un para contener el texto transcrito y un para mostrar cuándo está en ButtonLabel curso la ActivityIndicator transcripción:

<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>

Implementación del servicio Voz

El archivo de código subyacente MainPage.xaml.cs contiene toda la lógica para enviar audio y recibir texto transcrito del servicio Voz de Azure.

El MainPage constructor obtiene una instancia de la interfaz de IMicrophoneServiceDependencyService :

public partial class MainPage : ContentPage
{
    SpeechRecognizer recognizer;
    IMicrophoneService micService;
    bool isTranscribing = false;

    public MainPage()
    {
        InitializeComponent();

        micService = DependencyService.Resolve<IMicrophoneService>();
    }

    // ...
}

Se TranscribeClicked llama al método cuando se pulsa la transcribeButton instancia:

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();
}

El método TranscribeClicked hace lo siguiente:

  1. Comprueba si la aplicación tiene acceso al micrófono y sale pronto si no lo hace.
  2. Crea una instancia de SpeechRecognizer clase si aún no existe.
  3. Detiene la transcripción continua si está en curso.
  4. Inserta una marca de tiempo e inicia la transcripción continua si no está en curso.
  5. Notifica a la aplicación que actualice su apariencia en función del nuevo estado de la aplicación.

El resto de los MainPage métodos de clase son asistentes para mostrar el estado de la aplicación:

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;
        }
    });
}

El UpdateTranscription método escribe el proporcionado en el elemento denominado newTextstringLabeltranscribedText . Obliga a que esta actualización se produce en el subproceso de interfaz de usuario, por lo que se puede llamar desde cualquier contexto sin provocar excepciones. escribe InsertDateTimeRecord la fecha y hora actuales en la instancia de para marcar el inicio de una nueva transcribedText transcripción. Por último, UpdateDisplayState el método actualiza los elementos y para reflejar si la ButtonActivityIndicator transcripción está en curso o no.

Creación de servicios de micrófono de plataforma

La aplicación debe tener acceso al micrófono para recopilar datos de voz. La interfaz debe implementarse y registrarse con en cada IMicrophoneService plataforma para que la aplicación DependencyService funcione.

Android

El proyecto de ejemplo define una IMicrophoneService implementación para Android denominada 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);
            }
        }
    }
}

tiene AndroidMicrophoneService las siguientes características:

  1. El Dependency atributo registra la clase con DependencyService .
  2. El método comprueba si se requieren permisos en función de la versión Android SDK y llama a si aún no se GetPermissionAsyncRequestMicPermissions ha concedido el permiso.
  3. El método usa la clase para solicitar permisos al usuario si se requiere una justificación; de lo contrario, solicita directamente permisos de RequestMicPermissionsSnackbar grabación de audio.
  4. Se OnRequestPermissionResult llama al método con un resultado una vez que el usuario ha respondido a la solicitud de bool permisos.

La MainActivity clase se personaliza para actualizar la instancia cuando se AndroidMicrophoneService completan las solicitudes de permisos:

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;
        }
    }
}

La clase define una referencia estática denominada , que es MainActivity necesaria para el objeto al solicitar InstanceAndroidMicrophoneService permisos. Invalida el método para actualizar el objeto cuando el usuario aprueba o deniega la OnRequestPermissionsResultAndroidMicrophoneService solicitud de permisos.

Por último, la aplicación Android debe incluir el permiso para grabar audio en el AndroidManifest.xml archivo:

<manifest ...>
    ...
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>

iOS

El proyecto de ejemplo define IMicrophoneService una implementación para iOS denominada 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);
            });
        }
    }
}

tiene iOSMicrophoneService las siguientes características:

  1. El Dependency atributo registra la clase con DependencyService .
  2. El GetPermissionAsync método llama a para solicitar permisos al usuario del RequestMicPermissions dispositivo.
  3. El RequestMicPermissions método usa la instancia compartida para solicitar permisos de AVAudioSession grabación.
  4. El OnRequestPermissionResult método actualiza la instancia con el valor TaskCompletionSourcebool proporcionado.

Por último, la aplicación de iOS Info.plist debe incluir un mensaje que indique al usuario por qué la aplicación solicita acceso al micrófono. Edite el archivo Info.plist para incluir las siguientes etiquetas en el <dict> elemento :

<plist>
    <dict>
        ...
        <key>NSMicrophoneUsageDescription</key>
        <string>Voice transcription requires microphone access</string>
    </dict>
</plist>

UWP

El proyecto de ejemplo define una IMicrophoneService implementación para UWP denominada 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
        }
    }
}

tiene UWPMicrophoneService las siguientes características:

  1. El Dependency atributo registra la clase con DependencyService .
  2. El GetPermissionAsync método intenta inicializar una instancia de MediaCapture . Si se produce un error, inicia una solicitud de usuario para habilitar el micrófono.
  3. El OnRequestPermissionResult método existe para satisfacer la interfaz, pero no es necesario para la implementación de UWP.

Por último, UWP Package.appxmanifest debe especificar que la aplicación usa el micrófono. Haga doble clic en el archivo Package.appxmanifest y seleccione la opción Micrófono en la pestaña Funcionalidades Visual Studio 2019:

Captura de pantalladel manifiesto en Visual Studio 2019

Prueba de la aplicación

Ejecute la aplicación y haga clic en el botón Transcribir. La aplicación debe solicitar acceso al micrófono e iniciar el proceso de transcripción. se ActivityIndicator animará, mostrando que la transcripción está activa. Mientras habla, la aplicación transmitirá datos de audio al recurso de Servicios de voz de Azure, que responderá con texto transcrito. El texto transcrito aparecerá en Label el elemento a medida que se reciba.

Nota:

Los emuladores de Android no pueden cargar e inicializar las bibliotecas del servicio voz. Se recomienda realizar pruebas en un dispositivo físico para la plataforma Android.