Unity - распознавание речи в текст в облаке Google, Unity зависает после успешного результата - PullRequest
0 голосов
/ 08 февраля 2019

Мой друг и я сейчас работаем над проектом VR в Unity, и мы пытаемся реализовать распознавание голоса как функцию.Мы используем Unity версии 2018.3.3f1.Идея состоит в том, что пользователь может сказать слово, и распознавание голоса увидит, правильно ли оно произнесено.Для этого мы решили использовать облачный сервис преобразования речи в текст, поскольку он поддерживает целевой язык (норвежский).Кроме того, приложение также является многопользовательским, поэтому мы пытаемся использовать потоковую версию облачной речи Google.Вот ссылка на их документацию: https://cloud.google.com/speech-to-text/docs/streaming-recognize

Мы создали плагин, который по сути выполняет распознавание речи для нас.Это модификация примера кода, приведенного в ссылке выше:

public Task<bool> StartSpeechRecognition()
    {
        return StreamingMicRecognizeAsync(20, "fantastisk");
    }

    static async Task<bool> StreamingMicRecognizeAsync(int inputTime, string inputWord)
    {
        bool speechSuccess = false;
        Stopwatch timer = new Stopwatch();


        Task delay = Task.Delay(TimeSpan.FromSeconds(1));

        if (NAudio.Wave.WaveIn.DeviceCount < 1)
        {
            //Console.WriteLine("No microphone!");
            return false;
        }

        var speech = SpeechClient.Create();
        var 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.Linear16,
                        SampleRateHertz = 16000,
                        LanguageCode = "nb",
                    },
                    InterimResults = true,
                }
            });




        // Compare speech with the input word, finish if they are the same and speechSuccess becomes true.
        Task compareSpeech = 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 (alternative.Transcript.Replace(" ", String.Empty).Equals(inputWord, StringComparison.InvariantCultureIgnoreCase))
                        {
                            speechSuccess = true;

                            return;
                        }

                    }
                }
            }
        });

        // Read from the microphone and stream to API.
        object writeLock = new object();
        bool writeMore = true;
        var waveIn = new NAudio.Wave.WaveInEvent();
        waveIn.DeviceNumber = 0;
        waveIn.WaveFormat = new NAudio.Wave.WaveFormat(16000, 1);
        waveIn.DataAvailable +=
            (object sender, NAudio.Wave.WaveInEventArgs args) =>
            {
                lock (writeLock)
                {
                    if (!writeMore) return;
                    streamingCall.WriteAsync(
                        new StreamingRecognizeRequest()
                        {
                            AudioContent = Google.Protobuf.ByteString
                                .CopyFrom(args.Buffer, 0, args.BytesRecorded)
                        }).Wait();
                }
            };

        waveIn.StartRecording();
        timer.Start();
        //Console.WriteLine("Speak now.");

        //Delay continues as long as a match has not been found between speech and inputword or time that has passed since recording is lower than inputTime.
        while (!speechSuccess && timer.Elapsed.TotalSeconds <= inputTime)
        {
            await delay;
        }

        // Stop recording and shut down.
        waveIn.StopRecording();
        timer.Stop();

        lock (writeLock) writeMore = false;

        await streamingCall.WriteCompleteAsync();
        await compareSpeech;


        //Console.WriteLine("Finished.");
        return speechSuccess;
    }

Мы создали небольшой проект в Unity, чтобы проверить, работает ли он с кубом GameObject, который имеет этот скрипт:

private CancellationTokenSource tokenSource;
VR_VoiceRecognition.VoiceRecognition voice = new VR_VoiceRecognition.VoiceRecognition();
IDisposable speech;

// Use this for initialization
void Start() {

    speech = Observable.FromCoroutine(WaitForSpeech).Subscribe();

}

// Update is called once per frame
void Update() {

}

IEnumerator WaitForSpeech()
{
    tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;

    Debug.Log("Starting up");

    Task<bool> t = Task.Run(() => voice.StartSpeechRecognition());

    while (!(t.IsCompleted || t.IsCanceled))
    {
        yield return null;
    }


    if (t.Status != TaskStatus.RanToCompletion)
    {

        yield break;
    }
    else
    {
        bool result = t.Result;
        UnityEngine.Debug.Log(t.Result);
        yield return result;
    }

}

void OnApplicationQuit()
{
    print("Closing application.");
    speech.Dispose();
}

Мы также используем плагин, рекомендованный нам поддержкой Unity, который, по их мнению, может иметь обходной путь, называемый UniRx (https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276).

На данный момент он работает нормально, когда вы играетеэто в редакторе в первый раз. Когда распознавание голоса возвращает ложь, тогда все в порядке (два случая, когда это происходит, если он не может найти микрофон или если пользователь не произносит конкретное слово). Однако, если этов случае успеха, он все равно возвращает значение true, но если вы выйдете из режима воспроизведения в редакторе и попытаетесь воспроизвести снова, Unity остановится. Служба поддержки Unity подозревает, что это может иметь отношение к файлам Google .dll или Google API. Мы не совсемуверен, что делать дальше, и мы надеемся, что кто-то может указать нам правильное направление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...