Распознавание с нестандартного микрофона

в 13:42, , рубрики: .net, микрофон, распознование речи, метки: ,

Некоторые сталкиваются с тем что необходимо распознать речь перевести её в текст и обработать. Проблема описывалась много раз как впрочем и пути её решения так что Google в помощь, но вот я столкнулся на собственном опыте с проблемой которая потребовала нетривиального решения, а именно как заставить распознавать речь с микрофона которые не установлен «по умолчанию». Если вы тоже столкнулись с подобной проблемой то эта статья именно для вас.

Итак что мы имеем — есть два различных движка для распознавания речи в Microsoft Windows (стандартный и Microsoft Speech SDK 11) причём сразу скажу что русский язык поддерживает пока только один из них, а именно Microsoft Speech SDK 11 с установленным русским языком. Если внимательно прочитать документацию по обоим движкам, то видно что в качестве устройства можно выбрать только DefaultInputDevice, но копнув глубже, а именно открыв сборку декомпилятором Telerik JustDecompile я убедился что все классы являются лишь обёрткой над СОМ объектами, а как раз в этих СОМ объектах нужная функция есть. Естественно что как и все программисты я ленивый и работать с СОМ не хотел, поэтому совмести два решения. Итак первое что нам необходима это найти Token нужного нам микрофона для этого существует следующая функция:

private SpeechLib.SpObjectToken FindMicByName(string name)
        {
            if (isot != null)
            {
                for (int i = 0; i < isot.Count; i++)
                {
                    sot = isot.Item(i);
                    string desc = sot.GetDescription(1033);
                    string id = sot.Id;
                    if (desc.Contains(name) != false)
                    {
                        break;
                    }
                }
                return sot;
            }
            else
                return null;
        }

После того как мы получим Token необходимо вызвать приватные методы у класса «движка» распознавания для этого используется следующая функция:

public void SetMicByName(string name, ref System.Speech.Recognition.SpeechRecognitionEngine sre)
        {
            if (isot != null)
            {
                sre.SetInputToDefaultAudioDevice();
                sot = FindMicByName(name);
                if (sot != null)
                {
                    FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);
                    object _sapiRecognizer = fi.GetValue(sre);
                    MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);
                    object[] parms = new object[] { sot, true };
                    mi.Invoke(_sapiRecognizer, parms);
                }
            }
        }

В конце я приведу полный текст вспомогательного класса, который используется в моей разработке, Вы можете использовать его полностью или частично или просто вставить необходимые фрагмента кода себе. Всё это проверенно на Windows 7,8,8.1 ,NET 4.0, 4.5, но думаю что и с другими версиями будет работать также.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
 
namespace RMI.SmartHouse.Service
{
    /// <summary>
    /// Позволяет осуществить выбор микрофонов.
    /// </summary>
    public class MicSelector : IDisposable
    {
        #region Приватные поля
        SpeechLib.SpInProcRecoContext siprc;
        SpeechLib.ISpeechObjectTokens isot;
        SpeechLib.SpObjectToken sot;
        #endregion
        
        #region Конструкторы
        
        /// <summary>
        /// Конструктор по умолчанию.
        /// </summary>
        public MicSelector() 
        {
            siprc = new SpeechLib.SpInProcRecoContext();
            isot = siprc.Recognizer.GetAudioInputs(null, null);
            sot = null;
        }
        
        #endregion
        
        #region Публичные свойства
        
        /// <summary>
        /// Список доступных устройств.
        /// </summary>
        public SpeechLib.ISpeechObjectTokens Isot
        {
            get
            {
                return this.isot;
            }
            private set
            {
                this.isot = value;
            }
        }
        
        #endregion
        
        #region Публичные методы
        
        /// <summary>
        /// Устанавливает выбранный микрофон.
        /// </summary>
        /// <param name="name">Имя микрофона.
        /// <param name="sre">Движок для распознавания.
        public void SetMicByName(string name, ref System.Speech.Recognition.SpeechRecognitionEngine sre)
        {
            if (isot != null)
            {
                sre.SetInputToDefaultAudioDevice();
                sot = FindMicByName(name);
                if (sot != null)
                {
                    FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);
                    object _sapiRecognizer = fi.GetValue(sre);
                    MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);
                    object[] parms = new object[] { sot, true };
                    mi.Invoke(_sapiRecognizer, parms);
                }
            }
        }
        
        /// <summary>
        /// Устанавливает выбранный микрофон.
        /// </summary>
        /// <param name="name">Имя микрофона.
        /// <param name="sre">Движок для распознавания.        
        public void SetMicByName(string name, ref Microsoft.Speech.Recognition.SpeechRecognitionEngine sre)
        {
            if (isot != null)
            {
                sre.SetInputToDefaultAudioDevice();
                sot = FindMicByName(name);
                if (sot != null)
                { 
                    FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);
                    object _sapiRecognizer = fi.GetValue(sre);
                    MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);
                    object[] parms = new object[] { sot, true };
                    mi.Invoke(_sapiRecognizer, parms);
                }
            }
        }
        
        /// <summary>
        /// Обновляет список доступных устройств.
        /// </summary>
        /// <returns>Список доступных устройств.</returns>
        public SpeechLib.ISpeechObjectTokens UpdateDeviceList()
        {
            if (siprc != null)
            {
                isot = siprc.Recognizer.GetAudioInputs(null, null);
                return isot;
            }
            else
            {
                return null;
            }
        }
        
        /// <summary>
        /// Освобождение ресурсов.
        /// </summary>
        public void Dispose()
        {
            if (sot != null)
            {
                sot = null;
            }
            if (isot != null)
            {
                isot = null;
            }
            if (siprc != null)
            {
                siprc = null;
            }
            GC.Collect();
        }
        
        #endregion
        
        #region Приватные функции
        /// <summary>
        /// Поиск микрофона по имени.
        /// </summary>
        /// <param name="name">Имя для поиска.
        /// <returns>Токен микрофона.</returns>
        private SpeechLib.SpObjectToken FindMicByName(string name)
        {
            if (isot != null)
            {
                for (int i = 0; i < isot.Count; i++)
                {
                    sot = isot.Item(i);
                    string desc = sot.GetDescription(1033);
                    string id = sot.Id;
                    if (desc.Contains(name) != false)
                    {
                        break;
                    }
                }
                return sot;
            }
            else
                return null;
        }
 
        #endregion
    }
}

Автор: maxim_rubchenko

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js