Issue
I am working on a Tkinter GUI for a text to speech project and for the voice conversion feature I want to record and play audio. My problem is that this stalls the GUI so I am trying to run this code asynchronously.
when using this function to play a .wav file and running it using asyncio the GUI still stalls then it reaches the while loop. If I replace the while loop with 'await asyncio.sleep(5)' the program doesn't stall so the function is definitely asynchronous but the loop is posing an issue.
async def PlayPreview():
global previewBar
soundName = dropLangs.get() + "-" + dropSpeakers.get() + "-" + dropModels.get() + ".wav"
soundPath = "./tts_models/" + dropLangs.get() + "/" + dropSpeakers.get() + "/" + dropModels.get() + "/" + soundName
#previewSound = wave(soundPath)
chunk = 1024
waveFile = wave.open(soundPath, 'rb')
port = pyaudio.PyAudio()
stream = port.open(format = port.get_format_from_width(waveFile.getsampwidth()),
channels = waveFile.getnchannels(),
rate = waveFile.getframerate(),
output = True)
data = waveFile.readframes(chunk)
st = stream.get_time()
frames = waveFile.getnframes()
rate = waveFile.getframerate()
length = frames/float(rate)
while len(data := waveFile.readframes(chunk)):
stream.write(data)
stream.close()
port.terminate()
print("done")
I have tried separating thew while loop into it's own async function and just awaiting it in the PlayPreview() function but that didn't make a difference.
FYI: the PlayPreview() function is called using the async-tkinter-loop package (modified to work with the customtkinter package) which essentially creates an asyncio task for it.
Solution
You need to use asyncio to wait for all other processes to run. Here is an updated version of your script:
import wave
import pyaudio
import asyncio
import threading
def play_audio():
soundName = dropLangs.get() + "-" + dropSpeakers.get() + "-" + dropModels.get() + ".wav"
soundPath = "./tts_models/" + dropLangs.get() + "/" + dropSpeakers.get() + "/" + dropModels.get() + "/" + soundName
chunk = 1024
waveFile = wave.open(soundPath, 'rb')
port = pyaudio.PyAudio()
stream = port.open(format=port.get_format_from_width(waveFile.getsampwidth()),
channels=waveFile.getnchannels(),
rate=waveFile.getframerate(),
output=True)
data = waveFile.readframes(chunk)
while len(data) > 0:
stream.write(data)
data = waveFile.readframes(chunk)
stream.close()
port.terminate()
print("done")
async def play_audio_async():
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, play_audio)
async def PlayPreview():
await play_audio_async()
print("Playback completed")
# Call PlayPreview() to start the audio playback
# Example usage with async-tkinter-loop
loop = asyncio.get_event_loop()
loop.run_until_complete(PlayPreview())
Don't forget to make sure you have the modules downloaded.
Answered By - Selim Waly
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.