gTTS 无法保存文件两次



我正在尝试将gTTS用作个人助理项目的真实文本到语音模块。查询谷歌服务时,我可以保存mp3文件并使用pygame运行它。

from pygame import mixer
from gtts import gTTS    
def speak(data):
    tts = gTTS(text=data, lang='en')
    tts.save('speech.mp3')
    mixer.init()
    mixer.music.load('speech.mp3')
    mixer.music.play()

运行函数时,一旦成功输出就会"说话",但是当再次运行它时,它会失败并显示错误。

Traceback (most recent call last):
  File "C:Usersuser1Desktopproject_aiassistant.py", line 7, in <module>
    text_to_speech.main('hello')
  File "C:Usersuser1Desktopproject_aimodulesspeech_text_synthesistext_to_speech.py", line 8, in main
    tts.save('speech.mp3')                                                                                                                                       File "C:Usersuser1AppDataLocalProgramsPythonPython36libsite-packagesgttstts.py", line 246, in save
    with open(savefile, 'wb') as f:                                                                                                                                   PermissionError: [Errno 13] Permission denied: 'speech.mp3'

尝试再次将文本保存到另一个mp3时发生错误。因此,pygame无法玩它。我知道我可以简单地更改文件名来保存它,但我宁愿不这样做。我如何才能做到这一点?

终于...成功。。。

我已经研究了这个问题几个小时。 除了PyGame之外,我还尝试了多种不同的声音播放器(pyaudio,playsound,pyglet等(。 我走上了其他人都走过的那条路。

然后。。。。它击中了我...一条不同的路...使用两个文件名。(一种称为双缓冲的技术(。

虽然我没有使用这个特定的代码,但我想我应该使用你的代码给出一个答案......

from pygame import mixer
from gtts import gTTS    
count = 0
def speak(data):
    global count
    tts = gTTS(text=data, lang='en')
    tts.save(f'speech{count%2}.mp3')
    mixer.init()
    mixer.music.load(f'speech{count%2}.mp3')
    mixer.music.play()
    count += 1

它起作用的原因是 TTS 库将在切换到新文件时释放以前的文件。 我们在尝试使用 1 个文件名时面临的问题是,我们很难找到一种方法来释放文件资源。 当您切换到其他文件名时,此方法会释放它。

享受互联网! 去制作一些很酷的程序!

这似乎是pygame的常见问题,至少我在SO上发现了一些关于这个主题的已删除问题。

尝试在保存后通过内存映射文件加载文件,而不是仅使用文件名,如下所示:

import mmap
...
def speak(data):
    tts = gTTS(text=data, lang='en')
    tts.save('speech.mp3')
    with open('speech.mp3') as f: 
        m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
    pygame.mixer.music.load(m) 
    pygame.mixer.music.play() 
    m.close() 

使用上下文管理器可确保文件在复制到内存后实际关闭,并且pygame.mixer.music.load根本不会接触文件。

最新更新