我们的应用程序正在使用SFSpeechRecognizer识别语音。它正在我们的末端运行,但有时会在客户端崩溃。我们在崩溃报告系统中收到以下错误:
Foundation.MonoTouchException: Objective-C exception thrown. Name: com.apple.coreaudio.avfaudio Reason: required condition is false: IsFormatSampleRateAndChannelCountValid(hwFormat)
...
AvAudioEngine.get_InputNode
MainViewController.ViewDidLoad
...
因此,我看到访问AvAudioEngine的InputNode属性时,ViewDidLoad方法发生崩溃。这是ViewDidLoad中的代码:
public override void ViewDidLoad()
{
...
speechRecognizer = new SFSpeechRecognizer(new NSLocale("en-US"));
audioEngine = new AVAudioEngine();
//simply access the engine's input node immediately after
instantiation so that the engine is configured for audio input TO FIX
IsFormatSampleRateAndChannelCountValid(format) crash
//https://stackoverflow.com/questions/47903563/avaudioengine-inputnodes-
format-changes-when-playing-an-avaudioplayernode
var input = audioEngine.InputNode;
...
}
这里还有开始/停止录制的方法:
Timer speechTimer;
private async void startDictating()
{
try
{
stopRecognizer = false;
recognitionTask?.Cancel();
recognitionTask = null;
await Task.Delay(1000);//https://github.com/wenkesj/react-
native-voice/issues/50
//==== Make volume louder =====//
var audioSession = AVAudioSession.SharedInstance();
error =
audioSession.SetCategory(AVAudioSessionCategory.PlayAndRecord);
audioSession.SetMode(AVAudioSession.ModeDefault, out error);
error = audioSession.SetActive(true,
AVAudioSessionSetActiveOptions.NotifyOthersOnDeactivation);
audioSession.OverrideOutputAudioPort(AVAudioSessionPortOverride.Speaker,
out error);
recognitionRequest = new SFSpeechAudioBufferRecognitionRequest
{
ShouldReportPartialResults = true
};
var inputNode = audioEngine.InputNode;
if (inputNode == null)
{
StaticHolder.ReportCrash("startDictating: ", new
NullReferenceException("Audio engine has no input node"));
return;
}
if (speechRecognizer != null)
recognitionTask =
speechRecognizer.GetRecognitionTask(recognitionRequest,
(result, err) => InvokeOnMainThread(() =>
{
var isFinal = false;
if (result != null)
{
isFinal = result.Final;
voiceResult = result.BestTranscription.FormattedString;
lblVoiceRecogResult.Text = voiceResult;
if (PreferenceClass.VoiceInstantSearch)
{
if (!stopRecognizer)
{
if (speechTimer != null)
{
speechTimer.Stop();
speechTimer.Start();
}
if (speechTimer == null)
{
speechTimer = new Timer();
speechTimer.Interval = 3000;
speechTimer.Elapsed += (s, e) =>
{
((Timer)s).Stop();
InvokeOnMainThread(() =>
{
SoundEngine.Instance.PlaySound(AudioFilesType.Multiple);
stopDictating();
btnRecordDone_Clicked(null);
});
return;
};
speechTimer.Start();
}
}
}
}
//if (err != null || isFinal)
//{
// if (PreferenceClass.VoiceInstantSearch)
// {
// stopDictating();
// HandleSpeechToTextResult();
// }
//}
}));
inputNode.RemoveTapOnBus(0);
//https://stackoverflow.com/questions/41438219/terminating-app-due-to-
uncaught-app-crashes-while-using-speech-kit-ios
/*
var recordingFormat = new AVAudioFormat(sampleRate: 44100,
channels: 1);
https://stackoverflow.com/questions/41805381/avaudioengine-
inputnode-installtap-crash-when-restarting-recording
But it generated a crash again - 'required condition is false:
format.sampleRate == hwFormat.sampleRate'
So used GetBusOutPutFormat
*/
var recordingFormat = inputNode.GetBusOutputFormat(0);
inputNode.InstallTapOnBus(
bus: 0,
bufferSize: 1024,
format: recordingFormat,
tapBlock: (buffer, when) =>
recognitionRequest?.Append(buffer));
audioEngine.Prepare();
audioEngine.StartAndReturnError(out error);
}
catch (Exception ex)
{
StaticHolder.ReportCrash("try to get voice record task
exception:", ex);
}
}
private void stopDictating()
{
try
{
stopRecognizer = true;
audioEngine.Stop();
audioEngine.InputNode.RemoveTapOnBus(0);
recognitionRequest?.EndAudio();
recognitionTask = null;
recognitionRequest = null;
if (voiceTapNotification != null) NSNotificationCenter.DefaultCenter.RemoveObserver(voiceTapNotification);
if (searchTapNotification != null) NSNotificationCenter.DefaultCenter.RemoveObserver(searchTapNotification);
viewRecording.Hidden = true;
}
catch (Exception ex)
{
StaticHolder.ReportCrash("try to stop voice record exception:", ex);
}
}
请确保您已连接输入麦克风。您可能在未连接麦克风的Mac mini中运行您的应用程序。如果它是具有输入麦克风的iPhone或iPad或Mac,则不会遇到此问题连接。