Spaces:
Runtime error
Runtime error
#!/usr/bin/env rye run python | |
import asyncio | |
import time | |
from pathlib import Path | |
import pyaudio | |
from openai import AsyncOpenAI | |
# Initialize async client | |
openai = AsyncOpenAI(base_url="http://localhost:8880/v1", api_key="not-needed-for-local") | |
# Create a shared PyAudio instance | |
p = pyaudio.PyAudio() | |
async def stream_to_speakers(text: str, stream_id: int) -> None: | |
"""Stream TTS audio to speakers asynchronously""" | |
player_stream = p.open( | |
format=pyaudio.paInt16, | |
channels=1, | |
rate=24000, | |
output=True | |
) | |
start_time = time.time() | |
print(f"Starting stream {stream_id}") | |
try: | |
async with openai.audio.speech.with_streaming_response.create( | |
model="kokoro", | |
voice="af_bella", | |
response_format="pcm", | |
input=text | |
) as response: | |
print(f"Stream {stream_id} - Time to first byte: {int((time.time() - start_time) * 1000)}ms") | |
async for chunk in response.iter_bytes(chunk_size=1024): | |
player_stream.write(chunk) | |
# Small sleep to allow other coroutines to run | |
await asyncio.sleep(0.001) | |
print(f"Stream {stream_id} completed in {int((time.time() - start_time) * 1000)}ms") | |
finally: | |
player_stream.stop_stream() | |
player_stream.close() | |
async def save_to_file(text: str, file_id: int) -> None: | |
"""Save TTS output to file asynchronously""" | |
speech_file_path = Path(__file__).parent / f"speech_{file_id}.mp3" | |
async with openai.audio.speech.with_streaming_response.create( | |
model="kokoro", | |
voice="af_bella", | |
input=text | |
) as response: | |
# Open file in binary write mode | |
with open(speech_file_path, 'wb') as f: | |
async for chunk in response.iter_bytes(): | |
f.write(chunk) | |
print(f"File {file_id} saved to {speech_file_path}") | |
async def main() -> None: | |
# Different text samples for variety | |
texts = [ | |
"The quick brown fox jumped over the lazy dogs. I see skies of blue and clouds of white", | |
"I see skies of blue and clouds of white. I see skies of blue and clouds of white", | |
] | |
# Create tasks for streaming to speakers | |
speaker_tasks = [ | |
stream_to_speakers(text, i) | |
for i, text in enumerate(texts) | |
] | |
# Create tasks for saving to files | |
file_tasks = [ | |
save_to_file(text, i) | |
for i, text in enumerate(texts) | |
] | |
# Combine all tasks | |
all_tasks = speaker_tasks + file_tasks | |
# Run all tasks concurrently | |
try: | |
await asyncio.gather(*all_tasks) | |
finally: | |
# Clean up PyAudio | |
p.terminate() | |
if __name__ == "__main__": | |
asyncio.run(main()) |