Yes, it is possible to save the spoken sentence in using all available voices.
You maybe have not used the pyttsx3 API correctly. Or there is an logical bug with indentation after the loop.
First, let's inspect what your code does.
Use print
to debug
import pyttsx3
engine = pyttsx3.init()
voices = engine.getProperty('voices')
print(f"found {len(voices)} voices to say the sentence") # use f-string to print count of voices
for voice in voices:
engine.setProperty('voice', voice.id)
print('changed voice to: ', voice)
engine.say('The quick brown fox jumped over the lazy dog.')
engine.runAndWait()
# this uses the last voice only
print('using engine current voice to save:', engine.getProperty('voice'))
engine.save_to_file('The quick brown fox jumped over the lazy dog.' , 'audio.mp3')
# Did it save?
Prints all the voices (here showing only first and last):
found 69 voices to say the sentence
changed voice to: <Voice id=afrikaans
name=afrikaans
languages=[b'\x05af']
gender=male
age=None>
...
changed voice to: <Voice id=cantonese
name=cantonese
languages=[b'\x05zh-yue']
gender=male
age=None>
Full dictionary is not installed for 'ru'
Full dictionary is not installed for 'zhy'
using engine current voice to save: cantonese
For me the file audio.mp3
was not created or saved.
Issues
(1) The file was not saved
Maybe because we need a final engine.runAndWait()
command to start the engine, generate the audio and save the file?
See docs example "Saving voice to a file" and runAndWait()
:
runAndWait()
→ None
Blocks while processing all currently queued commands. Invokes callbacks for engine notifications appropriately. Returns when all commands queued before this call are emptied from the queue.
Here we have the reason. It was not saved because the engine did run before queuing the save command:
engine.runAndWait()
# this uses the last voice only
engine.save_to_file('The quick brown fox jumped over the lazy dog.' , 'audio.mp3')
(2) The current (last set) voice is used to save
The current voice set in the engine is also the last set in your loop.
To save an audio-file for each voice, you should include the save command inside the loop.
Move the line up and indent to be aligned within the loop's body. Since you are currently using the fix filename audio.mp3
, it would be wise to change it for each iteration, e.g. prefix the filename with the current voice.id
like filename = "voice.id + "audio.mp3"
.
Fixed solution
Save each voice separately
This should save many files, each with another voice.
import pyttsx3
engine = pyttsx3.init() # engine begins to queue following commands
voices = engine.getProperty('voices')
print(f"found {len(voices)} voices to say the sentence") # use f-string to print count of voices
for voice in voices:
engine.setProperty('voice', voice.id)
print('using engine current voice to save:', engine.getProperty('voice').name)
filename_by_voice = f"audio_{voice.id}.mp3"
print('saving voice to: ', filename_by_voice)
engine.save_to_file('The quick brown fox jumped over the lazy dog.' , filename_by_voice)
# final command to start the engine and execute queued commands
engine.runAndWait() # save the file(s)
Note: I removed the say
command to speed up things.