Распознавание речи Google с помощью Xamarin Android - PullRequest
0 голосов
/ 08 декабря 2018

Некоторое время назад я пытался заставить Google Speech Recognition работать в Xamarin (часть Android).К сожалению, пока у меня нет успеха.Примеры / фрагменты, которые я использую: Plugin.AudioRecorder , GrpcXamarinSamples и Пример распознавания Google .

Цель этого приложения - получитьпотоковый голос с микрофона на платформе Android, попросить Google обработать звук и вернуть строку для дальнейшего использования в проекте.Пример проекта работает, но как только я пытаюсь перенести его в свой собственный проект и заменить NAudio.WaveIn на код Plugin.AudioRecorder, он не работает должным образом.Я пробовал несколько способов сделать это, но ни один из них не работает, и мы всегда получаем какую-то ошибку.(прямо сейчас исключение NullPointerException, которое я не могу разместить)

В настоящее время я застрял в следующем классе, где Listen () - это метод, который вызывается, когда мы хотим получить единственное прослушивание-распознавание-возвратпетля.Когда я вызываю эту функцию, в консоли я получаю следующие результаты:

using System;
using System.Threading.Tasks;
using System.Reflection;
using System.IO;
using System.Threading;

using Android.App;

using Google.Apis.Auth.OAuth2;
using Google.Cloud.Speech.V1;
using Grpc.Core;
using Grpc.Auth;
using Xamarin.Forms;
using MyApp.Droid;
using Plugin.AudioRecorder;

[assembly: Dependency(typeof(GoogleSpeechRecognition))]
namespace MyApp.Droid
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    class GoogleSpeechRecognition : ISpeechRecognition
    {
        Editor logEditor;
        AudioRecorderService recorder;

        Assembly assembly = typeof(MainActivity).GetTypeInfo().Assembly;
        Stream authStream = global::Android.App.Application.Context.Assets.Open("authenticateGoogle.json");
        string resultString = null;
        GoogleCredential credential;
        Channel channel;
        SpeechClient speech;
        SpeechClient.StreamingRecognizeStream streamingCall;


        private void Log(string logText)
        {
            //logEditor.Text += String.Format("{0}: {1}\n", DateTime.Now.ToString("HH:mm:ss.fff"), logText);
            Console.WriteLine(String.Format("{0}: {1}\n", DateTime.Now.ToString("HH:mm:ss.fff"), logText));
        }

        public async Task<string> Listen()
        {
            PrepareSpeechRecognition();
            WriteInitialPackage();
            string result = await StreamingMicRecognizeAsync();
            return result;
        }

        public void PrepareSpeechRecognition(Editor editor = null)
        {
            if (editor != null)
            {
                logEditor = editor;
            }
            recorder = new AudioRecorderService
            {
                StopRecordingOnSilence = true, //will stop recording after max seconds of silence (defined below)
                AudioSilenceTimeout = TimeSpan.FromSeconds(0.5), //will stop recording after x seconds of silence, default is 2
                //SilenceThreshold = 1.0F, //indicates the threshold that determines silence. Between 0 and 1, default is .15
                StopRecordingAfterTimeout = true,  //stop recording after a max timeout (defined below)
                //TotalAudioTimeout = TimeSpan.FromSeconds(60) //audio will stop recording after x seconds, default is 30
            };

            // required to protect against a System.ArgumentNullException on Xamarin.Android during initialization of type
            // Microsoft.Extensions.PlatformAbstractions.ApplicationEnvironment in the dependency from Google.Api.Gax (see https://github.com/aspnet/PlatformAbstractions/blob/rel/1.1.0/src/Microsoft.Extensions.PlatformAbstractions/ApplicationEnvironment.cs).
            // The field initializer for "ApplicationBasePath" calls GetApplicationBasePath() which calls Path.GetFullPath(basePath)
            // where basePath is AppContext.BaseDirectory which returns null on Xamarin by default (see https://github.com/mono/mono/blob/mono-5.10.0.140/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs)
            AppDomain.CurrentDomain.SetData("APP_CONTEXT_BASE_DIRECTORY", Path.DirectorySeparatorChar.ToString());

            using (var reader = new StreamReader(authStream))
            {
                resultString = reader.ReadToEnd();
            }
            credential = GoogleCredential.FromJson(resultString);
            if (credential.IsCreateScopedRequired)
            {
                credential = credential.CreateScoped(new[] { "https://www.googleapis.com/auth/cloud-platform" });
            }

            channel = new Channel(SpeechClient.DefaultEndpoint.Host,
                credential.ToChannelCredentials());

            speech = SpeechClient.Create(channel, new SpeechSettings());

            streamingCall = speech.StreamingRecognize();
        }

        public async void WriteInitialPackage()
        {
            streamingCall = speech.StreamingRecognize();
            // Write the initial request with the config.
            await streamingCall.WriteAsync(
                new StreamingRecognizeRequest()
                {
                    StreamingConfig = new StreamingRecognitionConfig()
                    {
                        Config = new RecognitionConfig()
                        {
                            Encoding = RecognitionConfig.Types.AudioEncoding.Flac,
                            SampleRateHertz = 16000,
                            LanguageCode = "en",
                        },
                        InterimResults = true,
                        SingleUtterance = true,
                    }
                }
            );
        }

        public async Task<string> StreamingMicRecognizeAsync()
        {
            string callResult = "";

            // Print responses as they arrive.
            Task printResponses = Task.Run(async () =>
            {
                while (await streamingCall.ResponseStream.MoveNext(
                    default(CancellationToken)))
                {
                    foreach (var result in streamingCall.ResponseStream
                        .Current.Results)
                    {
                        foreach (var alternative in result.Alternatives)
                        {
                            if (result.IsFinal)
                            {
                                Console.WriteLine("FINAL: ");
                                Console.WriteLine(alternative.Transcript);
                                callResult = alternative.Transcript;
                            }
                            Console.WriteLine(alternative.Transcript);
                        }
                    }
                }
            });

            byte[] buffer = new byte[32 * 1024];
            var audioRecordTask = await recorder.StartRecording();
            int bytesRead = 0;
            Log("STARTED RECORDING");
            using (var _stream = recorder.GetAudioFileStream())
            {
                Log("Using");
                while (recorder.IsRecording)
                {
                    Log("Read bytes");
// [THIS IS WHERE IT ERRORS OUT]
                    try
                    {
                        bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length);
                    }
                    catch(Exception e)
                    {
                        Log("Exception: " + e.Message);
                    }
// [/THIS IS WHERE IT ERRORS OUT]
                    Log("Write");
                    streamingCall.WriteAsync(
                        new StreamingRecognizeRequest()
                        {
                            AudioContent = Google.Protobuf.ByteString.CopyFrom(buffer, 0, bytesRead)
                        }
                    ).Wait();
                    Log("Delay?");
                    //await Task.Delay(500);
                };
                Log("FINISHED RECORDING");
                await streamingCall.WriteCompleteAsync();
            }
            Log("STOP _STREAM");

            await streamingCall.WriteCompleteAsync();
            await printResponses;
            return callResult;
        }
    }
}

12-08 09: 45: 23.721 I / mono-stdout (19951): 09: 45: 23.605:ЗАПУСК ЗАПИСИ 12-08 09: 45: 23.728 I / mon-stdout (19951): 09: 45: 23.605: ЗАПУСК ЗАПИСИ

09: 45: 23.734: Использование 12-08 09: 45: 23.734 I /mono-stdout (19951): 09: 45: 23.734: использование 12-08 09: 45: 23.734 I / mon-stdout (19951): 09: 45: 23.738: чтение байтов

12-08 09:45: 23.738 I / mon-stdout (19951): 09: 45: 23.738: считанные байты 12-08 09: 45: 23.739 I / mon-stdout (19951): 12-08 09: 45: 23.795 I / хореограф (19951): Пропущено 43 кадра!Приложение может выполнять слишком много работы в своем основном потоке.Необработанное исключение:

System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта.

Извините за грязный код и все, это учебный проект, который имеет много итераций.
Аутентификация Google работает, мы проверили это с примером проекта.

Редактировать: По запросу полный журнал: https://pastebin.com/q3G62ByT

...