我正在尝试使用来自Github(来自DeepHorizons)的tts模块制作具有文本到语音功能的程序。由于我希望能够在讲话时停止该节目,我将音频录制到文件然后播放。为了能够创建多次相同的文件名(say.wav),我需要删除旧文件。问题是我无法删除它,因为它被使用(PermissionError:[WinError 32]进程无法访问该文件,因为它正被另一个进程使用),但它只发生在第二个进程它说话的时间 - 第一次,它退出pygame并删除文件;在第二次,它可能不会退出pygame,因为它给了我错误。我尝试过一些库(比如pyaudio或pygame)但是在播放之后它们都不能完全关闭音频文件。顺便说一句,我使用的是Windows。 我的主要功能是这个(使用pygame,因为我更熟悉它):
import os
import datetime
import time
import tts.sapi
import pygame
voice = tts.sapi.Sapi()
directory_uncom=os.getcwd()
if not "speech" in directory_uncom:
directory=directory_uncom+"/speech"
else:
directory=directory_uncom
def speak(say):
global directory
global voice
commands_read=open(directory+"/commands.txt","r")
lines3=commands_read.read().splitlines()
lines3[0]="stop_speaking=false"
commands_write=open(directory+"/commands.txt","w")
commands_write.write(lines3[0])
for i in lines3[1:]:
commands_write.write("\n"+i)
commands_write.close()
stop=lines3[0][14:]
voice.create_recording("say.wav", say)
pygame.mixer.init(22000)
pygame.mixer.music.load("say.wav")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True and stop=="false":
commands_read=open(directory+"/commands.txt","r")
lines3=commands_read.read().splitlines()
stop=lines3[0][14:]
pygame.quit()
os.remove("say.wav")
speak("hello") #In this one, it does everything correctly.
speak("hello") #In this one, it gives the error.
我做错了什么?或者有人能告诉我更好的方法吗?
提前致谢。
编辑 - >我发现了另一种选择"这是以下内容:
voice.create_recording("say.wav", say)
with open("say.wav") as say_wav_read:
say_wav= mmap.mmap(say_wav_read.fileno(), 0, access=mmap.ACCESS_READ)
pygame.mixer.init(22000)
pygame.mixer.music.load(say_wav)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True and stop=="false":
commands_read=open(directory+"/commands.txt","r")
lines3=commands_read.read().splitlines()
stop=lines3[0][14:]
pygame.quit()
say_wav_read.close()
现在它可以覆盖文件(不再需要os.remove(),因为pygame只需要关闭文件而我不需要删除它 - 它只是被覆盖了),但是有一个问题:它被卡住并循环句子的相同部分(例如:你好,你好吗?> ow是y / ow是y / ow是y / ...)。有什么方法可以解决这个问题吗?
第一个"替代"如果没有os.remove(),则会出现此错误:_ctypes.COMError:( - 2147287038,无,(无,无,无,0,无))。可能是因为文件仍然打开(pygame)。所以os.remove()根本就没有必要。更好的选择?
答案 0 :(得分:0)
最后我发现了一种类似于我发布的第一种方式。如果OP想要播放的声音不能作为声音而不是音乐播放,我会从某个问题的评论中读到一个问题。我在Pygame文档中搜索了一个名为Sound的模块(顺便说一下,它只适用于OGG和未压缩的WAV文件)。我使用它,现在它成功关闭文件(不知道为什么)并且它不会循环播放所说的内容。在文档中,他们说音乐是流式传输的,并且从未一次性加载。我注意到,当我命令程序停止说话时,错误开始了(可能是腐败,我不知道),所以我认为这是导致循环的问题。它没有关闭的原因,我不知道,但它现在关闭,没有循环,所以现在它工作得很好!最终的代码是:
import os
import datetime
import time
import tts.sapi
import pygame
voice = tts.sapi.Sapi()
directory_uncom=os.getcwd()
if not "speech" in directory_uncom:
directory=directory_uncom+"/speech"
else:
directory=directory_uncom
def speak(say):
global directory
global voice
commands_read=open(directory+"/commands.txt","r")
lines3=commands_read.read().splitlines()
lines3[0]="stop_speaking=false"
commands_write=open(directory+"/commands.txt","w")
commands_write.write(lines3[0])
for i in lines3[1:]:
commands_write.write("\n"+i)
commands_write.close()
stop=lines3[0][14:]
voice.create_recording("say.wav", say)
pygame.mixer.init(22000)
sound=pygame.mixer.Sound("say.wav")
sound.play()
while pygame.mixer.get_busy() == True and stop=="false":
commands_read=open(directory+"/commands.txt","r")
lines3=commands_read.read().splitlines()
stop=lines3[0][14:]
else:
sound.stop()
pygame.quit()