public async Task Start(SpeechRecognitionOptions options) { SpeechRecognizer recognizer = null; try { Logger.LogInformation("Starting speech recognition"); var credentials = this.Credentials; var speechConfig = SpeechConfig.FromEndpoint(new Uri($"wss://{credentials.Region}.stt.speech.microsoft.com/speech/universal/v2"), credentials.SubscriptionKey); speechConfig.SetProfanity(ProfanityOption.Raw); if (options.Languages.Count > 1) { //enable continuous language detection when we have more than 1 language //this seems kind of buggy though, at times the speech recognition just simply doesn't work at all when this is enabled speechConfig.SetProperty(PropertyId.SpeechServiceConnection_ContinuousLanguageIdPriority, "Latency"); } var languageConfig = AutoDetectSourceLanguageConfig.FromLanguages(options.Languages.Select(lang => { //convert language selections if (lang.Length == 2) { //two-letter code. select some default five-letter code instead. if (lang == "en") { lang = "en-US"; } else { lang = lang + "-" + lang.ToUpperInvariant(); } } return(lang); }).ToArray()); recognizer = new SpeechRecognizer(speechConfig, languageConfig, AudioConfig); //set up the special phrases if any if (options.Phrases?.Count > 0) { var phrases = PhraseListGrammar.FromRecognizer(recognizer); foreach (var phrase in options.Phrases) { phrases.AddPhrase(phrase); } } //prepare events recognizer.Canceled += (sender, e) => { SpeechRecognizer = null; Dispose(Disposables); if (e.ErrorCode == CancellationErrorCode.Forbidden || e.ErrorCode == CancellationErrorCode.AuthenticationFailure) { //out of quota (or invalid key, try the next one anyway) int credentialsIndexCurrent = CredentialsIndex; if (NextCredentials()) { Logger.LogInformation($"Out of quota for credentials {credentialsIndexCurrent}. Restarting with {CredentialsIndex}"); Threading.Tasks.FireAndForget(() => Start(options)); return; } } if (e.Reason != CancellationReason.EndOfStream && e.Reason != CancellationReason.CancelledByUser) { Logger.LogWarning($"Recognition stopped. reason={e.Reason}, erroCode={e.ErrorCode}, details={e.ErrorDetails}"); } Stopped?.Invoke(this, new SpeechRecognitionStoppedEvent() { Message = $"{e.ErrorCode}: {e.ErrorDetails}" }); }; recognizer.Recognizing += (sender, e) => { OnSpeechEvent(e, false); }; recognizer.Recognized += (sender, e) => { OnSpeechEvent(e, true); }; recognizer.SpeechEndDetected += (sender, e) => { StreamAudioNoiseGate?.OnAudioStop(); }; //start recognizing await recognizer.StartContinuousRecognitionAsync(); //start our audio source if (!IsRunning && StreamAudioSource != null) { await StreamAudioSource.Start(); } } catch (Exception e) { Logger.LogError(e, "Could not start continuous recognition"); recognizer?.Dispose(); throw; } SpeechRecognizer = recognizer; IsRunning = true; Disposables.Add(recognizer); }