Распознавание речи с помощью служб речи Azure

Служба "Речь Azure" — это облачный API, который предлагает следующие функции:

  • Преобразование аудиофайлов или потоков в текст речи в текст.
  • Текст в речь преобразует входной текст в синтезированную речь человека.
  • Перевод речи обеспечивает перевод речи в режиме реального времени, многоязычный перевод для преобразования речи в текст и речь.
  • Помощник голосовых помощник могут создавать человеческую беседу для приложений.

В этой статье объясняется, как речь в тексте реализована в примере Xamarin.Forms приложения с помощью службы "Речь Azure". На следующих снимках экрана показан пример приложения на iOS и Android:

Снимок экрана примера приложения в iOS и Android

Создание ресурса службы "Речь Azure"

Служба "Речь Azure" является частью Azure Cognitive Services, которая предоставляет облачные API для таких задач, как распознавание изображений, распознавание речи и перевод, а также поиск Bing. Дополнительные сведения см. в статье "Что такое Azure Cognitive Services?".

Пример проекта требует создания ресурса Azure Cognitive Services в портал Azure. Ресурс Cognitive Services можно создать для одной службы, например службы "Речь" или в качестве ресурса с несколькими службами. Ниже приведены действия по созданию ресурса службы распознавания речи.

  1. Войдите в портал Azure.
  2. Создайте ресурс с несколькими службами или одиночными службами.
  3. Получите сведения о ключе API и регионе для ресурса.
  4. Обновите пример файла Constants.cs .

Пошаговое руководство по созданию ресурса см. в разделе "Создание ресурса Cognitive Services".

Примечание.

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начать работу. После получения учетной записи можно создать ресурс с одним обслуживанием на бесплатном уровне, чтобы попробовать службу.

Настройка приложения с помощью службы "Речь"

После создания ресурса Cognitive Services файл Constants.cs можно обновить с помощью региона и ключа API из ресурса Azure:

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

Установка пакета службы "Речь NuGet"

Пример приложения использует пакет NuGet Microsoft.CognitiveServices.Speech для подключения к службе "Речь Azure". Установите этот пакет NuGet в общем проекте и каждом проекте платформы.

Создание интерфейса IMicrophoneService

Для каждой платформы требуется разрешение на доступ к микрофону. Пример проекта предоставляет IMicrophoneService интерфейс в общем проекте и использует Xamarin.FormsDependencyService для получения реализаций платформы интерфейса.

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

Создание макета страницы

Пример проекта определяет базовый макет страницы в файле MainPage.xaml . Элементы макета ключей — это Button процесс транскрибирования, Label содержащий транскрибируемый текст, а ActivityIndicator также отображаемое при выполнении транскрибирования:

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

Реализация службы "Речь"

Файл кода MainPage.xaml.cs содержит всю логику для отправки звука и получения транскрибированного текста из службы распознавания речи Azure.

Конструктор MainPage получает экземпляр IMicrophoneService интерфейса из DependencyService:

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

    public MainPage()
    {
        InitializeComponent();

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

    // ...
}

Метод TranscribeClicked вызывается при нажатии экземпляра transcribeButton :

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

Метод TranscribeClicked выполняет следующие действия:

  1. Проверяет, имеет ли приложение доступ к микрофону и завершает работу рано, если это не так.
  2. Создает экземпляр класса, SpeechRecognizer если он еще не существует.
  3. Останавливает непрерывное транскрибирование, если оно выполняется.
  4. Вставляет метку времени и запускает непрерывную транскрибирование, если она не выполняется.
  5. Уведомляет приложение об обновлении внешнего вида на основе нового состояния приложения.

Остальные MainPage методы класса являются вспомогательными средствами для отображения состояния приложения:

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

