Задача
Мой проект состоит из настольного приложения, которое записывает аудио в режиме реального времени, для которого я намерен получать отзывы распознавания в реальном времени от API. С микрофоном реализация в режиме реального времени с использованием нового API речи для текста тривиальна, и мой сценарий отличается от сценария только в том смысле, что мои данные записываются в MemoryStream
объект.
Поддержка API
В этой статье объясняется, как реализовать API Recognizer
( link ) с пользовательскими аудиопотоками , что неизменно требует реализации абстрактного класса PullAudioInputStream
( ссылка ) для создания необходимого объекта AudioConfig
с использованием метода CreatePullStream
( ссылка ). Другими словами, для достижения того, что мне требуется, должен быть реализован интерфейс обратного вызова.
Попытка реализации
Поскольку мои данные записываются в MemoryStream (а библиотека, которую я использую, будет записывать только файлы или объекты Stream), в приведенном ниже коде я просто копирую буфер в реализованный класс ( небрежно, возможно? ) устранение расхождений в сигнатурах методов.
class AudioInputCallback : PullAudioInputStreamCallback
{
private readonly MemoryStream memoryStream;
public AudioInputCallback(MemoryStream stream)
{
this.memoryStream = stream;
}
public override int Read(byte[] dataBuffer, uint size)
{
return this.Read(dataBuffer, 0, dataBuffer.Length);
}
private int Read(byte[] buffer, int offset, int count)
{
return memoryStream.Read(buffer, offset, count);
}
public override void Close()
{
memoryStream.Close();
base.Close();
}
}
Реализация Recognizer
выглядит следующим образом:
private SpeechRecognizer CreateMicrosoftSpeechRecognizer(MemoryStream memoryStream)
{
var recognizerConfig = SpeechConfig.FromSubscription(SubscriptionKey, @"westus");
recognizerConfig.SpeechRecognitionLanguage =
_programInfo.CurrentSourceCulture.TwoLetterISOLanguageName;
// Constants are used as constructor params)
var format = AudioStreamFormat.GetWaveFormatPCM(
samplesPerSecond: SampleRate, bitsPerSample: BitsPerSample, channels: Channels);
// Implementation of PullAudioInputStreamCallback
var callback = new AudioInputCallback(memoryStream);
AudioConfig audioConfig = AudioConfig.FromStreamInput(callback, format);
//Actual recognizer is created with the required objects
SpeechRecognizer recognizer = new SpeechRecognizer(recognizerConfig, audioConfig);
// Event subscriptions. Most handlers are implemented for debugging purposes only.
// A log window outputs the feedback from the event handlers.
recognizer.Recognized += MsRecognizer_Recognized;
recognizer.Recognizing += MsRecognizer_Recognizing;
recognizer.Canceled += MsRecognizer_Canceled;
recognizer.SpeechStartDetected += MsRecognizer_SpeechStartDetected;
recognizer.SpeechEndDetected += MsRecognizer_SpeechEndDetected;
recognizer.SessionStopped += MsRecognizer_SessionStopped;
recognizer.SessionStarted += MsRecognizer_SessionStarted;
return recognizer;
}
Как данные становятся доступными для распознавателя (с помощью CSCore):
MemoryStream memoryStream = new MemoryStream(_finalSource.WaveFormat.BytesPerSecond / 2);
byte[] buffer = new byte[_finalSource.WaveFormat.BytesPerSecond / 2];
_soundInSource.DataAvailable += (s, e) =>
{
int read;
_programInfo.IsDataAvailable = true;
// Writes to MemoryStream as event fires
while ((read = _finalSource.Read(buffer, 0, buffer.Length)) > 0)
memoryStream.Write(buffer, 0, read);
};
// Creates MS recognizer from MemoryStream
_msRecognizer = CreateMicrosoftSpeechRecognizer(memoryStream);
//Initializes loopback capture instance
_soundIn.Start();
await Task.Delay(1000);
// Starts recognition
await _msRecognizer.StartContinuousRecognitionAsync();
Результат
Когда приложение запускается, я не получаю никаких исключений и никаких ответов от API, кроме SessionStarted
и SessionStopped
, как показано ниже в окне журнала моего приложения.
Я мог бы использовать предложения различных подходов к моей реализации, так как подозреваю, что есть некоторая проблема с синхронизацией при привязке записанного события DataAvailable
с фактической отправкой данных в API, что заставляет его преждевременно отбрасывать сеанс. Без подробного отзыва о том, почему мои запросы были неудачными, я могу только догадываться о причине.