import openai from openai import OpenAI import pyaudio import wave import threading from dotenv import load_dotenv import os # Load environment variables from .env file load_dotenv() # Set up your OpenAI API key from the environment variable client = OpenAI(api_key=os.getenv('OPENAI_API_KEY')) def list_audio_devices(): p = pyaudio.PyAudio() print("Available audio devices:") info = p.get_host_api_info_by_index(0) num_devices = info.get('deviceCount') # List all available devices, and mark output devices for i in range(0, num_devices): if p.get_device_info_by_index(i).get('maxOutputChannels') > 0: print(f"Device index {i}: {p.get_device_info_by_index(i).get('name')}") p.terminate() def play_saved_audio(file_path, device_index=None): # Open the saved audio file wf = wave.open(file_path, 'rb') print(f"Playing audio to device {device_index}") # Setup PyAudio p = pyaudio.PyAudio() try: stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True, output_device_index=device_index) data = wf.readframes(1024) while data: stream.write(data) data = wf.readframes(1024) except Exception as e: print(f"Error playing audio on device {device_index}: {e}") finally: stream.stop_stream() stream.close() wf.close() p.terminate() #Plays to multiple device indexes at the same time def play_audio_multiplexed(file_paths, device_indices): p = pyaudio.PyAudio() streams = [] # Open all files and start all streams for file_path, device_index in zip(file_paths, device_indices): wf = wave.open(file_path, 'rb') stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True, output_device_index=device_index) streams.append((stream, wf)) # Play interleaved active_streams = len(streams) while active_streams > 0: for stream, wf in streams: data = wf.readframes(1024) if data: stream.write(data) else: stream.stop_stream() stream.close() wf.close() active_streams -= 1 p.terminate() def stream_audio_to_virtual_mic(text, voice="fable", device_index=None, device_index_2=None): response = client.audio.speech.create( model="tts-1", voice=voice, input=text, response_format='wav' ) #This can either stream to one device index at a time, or, via multiplexing #it can stream to two similtaneously to prevent lag playing in sequence if device_index_2 is not None: file_path_1 = "output1.wav" file_path_2 = "output2.wav" response.stream_to_file(file_path_1) response.stream_to_file(file_path_2) play_audio_multiplexed([file_path_1, file_path_2], [device_index, device_index_2]) else: file_path_1 = "output1.wav" response.stream_to_file(file_path_1) play_saved_audio(file_path_1, device_index) return ""; if __name__ == "__main__": import sys arglen = len(sys.argv) if arglen < 2: print("Usage: python script.py 'text to convert'") sys.exit(1) print(f"arg count {arglen}") if arglen == 4: device_index = int(sys.argv[2]) device_index_2 = int(sys.argv[3]) elif arglen == 3: device_index = int(sys.argv[2]) device_index_2 = None else: list_audio_devices() device_index = int(input("Enter the device index: ")) device_index_2 = None stream_audio_to_virtual_mic(sys.argv[1], voice="fable", device_index=device_index,device_index_2=device_index_2)