Метод UpdateTranscription записывает предоставленный LabelnewTextstring элемент с именем.transcribedText Это заставляет это обновление выполняться в потоке пользовательского интерфейса, чтобы его можно было вызывать из любого контекста, не вызывая исключений. Записывает InsertDateTimeRecord текущую дату и время transcribedText в экземпляр, чтобы пометить начало нового транскрибирования. Наконец, UpdateDisplayState метод обновляет Button и ActivityIndicator элементы, чтобы отразить, выполняется ли транскрибирование.

Создание служб микрофона платформы

Приложение должно иметь доступ к микрофону для сбора речевых данных. Интерфейс IMicrophoneService должен быть реализован и зарегистрирован на каждой DependencyService платформе для работы приложения.

Android

Пример проекта определяет реализацию IMicrophoneService для Android с именем 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);
            }
        }
    }
}

У AndroidMicrophoneService него есть следующие функции:

  1. Атрибут Dependency регистрирует класс с DependencyServiceпомощью .
  2. Метод GetPermissionAsync проверка, если необходимы разрешения на основе версии пакета SDK для Android, и вызываетRequestMicPermissions, если разрешение еще не предоставлено.
  3. Метод RequestMicPermissions использует Snackbar класс для запроса разрешений от пользователя, если требуется обоснование, в противном случае он напрямую запрашивает разрешения записи звука.
  4. Метод OnRequestPermissionResult вызывается с результатом bool после того, как пользователь ответил на запрос разрешений.

Класс MainActivity настраивается для обновления экземпляра AndroidMicrophoneService при завершении запросов разрешений:

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

Класс MainActivity определяет статическую ссылку Instance, которая требуется AndroidMicrophoneService объектом при запросе разрешений. Он переопределяет OnRequestPermissionsResult метод для обновления AndroidMicrophoneService объекта, когда запрос разрешений утвержден или отклонен пользователем.

Наконец, приложение Android должно включать разрешение на запись звука в файл AndroidManifest.xml :

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

iOS

Пример проекта определяет реализацию IMicrophoneService для iOS с именем 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);
            });
        }
    }
}

У iOSMicrophoneService него есть следующие функции:

  1. Атрибут Dependency регистрирует класс с DependencyServiceпомощью .
  2. Метод GetPermissionAsync вызывает RequestMicPermissions запрос разрешений от пользователя устройства.
  3. Метод RequestMicPermissions использует общий AVAudioSession экземпляр для запроса разрешений записи.
  4. Метод OnRequestPermissionResult обновляет TaskCompletionSource экземпляр указанным значением bool .

Наконец, приложение iOS Info.plist должно содержать сообщение, которое сообщает пользователю, почему приложение запрашивает доступ к микрофону. Измените файл Info.plist, чтобы включить в элемент следующие теги <dict> :

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

UWP

Пример проекта определяет реализацию IMicrophoneService для UWP с именем 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
        }
    }
}

У UWPMicrophoneService него есть следующие функции:

  1. Атрибут Dependency регистрирует класс с DependencyServiceпомощью .
  2. Метод GetPermissionAsync пытается инициализировать MediaCapture экземпляр. Если это не удается, он запускает запрос пользователя для включения микрофона.
  3. Метод OnRequestPermissionResult существует для удовлетворения интерфейса, но не требуется для реализации UWP.

Наконец, пакет UWP Package.appxmanifest должен указать, что приложение использует микрофон. Дважды щелкните файл Package.appxmanifest и выберите параметр микрофона на вкладке "Возможности " в Visual Studio 2019:

Снимок экрана манифеста в Visual Studio 2019

Тестирование приложения

Запустите приложение и нажмите кнопку Transcribe . Приложение должно запросить доступ к микрофону и начать процесс транскрибирования. Будет ActivityIndicator анимация, показывающая, что транскрибирование активно. Когда вы говорите, приложение будет передавать звуковые данные в ресурс Служб распознавания речи Azure, который будет отвечать на транскрибированные тексты. Транскрибированные текст будут отображаться в элементе Label по мере получения.

Примечание.

Эмуляторы Android не загружают и инициализируют библиотеки службы "Речь". Тестирование на физическом устройстве рекомендуется для платформы Android.