Text to Speech

oromanetti, that solely depends on the engine being used.

Thank you Lerg :slight_smile:

could you tell me more?

I’m on iOS, What should I do if I want the engine to consider dots?

Hi,

Thank you for this plugin, it’s great  :slight_smile:

I use the sample project and I’ve tried to put this text:

local text = ‘at mat.sam sat.tom sat.mom sat.mom sat tom.mom sat sam.tom at mat.’   

These are small sentences for an educational app for kids.

My problem is that when I push the “Speak” button, the engine reads the sentences without taking account dots as if it was only one sentence. I don’t understand why.

Another “bug” is that it pronounces " sat." as " saturday".

Any help would be very appreciated.

Thank you!   :slight_smile:

Best

Olivier

Hi,

I’ve discovered that if you do not put an uppercase at the beginning of sentences, the machine ignores period (".")

In my exemple, if your text is

local text = ‘at mat. sam sat. tom sat. mom sat. mom sat tom. mom sat sam. tom at mat.’  

-> the periods are ignored and “sat.” is pronounced “saturday”

But if your text is 

local text = ‘At mat. Sam sat. Tom sat. Mom sat. Mom sat tom. Mom sat sam. Tom at mat.’  

-> the periods are NOT ignored!!! and “sat.” is correctly pronounced

Is it possible to “pause / resume” the engine ?

I am glad you could resolve it. And thanks for the discovery, that’s useful.
Unfortunately, it’s not possible to pause/resume the speech.

Hi thus this plugin supports Hindi or Marathi Language.

and if yes please share the language code to be used.

How to use that

??

local listener3=function()

 local text = ’ दिल्ली के मुख्यमंत्री अरविंद केजरीवाल के सचिव के घर पर केंद्रीय जांच ब्यूरो की छापामारी को लेकर तीखी प्रतिक्रिया मिलीं’

        texttospeech.speak(text, {

            language = ’ hi-IN’,       

            pitch = 0.8,

            rate = 0.6,

            volume = 0.9   

        })

end

local button3=display.newCircle(300,400,30)

button3:addEventListener(“tap”,listener3)

Help!  I am going mad trying to get this to work.  I have a overlay which has the following code:- 

local texttospeech = require(‘plugin.texttospeech’)  

When the scene loads I call texttospeech.init(SpeakNow) and it all works.  The speech engine fires up and speaks whatever I have asked it to.

If the user closes the Overlay and reloads it, nothing happens - the speech will not replay.

I have tried to clear down everything: -

texttospeech.stop()

texttospeech = nil

package.loaded[“plugin.texttospeech”] = nil

But it will not play the speech again??  Any ideas?

matt405, you don’t need to unload the plugin, it should work. The usual cause for such problems is global variables, maybe you have some global function that is no longer valid after you enter the overlay again. Put print statements everywhere and see what is getting called and when.

A heads up. The plugin will become paid on Wednesday (Oct. 12). If you have any nearly completed apps, submit them while the plugin is free.

Launch sale for $14.99 for a week and $19.99 after that. Subscription so I can support the plugin over time.

Thanks everybody for your testing and suggestions while it was free!

I have some problems switching language with this plugin. I’m doing an app helping kids learn foreign words and I want the app to read a list of word pairs (domestic language / foreign languaga). But after one switch, the language seems to be locked and will not switch again!

So the first word is spoken in Norwegian and the rest of the words are spoken in British English.

Below is a very simple app demonstrating the problem:

local texttospeech = require("plugin.texttospeech") texttospeech.init() local nextWord = 1 local lastWord = 4 local readyForNextWordTimer = nil local function readNextSequence(idx) if (idx == 1) then texttospeech.speak("katt", {language = "no-NO"}) nextWord = 2 elseif (idx == 2) then texttospeech.speak("cat", {language = "en-GB"}) nextWord = 3 elseif (idx == 3) then texttospeech.speak("fugl", {language = "no-NO"}) nextWord = 4 elseif (idx == 4) then texttospeech.speak("bird", {language = "en-GB"}) nextWord = 5 else timer.cancel(readyForNextWordTimer) end end local function checkIfFinished() if (texttospeech.isSpeaking() == false) then readNextSequence(nextWord) end end readyForNextWordTimer = timer.performWithDelay( 1000, checkIfFinished, -1)

(full source attached)

Maybe I’m doing something wrong when waiting for the spoken word to be finished. It seems to work ok, except for the language switching part…

And, yes, I’m a paying customer…  :wink:

A heads up. The plugin will become paid on Wednesday (Oct. 12). If you have any nearly completed apps, submit them while the plugin is free.

Launch sale for $14.99 for a week and $19.99 after that. Subscription so I can support the plugin over time.

Thanks everybody for your testing and suggestions while it was free!

I’m currently using this in a released app. How will this affect me? Will I not be able to use it going forward? (unless I pay)

As I’ve understood it it will work, but you will not be able to update/bugfix it anymore.

Ok, I see.  :frowning:

Yes, it’s a bummer that you have to pay a yearly fee to be able to service an existing app. But I guess the line has to be drawn somewhere. In my case it’s a quite “living” app with many bug fixes and new things (using this very plugin) so it feels fair to pay for it.

