Офлайн розпізнавання мови в Android (JellyBean)


78

Схоже, Google зробив функцію розпізнавання мови в режимі офлайн доступною від Google Now для сторонніх програм. Він використовується додатком під назвою Utter .

Хто-небудь бачив якісь реалізації того, як виконувати прості голосові команди за допомогою цього офлайн-запису? Ви просто використовуєте звичайний API SpeechRecognizer, і він працює автоматично?


1
Отже, поки ми завантажуємо мову, нам не потрібно змінювати наш код?
Ruchir Baronia

Відповіді:


73

Google спокійно ввімкнув розпізнавання в автономному режимі в цьому оновленні пошуку, але (поки) немає API або додаткових параметрів, доступних у класі SpeechRecognizer . {Див. Редагування внизу цієї публікації} Функціонал доступний без додаткового кодування, однак пристрій користувача потрібно буде правильно налаштувати, щоб він почав працювати, і в цьому полягає проблема, і я думаю, чому багато розробників припустимо, що їм «чогось не вистачає».

Крім того, Google заборонила певним пристроям Jelly Bean використовувати автономне розпізнавання через апаратні обмеження. До яких пристроїв це стосується, не задокументовано, насправді нічого не задокументовано, тому налаштування можливостей для користувача виявилося питанням спроб і помилок (для них). Для деяких це працює відразу - для тих, хто цього не робить, це «керівництво», яке я їм надаю.

  1. Переконайтеся, що за замовчуванням Android Voice Recogniser встановлено на Google, а не на Samsung / Vlingo
  2. Видаліть усі встановлені в автономному режимі файли розпізнавання в налаштуваннях Google Voice Search
  3. Перейдіть у налаштування програми Android і перевірте, чи можете ви видалити оновлення для програм Google Search і Google Voice Search.
  4. Якщо ви не можете зробити вищезазначене, перейдіть до Play Store і перевірте, чи є у вас там можливість.
  5. Перезавантажте (якщо ви досягли 2, 3 або 4)
  6. Оновіть Google Search і Google Voice Search із магазину Play (якщо ви досягли 3 чи 4 або якщо оновлення доступне в будь-якому випадку).
  7. Перезавантажте (якщо ви досягли 6)
  8. Встановіть англійські британські мовні файли
  9. Перезавантажте
  10. Використовуйте повне! з підключенням
  11. Перейдіть у режим польоту і спробуйте
  12. Після того, як воно запрацює, офлайн-розпізнавання інших мов, таких як англійська, США також має почати працювати.

РЕДАГУВАТИ: Тимчасове змінення мовної установки пристрою на англійську UK також, здається, запускає це, щоб це працювало для деяких.

Деякі користувачі повідомляли, що їм все одно довелося перезавантажуватися кілька разів, перш ніж він почне працювати, але всі вони з часом потрапляють туди, часто незрозуміло до того, що було тригером, ключ до якого знаходиться всередині файлу .apk пошуку Google , тож не у відкритому доступі або частина AOSP .

З того, що я можу встановити, Google перевіряє наявність підключення, перш ніж вирішувати, чи використовувати розпізнавання в автономному режимі чи в Інтернеті. Якщо спочатку доступне з’єднання, але воно втрачене до відповіді, Google надасть помилку підключення, і воно не повернеться до режиму офлайн. Як додаткове зауваження, якщо було зроблено запит на синтезований мережевий голос, помилка не надається, якщо не вдається - Ви отримуєте тишу.

Оновлення пошуку Google не ввімкнуло жодних додаткових функцій в Google Now, і насправді, якщо ви спробуєте використовувати його без з’єднання з Інтернетом, воно помилиться. Я згадую це, коли думав, чи не буде ця здатність вилучена так тихо, як з’явилося, і тому не слід покладатися на неї у виробництві.

Якщо ви маєте намір почати використовувати клас SpeechRecognizer, будьте застережені, з ним пов’язана досить велика помилка , для обробки якої потрібна ваша власна реалізація.

Неможливість спеціального запиту офлайн = істина робить управління цією функцією неможливим без маніпуляцій з підключенням даних. Сміття. Ви отримаєте сотні електронних листів із запитаннями, чому ви не ввімкнули щось таке просте!

EDIT: Починаючи з API рівня 23, був доданий новий параметр EXTRA_PREFER_OFFLINE, якого служба розпізнавання Google, схоже, дотримується.

Сподіваюся, вищесказане допомагає.


Це чудово працює для мене, і його було дуже легко реалізувати. Я використав цей зразок тут як вихідну точку. jameselsey.co.uk/blogs/techblog/…
rmooney

@brandall Цікаво, чи можу я вибрати мову, якою я визнаю? Офлайн-файл мови підтримує мою мову (в'єтнамська) зараз! Я хочу створити програму, яка виконує розпізнавання мови в режимі офлайн ДО моєї мови (в'єтнамська)! Це можливо ?? Дуже вдячний!
truongnm

1
@truongmn - Це допомагає? stackoverflow.com/q/10538791/1256219 Якщо ні, задайте нове запитання і
приєднайте

На моєму Samsung Galaxy Grand Prime під керуванням Kitkat 4.4 мені довелося вимкнути програми Google Search (і Google+) з Диспетчера програм, потім увімкнути «Обмежити фонові дані» (або переконатися, що у мене не було доступного з’єднання), а потім знову активувати програми Google Search (і Google+) (можливо, мені також довелося очистити всі дані для цих програм безпосередньо перед тим, як їх вимкнути). Тоді як, коли я намагався увімкнути функцію «Обмежити фонові дані», коли ці програми були ввімкнені, тоді мікрофон не відображався в номеронабирачі. Очевидно, повторне ввімкнення без з’єднання (або обмеження) змушує використовувати офлайн.
Шелбі Мур III

Привіт, допоможіть мені у цьому stackoverflow.com/questions/32866239/…
Рао

20

Я хотів би вдосконалити керівництво, яке відповідь https://stackoverflow.com/a/17674655/2987828 надсилає своїм користувачам із зображеннями. Це речення "Для тих, хто цього не робить, це" керівництво ", яке я їм надаю". що я хочу вдосконалити.

Користувач повинен натиснути на чотири кнопки, виділені синім кольором на цих зображеннях:

Перейдіть до налаштувань програми Android, виберіть Мови та введення, редагувати налаштування набору тексту в Google Voice, виберіть Завантажити розпізнавання мови в режимі офлайн, виберіть свої мови на вкладці ALL.

Тоді користувач може вибрати будь-які бажані мови. Коли завантаження буде завершено, він повинен від’єднатися від мережі, а потім натиснути кнопку «мікрофон» на клавіатурі.

У мене це працювало (android 4.1.2), потім розпізнавання мови працювало нестандартно, без перезавантаження. Тепер я можу диктувати інструкції оболонці емулятора терміналів! І це вдвічі швидше в автономному режимі, ніж в Інтернеті, на padfone 2 від ASUS.

Ці зображення ліцензовані згідно cc by-sa 3.0 з атрибуцією, необхідною для stackoverflow.com/a/21329845/2987828; отже, ви можете додати ці зображення де завгодно разом із цим приписом.

(Це стандартна політика щодо всіх зображень та текстів на stackoverflow.com)


18

Просте та гнучке розпізнавання в режимі офлайн на Android реалізоване CMUSphinx, інструментарієм розпізнавання мови з відкритим кодом. Він працює суто в автономному режимі, швидко і налаштовується. Наприклад, він може постійно слухати ключові слова.

Ви можете знайти найновіший код та підручник тут .

Оновлення в 2019 році : час йде швидко, CMUSphinx вже не такий точний. Натомість рекомендую спробувати набір інструментів Kaldi. Демо-версія тут .


1
Я щойно спробував демонстрацію, і вона працює досить добре. Швидкий і простий у використанні.
Мікер

2
Привіт, CMUSphinx також працює для індійської англійської мови з наголосом?
Люцифер

1
@Kedarnath, здається, це в їх списку, див. Опитування тут: cmusphinx.sourceforge.net
Джертер

Дякую, спробуй зараз!
Hermandroid

Це працює для арабської? Чи знаєте ви щось, що працює на арабську?
Юсеф Шериф

7

Коротше кажучи, у мене не реалізація, а пояснення.

Google не надав доступ до розпізнавання мови в режимі офлайн для сторонніх програм. Офлайн-розпізнавання доступне лише за допомогою клавіатури. Бен Рендалл (розробник ультра!) Пояснює своє обхідне рішення у статті в Android Police:

Я застосував власну клавіатуру і перемикався між Google Voice Typing та типовою клавіатурою користувачів із невидимим текстовим полем редагування та прозорою активністю для отримання вводу. Брудний хак!

Це був єдиний спосіб зробити це, оскільки голосовий ввід в режимі офлайн може бути ініційований лише за допомогою IME або системної програми (це був мій корінь). Інший тип API розпізнавання… не активував його, а просто помилився з помилкою сервера. ... Багато роботи витрачено для мене на обхідний шлях! Але принаймні я був готовий до реалізації ...

