【问题标题】:Python - audio file not being closed -> os.remove()Python - 音频文件未关闭 -> os.remove()
【发布时间】:2017-12-19 13:55:13
【问题描述】:

我正在尝试使用来自 Github(来自 DeepHorizo​​ns)的 tts 模块制作一个具有文本到语音功能的程序。因为我希望能够在程序说话时停止程序,所以我将音频录制到文件中然后播放。为了能够多次创建同名文件(比如.wav),我需要删除旧的。问题是我无法删除它,因为它正在被使用(PermissionError: [WinError 32] The process cannot access the file because it is being used by another process),但它只发生在它第二次说话时——第一次时间,它退出 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 are y / ow are y / ow are y / ...)。有什么办法可以解决这个问题?

使用第一个“替代”并且没有 os.remove(),它会给出以下错误:_ctypes.COMError: (-2147287038, None, (None, None, None, 0, None))。可能是因为文件仍处于打开状态(pygame)。所以 os.remove() 根本没有必要。更好的选择?

【问题讨论】:

  • 按这个顺序(用那些命令),它仍然只第一次起作用,第二次,它不能删除它。 pygame.mixer.music.stop() pygame.mixer.stop() pygame.mixer.quit() pygame.quit()
  • 此文件由voice.create_recording co 创建,可能需要类似于voice.close()的内容
  • 我试过不播放文件(只是创建它然后删除它),它工作得很好。问题似乎出在我播放文件时。它仍然是第二次打开(我不知道为什么)然后脚本无法删除它。
  • 我找到了一种使用 with 语句关闭文件的方法:with open("say.wav") as say_wav_read: say_wav= mmap.mmap(say_wav_read.fileno(), 0, access=mmap. ACCESS_READ) 然后 pygame 加载并播放文件。最后: pygame.quit() say_wav.close() os.remove("say.wav") 可以,但是有一个问题,就是有时候会卡住,循环句子的同一部分(例如:你好,你好吗 -> 你好/你好/你好/你好/ ...)永远。可能不应该……你知道为什么会这样吗?或者也许是更好的选择?

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


【解决方案1】:

最后我找到了一种类似于我发布的第一个方法。如果 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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    相关资源
    最近更新 更多