And now that the plugin is paid for, Sergey cannot call this just a hobby project anymore and has to respond to support queries in a swift fashion - hehehe  :smiley:

This plugin seems to have an issue with recursive calls inside the onComplete event; you can’t call the same function that you were at while creating the onComplete function. I don’t know if this is a Lua limitation or just this particular plugin.

Here’s a fully working example demonstrating this. Make sure you import the plugin in build.settings before running this.

* running on iOS 10 will crash after the first sentence is finished

local texttospeech = require('plugin.texttospeech') texttospeech.init() local cards = { "Little pig, little Pig, let me come in.", "No, no, not by the hair on my chinny chin chin.", "", "Then I'll huff, and I'll puff, and I'll blow your house in." } local readingCardNumber -- currently reading this card. First card index is 1. local readNextCard = function() readingCardNumber = readingCardNumber + 1 print("Attempting to read card " .. tostring(readingCardNumber) .. " of " .. tostring(#cards)) if readingCardNumber \> #cards then print("No more cards to read") return end local readText = cards[readingCardNumber] if readText ~= nil and readText ~= "" then print("Reading: " .. readText) local options = { language = 'en-US', id = "cardNumber" .. tostring(readingCardNumber), onComplete = function(id) print('Speech "' .. id .. '" has ended.') readNextCard() end, onProgress = function(id, start, count) print("Speech " .. id .. ": " .. readText:sub(start, start + count)) end, } if texttospeech.isSpeaking() then texttospeech.stop() end texttospeech.speak(readText, options) else print("Skipping empty text found on card " .. tostring(readingCardNumber)) readNextCard() end end local function startReading() readingCardNumber = 0 readNextCard() end startReading()

The solution I found (hacky and horrible) is to have a timer that will try to call the next sentence but will exit if we are already speaking something else:

local texttospeech = require('plugin.texttospeech') texttospeech.init() local cards = { "Little pig, little Pig, let me come in.", "No, no, not by the hair on my chinny chin chin.", "", "Then I'll huff, and I'll puff, and I'll blow your house in." } local readingCardNumber -- currently reading this card. First card index is 1. local doneReading = false -- exit condition local timerId function readNextCard() if texttospeech.isSpeaking() then print("."); return end readingCardNumber = readingCardNumber + 1 print("Attempting to read card " .. tostring(readingCardNumber) .. " of " .. tostring(#cards)) if readingCardNumber \> #cards then print("No more cards to read") timer.cancel(timerId) return end local readText = cards[readingCardNumber] if readText ~= nil and readText ~= "" then print("Reading: " .. readText) local options = { language = 'en-US', id = "cardNumber" .. tostring(readingCardNumber), onComplete = function(id) print('Speech "' .. id .. '" has ended.') end, onProgress = function(id, start, count) print("Speech " .. id .. ": " .. readText:sub(start, start + count)) end, } if texttospeech.isSpeaking() then texttospeech.stop() end texttospeech.speak(readText, options) else print("Skipping empty text found on card " .. tostring(readingCardNumber)) readNextCard() end end local function startReading() readingCardNumber = 0 readNextCard() end timerId = timer.performWithDelay(100, readNextCard, -1) startReading()

Any luck on looking at the multi language issue, Lerg?

I’ve made a slightly more advanced test setup where the user can select between speaking the same Norwegian word “værhane” in Norwegian, English and Russian:

W = display.actualContentWidth texttospeech = require("plugin.texttospeech") status = display.newText("", 50, 150, native.systemFont, 0.03\*W) status.anchorX = 0 status.anchorY = 0 function initCB(e) status.text = status.text .. "\nis error: " .. tostring(e.isError) end local txt = "værhane" function norTouch(e) if (e.phase == "ended") then status.text = status.text .. "\ntexttospeech.speak('" .. txt .. "', {language = 'no-NO'})" texttospeech.speak(txt, {language = "no-NO"}) end end function engTouch(e) if (e.phase == "ended") then status.text = status.text .. "\ntexttospeech.speak('" .. txt .. "', {language = 'en-GB'})" texttospeech.speak(txt, {language = "en-GB"}) end end function rusTouch(e) if (e.phase == "ended") then status.text = status.text .. "\ntexttospeech.speak('" .. txt .. "', {language = 'ru-RU'})" texttospeech.speak(txt, {language = "ru-RU"}) end end nor = display.newText("NOR", 0.20\*W, 50, native.systemFontBold, 0.1\*W) eng = display.newText("ENG", 0.50\*W, 50, native.systemFontBold, 0.1\*W) rus = display.newText("RUS", 0.80\*W, 50, native.systemFontBold, 0.1\*W) nor:addEventListener("touch", norTouch) eng:addEventListener("touch", engTouch) rus:addEventListener("touch", rusTouch) status.text = status.text .. "\ncalling init()" texttospeech.init(initCB)

This setup behaves very, very strange!

If I tap Norwegian first, the text is spoken correctly in Norwegian. If I tap English or Russian first, the app will never again speak Norwegian again. Instead it uses the last spoken language between English and Russian.

The strange thing is that switching between English and Russian seems to work great. It’s just switching back to Norwegian that doesn’t seem to work…

Will be looking at the reported issues on the weekend.
If switching languages doesn’t work that’s really strange, I’ll try to see what’s happening.