B4J Code Snippet [PyBridge] Text to Speech with pyttsx3


Dependency:
pip install pyttsx3

1742111475887.png


B4X:
Private Sub CreateEngine As ResumableSub
    Ttsx3Engine = Py.ImportModule("pyttsx3").Run("init")
    Dim voices As PyWrapper = Ttsx3Engine.Run("getProperty").Arg("voices")
    'Get the voices names:
    Dim VoicesNames As PyWrapper = Py.Map_(Py.Lambda("v: v.name"), voices).ToList
    Wait For (VoicesNames.Fetch) Complete (voices As PyWrapper)
    For Each Voice As String In voices.Value.As(List)
        ListView1.Items.Add(Voice)
    Next
    Wait For (Py.Flush) Complete (Success As Boolean)
    Return Success
End Sub

Private Sub ListView1_SelectedIndexChanged(Index As Int)
    Dim voices As PyWrapper = Ttsx3Engine.Run("getProperty").Arg("voices")
    Ttsx3Engine.Run("setProperty").Arg("voice").Arg(voices.Get(Index).GetField("id"))
End Sub

Private Sub Say(Text As String)
    Button1.Enabled = False
    Ttsx3Engine.Run("say").Arg(Text)
    Ttsx3Engine.Run("runAndWait")
    Ttsx3Engine.Run("stop")
    Wait For (Py.Flush) Complete (Success As Boolean)
    Button1.Enabled = True
End Sub
 

Attachments

  • TTS.zip
    3.8 KB · Views: 27

Erel

B4X founder
Staff member
Licensed User
Longtime User
This line worth some explanation:
B4X:
Dim VoicesNames As PyWrapper = Py.Map_(Py.Lambda("v: v.name"), voices).ToList
The "map" method, takes a function (lambda function in this case) and runs it on each item in the list. It returns an iterable object which we convert back to a list with the ToList call.

B4X:
Dim list As PyWrapper = Py.WrapObject(Array(1, 2, 3, 4)) 'it actually creates a tuple, which can be thought of as a read-only list, but it is not important in this case
list = Py.Map_(Py.Lambda("x: x * 2"), list).ToList
list.Print

[2, 4, 6, 8]
 

udg

Expert
Licensed User
Longtime User
Great example. Thanks Erel.

But..wait a minute..
B4X:
ListView1.Items.Add(Voice)
Please read #1 in this thread.. :)

Sorry, I couldn't resist.
 

udg

Expert
Licensed User
Longtime User
Experimenting with the demo code..
Add two lines (well, one will suffice) to sub ListView1_SelectedIndexChanged to change the speaking out rate.
B4X:
Private Sub ListView1_SelectedIndexChanged(Index As Int)
    Dim voices As PyWrapper = Ttsx3Engine.Run("getProperty").Arg("voices")
    Ttsx3Engine.Run("setProperty").Arg("voice").Arg(voices.Get(Index).GetField("id"))
    Dim rate As PyWrapper = Ttsx3Engine.Run("getProperty").Arg("rate")
    Ttsx3Engine.Run("setProperty").Arg("rate").Arg(175)
    'Ttsx3Engine.Run("setProperty").Arg("volume").Arg(0.5)            'ranges between 0.0 and 1.0
End Sub
Uncomment the row about the volume change to experiment with volume level too.
 

Similar Threads

Top