З Аттера! Претензії бути першим додатком, що не стосується IME, і який використовував розпізнавання голосу в режимі офлайн у Jelly Bean


4
Я думав, що саме він, за його словами, робив до останнього оновлення. Слідом за вашою цитатою: "Рендалл продовжував пояснювати, що Utter! Тепер використовує SpeechRecognizer, який був оновлений, дозволяючи розробникам використовувати автономне розпізнавання в ряді програм, тоді як Recognizerintent, попередній офлайн-код голосового набору, вимагав дійсного токена IME".
rmooney

3

Я успішно реалізував свою мовленнєву службу з автономними можливостями, використовуючи onPartialResults в автономному режимі та onResults в Інтернеті.


Чи можу я дізнатись більше про це, будь ласка. у мене тут є помилка, пов’язана з публікацією stackoverflow.com/questions/32866239/…
Rao's

2

Я мав справу з цим і помітив, що вам потрібно встановити офлайн-пакет для вашої мови. Моєю мовною настройкою було "Español (United States)", але для цієї мови немає офлайн-пакету, тому, коли я вимкнув усі підключення до мережі, я отримав попередження від RecognizerIntent про те, що не вдається зв’язатися з Google, тоді я зміню мову на "English (US)" (оскільки я вже маю офлайн-пакет) і запустив RecognizerIntent, що він щойно вийшов.

Клавіші: Налаштування мови == Пакет розпізнавання голосу в режимі офлайн


Чи можу я дізнатись, яким пристроєм ви користувались? Чи підтримує він, а не пристрій Google. Як Samsung, Asus тощо. Я працюю над ним і в автономному режимі не підтримую інші пристрої.
Рао

1

Очевидно, можливо встановити розпізнавання голосу в режимі офлайн вручну, завантаживши файли безпосередньо та встановивши їх у потрібних місцях вручну. Я думаю, це лише спосіб обійти вимоги Google до обладнання. Однак особисто мені не довелося перезавантажуватись або щось інше, просто переходячи до Великобританії та назад, зробив це.


0

Робочий приклад наведено нижче,

MyService.class

public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay {

  public static SpeechDelegate delegate;

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    //TODO do something useful
    try {
      if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
        ((AudioManager) Objects.requireNonNull(
          getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    Speech.init(this);
    delegate = this;
    Speech.getInstance().setListener(this);

    if (Speech.getInstance().isListening()) {
      Speech.getInstance().stopListening();
    } else {
      System.setProperty("rx.unsafe-disable", "True");
      RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
        if (granted) { // Always true pre-M
          try {
            Speech.getInstance().stopTextToSpeech();
            Speech.getInstance().startListening(null, this);
          } catch (SpeechRecognitionNotAvailable exc) {
            //showSpeechNotSupportedDialog();

          } catch (GoogleVoiceTypingDisabledException exc) {
            //showEnableGoogleVoiceTyping();
          }
        } else {
          Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
        }
      });
    }
    return Service.START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    //TODO for communication return IBinder implementation
    return null;
  }

  @Override
  public void onStartOfSpeech() {
  }

  @Override
  public void onSpeechRmsChanged(float value) {

  }

  @Override
  public void onSpeechPartialResults(List<String> results) {
    for (String partial : results) {
      Log.d("Result", partial+"");
    }
  }

  @Override
  public void onSpeechResult(String result) {
    Log.d("Result", result+"");
    if (!TextUtils.isEmpty(result)) {
      Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
    }
  }

  @Override
  public void onSpecifiedCommandPronounced(String event) {
    try {
      if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
        ((AudioManager) Objects.requireNonNull(
          getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    if (Speech.getInstance().isListening()) {
      Speech.getInstance().stopListening();
    } else {
      RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
        if (granted) { // Always true pre-M
          try {
            Speech.getInstance().stopTextToSpeech();
            Speech.getInstance().startListening(null, this);
          } catch (SpeechRecognitionNotAvailable exc) {
            //showSpeechNotSupportedDialog();

          } catch (GoogleVoiceTypingDisabledException exc) {
            //showEnableGoogleVoiceTyping();
          }
        } else {
          Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
        }
      });
    }
  }


  @Override
  public void onTaskRemoved(Intent rootIntent) {
    //Restarting the service if it is removed.
    PendingIntent service =
      PendingIntent.getService(getApplicationContext(), new Random().nextInt(),
        new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT);

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    assert alarmManager != null;
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
    super.onTaskRemoved(rootIntent);
  }
}

Докладніше

https://github.com/sachinvarma/Speech-Recognizer

Сподіваюся, це допоможе комусь у майбутньому.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.