Friday, September 21, 2018

Using TTS on Android: Punctuation is read aloud

Leave a Comment

CONTEXT: My application is sending sentences to whatever TTS engine the user has. Sentences are user-generated and may contain punctuation.

PROBLEM: Some users report that the punctuation is read aloud (TTS says "comma" etc) on SVOX, Loquendo and possibly others.

QUESTION:

  1. Should I strip all punctuation?
  2. Should I transform the punctuation using this kind of API?
  3. Should I let the TTS engine deal with the punctuation?

The same user that sees the problem with Loquendo, does not have this problem with another Android application called FBReader. So I guess the 3rd option is not the right thing to do.

2 Answers

Answers 1

I had the same problem with one of my apps.

The input string was:

Next alarm in 10 minutes,it will be 2:45 pm

and the TTS engine would say:

Next alarm in 10 minutes comma it will be 2:45 pm.

The problem was fixed just by adding a space after the comma like this:

Next alarm in 10 minutes, it will be 2:45 pm

This is a stupid mistake, and maybe your problem is more complicated than that, but it worked for me. :)

Answers 2

So, you're worried about what back-alley-acquired text-to-speech engine the user might happen to have selected as their default... presumably because you don't want your app to look bad due to this engine's unknown/bad behavior. Understandable.

The (good) fact is, though, that the TTS's behavior is not actually your responsibility unless you decide to embed an engine in the app itself (Difficulty: Hard, Recommended? No).

Engines can and should be presumed to adhere to Android rules and behaviors dictated here... and presumed to supply their own sufficient set of configuration options in the Android system settings (home\settings\language&locale\TTS) which may or may not include pronunciation options. The user should also be presumed intelligent enough to install an engine that they are satisfied with.

It is a slippery slope to take on the job of anticipating and "correcting" for unknown and unwanted engine behaviors (at least in engines that you haven't tested yourself).

A SIMPLE AND GOOD OPTION (Difficulty: Easy):

  • Make a setting in your app: "ignore punctuation."

A BETTER OPTION (Difficulty: Medium):

  • Do the above, but only show the "ignore punctuation" setting-option if the engine you have detected on the user's device is prone to this issue.

Also, one thing to note is that there are many, many differences between engines (whether they use embedded voices vs online, response time, initialization time, reliability/adherence to Android specs, behavior across Android API levels, behavior across their own version history, the quality of voices, not to mention language capability)... differences that may be even more important to users than whether or not punctuation is pronounced.

You say "My application is sending sentences to whatever TTS engine the user has." Well... "That's yer problem right there." Why not give the user a choice on what engine to use?

And leads us to...

AN EVEN BETTER OPTION (Difficulty: Hard and Good! [in my humble opinion]):

  • Decide on some "known-good" engines your app will "support," starting with Google and Samsung. I would guess that there are less than 5% of devices out there these days that don't have either of those engines on them.
  • Study and test these engines as much as possible across all Android API levels that you plan to support... at least in as far as whether they pronounce punctuation or not.
  • Over time, test more engines if you like, and add them to your supported engines in subsequent app updates.
  • Run an algorithm when your app starts that detects which engines are installed, then use that info against your own list of supported engines:

private ArrayList<String> whatEnginesAreInstalled(Context context) {     final Intent ttsIntent = new Intent();     ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);     final PackageManager pm = context.getPackageManager();     final List<ResolveInfo> list = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);     ArrayList<String> installedEngineNames = new ArrayList<>();     for (ResolveInfo r : list) {         String engineName = r.activityInfo.applicationInfo.packageName;         installedEngineNames.add(engineName);          // just logging the version number out of interest         String version = "null";         try {             version = pm.getPackageInfo(engineName,             PackageManager.GET_META_DATA).versionName;             } catch (Exception e) {                 Log.i("XXX", "try catch error");             }         Log.i("XXX", "we found an engine: " + engineName);         Log.i("XXX", "version: " + version);     }     return installedEngineNames; } 

  • In your app's settings, present all engines that you've decided to support as options (even if not currently installed). This could be a simple group of RadioButtons with titles corresponding to the different engine names. If the user selects one that isn't installed, notify them of that and give them the option of installing it with an intent.
  • Save the user's selected engine name (String) in SharedPreferences, and use their selection as the last argument of the TextToSpeech constructor any time you need a TTS in your app.
  • If the user has some weird engine installed, present it as a choice also, even if it is unrecognized/unsupported, but inform them that they have selected an unknown/untested engine.
  • If the user selects an engine that is supported but is known to pronounce punctuation (bad), then upon selection of that engine, have an alert dialog pop up warning the user about that, explaining that they can turn this bad behavior off with the "ignore punctuation" setting referred to already.

SIDE-NOTES:

  • Don't let the SVOX/PICO (emulator) engine get you too worried -- it has many flaws and is not even designed or guaranteed to run on Android above API ~20, but is still included on emulators images up to API ~24, resulting in "unpredictable results" that don't actually reflect reality. I have yet to see this engine on any real hardware device made within the last seven years or so.

  • Since you say that "sentences are user generated," I would be more worried about solving the problem of what language they are going to be typing in! I'll look out for a question on that! :)

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment