简体   繁体   English

有没有办法用pyttsx3保存包含不同声音的音频文件?

[英]Is there a way to save an audio file containing different voices with pyttsx3?

I combined these examples from the official pyttsx3 documentation:我结合了官方pyttsx3文档中的这些示例:

I want to save an audio file containing all the voices.我想保存一个包含所有声音的音频文件。

Code代码

import pyttsx3

engine = pyttsx3.init()
voices = engine.getProperty('voices')
for voice in voices:
    engine.setProperty('voice', voice.id)
    engine.say('The quick brown fox jumped over the lazy dog.')

engine.runAndWait()

# this uses the last voice only
engine.save_to_file('The quick brown fox jumped over the lazy dog.' , 'audio.mp3')

Issue问题

The engine.save_to_file('The quick brown fox jumped over the lazy dog.', 'audio.mp3') will use the last voice reading the sentence. engine.save_to_file('The quick brown fox jumped over the lazy dog.', 'audio.mp3')将使用最后一个语音朗读句子。

Question

Is it possible to do so?有可能这样做吗? Are there other Text-To-Speach engines (tts) that can do?是否有其他文本转语音引擎 (tts) 可以做到?

You can include the last part of your code ( engine.save_to_file('The quick brown fox jumped over the lazy dog.', 'audio.mp3') ) inside the while loop to obtain seperate audio files with each of the voice.您可以将代码的最后一部分 ( engine.save_to_file('The quick brown fox jumped over the lazy dog.', 'audio.mp3') ) 包含在 while 循环中,以获得每个声音的单独音频文件

import pyttsx3

engine = pyttsx3.init()
voices = engine.getProperty('voices')

for i, voice in enumerate(voices, start=1):
    engine.setProperty('voice', voice.id)
    engine.say('The quick brown fox jumped over the lazy dog.')
    engine.save_to_file('The quick brown fox jumped over the lazy dog.' , f'audio_{i}.mp3')
    

engine.runAndWait()

This will save each voice to files in the order audio1.py, audio2.py, etc....这会将每个语音按 audio1.py、audio2.py 等顺序保存到文件中......

If you want to concatenate these audio files together then there are modules for such purposes.如果您想将这些音频文件连接在一起,那么有用于此类目的的模块。 Refer to https://www.thepythoncode.com/article/concatenate-audio-files-in-python regarding this.有关此内容,请参阅https://www.thepythoncode.com/article/concatenate-audio-files-in-python

Yes, it is possible to save the spoken sentence in using all available voices.是的,可以使用所有可用的语音来保存口语句子。

You maybe have not used the pyttsx3 API correctly.您可能没有正确使用 pyttsx3 API。 Or there is an logical bug with indentation after the loop.或者在循环后有缩进的逻辑错误。

First, let's inspect what your code does.首先,让我们检查一下您的代码做了什么。

Use print to debug使用print调试

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.对我来说,文件audio.mp3没有创建或保存。

Issues问题

(1) The file was not saved (1) 文件未保存

Maybe because we need a final engine.runAndWait() command to start the engine, generate the audio and save the file?也许是因为我们需要最后一个engine.runAndWait()命令来启动引擎、生成音频并保存文件? See docs example "Saving voice to a file" and runAndWait() :请参阅文档示例“将语音保存到文件”runAndWait()

runAndWait() → None runAndWait() → 无

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 (2) 使用当前(上次设置)语音保存

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, eg prefix the filename with the current voice.id like filename = "voice.id + "audio.mp3" .由于您当前使用的是修复文件名audio.mp3 ,因此每次迭代都更改它是明智的,例如,在文件名前加上当前的voice.id前缀,例如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.注意:我删除了say命令以加快速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM