Python - 音频文件未关闭 - > os.remove()

时间:2017-12-19 13:55:13

标签: python python-3.x audio pygame text-to-speech

我正在尝试使用来自Github(来自DeepHorizo​​ns)的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()根本就没有必要。更好的选择?

1 个答案:

答案 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()