audio_output.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import pyaudio
  2. import wave
  3. import os
  4. defaultframes = 512
  5. class textcolors:
  6. if not os.name == 'nt':
  7. blue = '\033[94m'
  8. green = '\033[92m'
  9. warning = '\033[93m'
  10. fail = '\033[91m'
  11. end = '\033[0m'
  12. else:
  13. blue = ''
  14. green = ''
  15. warning = ''
  16. fail = ''
  17. end = ''
  18. recorded_frames = []
  19. device_info = {}
  20. useloopback = False
  21. recordtime = 5
  22. #Use module
  23. p = pyaudio.PyAudio()
  24. #Set default to first in list or ask Windows
  25. try:
  26. default_device_index = p.get_default_input_device_info()
  27. except IOError:
  28. default_device_index = -1
  29. #Select Device
  30. print (textcolors.blue + "Available devices:\n" + textcolors.end)
  31. for i in range(0, p.get_device_count()):
  32. info = p.get_device_info_by_index(i)
  33. print (textcolors.green + str(info["index"]) + textcolors.end + ": \t %s \n \t %s \n" % (info["name"], p.get_host_api_info_by_index(info["hostApi"])["name"]))
  34. if default_device_index == -1:
  35. default_device_index = info["index"]
  36. #Handle no devices available
  37. if default_device_index == -1:
  38. print (textcolors.fail + "No device available. Quitting." + textcolors.end)
  39. exit()
  40. #Get input or default
  41. device_id = int(input("Choose device [" + textcolors.blue + str(default_device_index) + textcolors.end + "]: ") or default_device_index)
  42. print ("")
  43. #Get device info
  44. try:
  45. device_info = p.get_device_info_by_index(device_id)
  46. except IOError:
  47. device_info = p.get_device_info_by_index(default_device_index)
  48. print (textcolors.warning + "Selection not available, using default." + textcolors.end)
  49. #Choose between loopback or standard mode
  50. is_input = device_info["maxInputChannels"] > 0
  51. is_wasapi = (p.get_host_api_info_by_index(device_info["hostApi"])["name"]).find("WASAPI") != -1
  52. if is_input:
  53. print (textcolors.blue + "Selection is input using standard mode.\n" + textcolors.end)
  54. else:
  55. if is_wasapi:
  56. useloopback = True;
  57. print (textcolors.green + "Selection is output. Using loopback mode.\n" + textcolors.end)
  58. else:
  59. print (textcolors.fail + "Selection is input and does not support loopback mode. Quitting.\n" + textcolors.end)
  60. exit()
  61. recordtime = int(input("Record time in seconds [" + textcolors.blue + str(recordtime) + textcolors.end + "]: ") or recordtime)
  62. #Open stream
  63. channelcount = device_info["maxInputChannels"] if (device_info["maxOutputChannels"] < device_info["maxInputChannels"]) else device_info["maxOutputChannels"]
  64. stream = p.open(format = pyaudio.paInt16,
  65. channels = channelcount,
  66. rate = int(device_info["defaultSampleRate"]),
  67. input = True,
  68. frames_per_buffer = defaultframes,
  69. input_device_index = device_info["index"],
  70. as_loopback = useloopback)
  71. #Start Recording
  72. print (textcolors.blue + "Starting..." + textcolors.end)
  73. for i in range(0, int(int(device_info["defaultSampleRate"]) / defaultframes * recordtime)):
  74. recorded_frames.append(stream.read(defaultframes))
  75. print (".")
  76. print (textcolors.blue + "End." + textcolors.end)
  77. #Stop Recording
  78. stream.stop_stream()
  79. stream.close()
  80. #Close module
  81. p.terminate()
  82. filename = input("Save as [" + textcolors.blue + "out.wav" + textcolors.end + "]: ") or "out.wav"
  83. waveFile = wave.open(filename, 'wb')
  84. waveFile.setnchannels(channelcount)
  85. waveFile.setsampwidth(p.get_sample_size(pyaudio.paInt16))
  86. waveFile.setframerate(int(device_info["defaultSampleRate"]))
  87. waveFile.writeframes(b''.join(recorded_frames))
  88. waveFile.close()