audio_recorder.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # -*- coding:utf-8 -*-
  2. from ssat_sdk.sat_environment import *
  3. from ssat_sdk.utils import LoggingUtil
  4. import os, sys, time
  5. import pyaudio
  6. import wave
  7. import threading
  8. import Queue
  9. READ_BUF_TIME = 0.02 #每帧长度20ms
  10. TAG = "audio_recorder"
  11. class ARecorder():
  12. def __init__(self, CHANNELS=2,RATE=44100,WIDTH=2):
  13. self.pyaudio = None
  14. self.pyStream = None
  15. self.saveWav = False
  16. self.RecordStatus = 0#0停止录制,1正在录制
  17. self.recordLock = threading.Condition()
  18. self.waveStatus = 0#0录制文件停止,1正在录制文件
  19. self.waveFile = ""
  20. self.frameQue = Queue.Queue()#存储录制的音频帧
  21. self.frameBufMax = 0 #每次录取的Buffer采集次数,也就是frameQue会存数据的次数。做到音频长度精准控制
  22. '''Record param
  23. 44.1KHZ,16bit;96khz,24bit;192Khz,32bit
  24. '''
  25. self.CHANNELS = CHANNELS
  26. self.RATE = RATE
  27. self.WIDTH = WIDTH # 采样时的字节宽度。2代表16bit
  28. self.FORMAT = pyaudio.get_format_from_width(WIDTH)
  29. # RATE = 192000
  30. # FORMAT = pyaudio.paInt32
  31. '''
  32. 查询录音设备状态
  33. True:正常,False:异常
  34. '''
  35. def getStatus(self):
  36. pa = pyaudio.PyAudio()
  37. devInfo = pa.get_default_input_device_info()
  38. print "getDeviceStatus,",devInfo
  39. if devInfo is None or len(devInfo) < 1:
  40. return False
  41. else:
  42. return True
  43. '''
  44. 录制wave文件,可以设定录制的时间,单位s。
  45. '''
  46. def recordWave(self, filePath, time, channels = 2):
  47. print "Recording wave..."
  48. self.pyaudio = pyaudio.PyAudio()
  49. self.pyStream = self.pyaudio.open(format=self.FORMAT,
  50. channels=channels,
  51. rate=self.RATE,
  52. input=True,
  53. output=False,
  54. frames_per_buffer=self.CHUNK*channels)
  55. print("* recording")
  56. frames = []
  57. for i in range(0, int(self.RATE / self.CHUNK * time)):
  58. data = self.pyStream.read(self.CHUNK)
  59. frames.append(data)
  60. print("* done")
  61. self.pyStream.stop_stream()
  62. self.pyStream.close()
  63. self.pyaudio.terminate()
  64. wf = wave.open(filePath, 'wb')
  65. wf.setnchannels(channels)
  66. wf.setsampwidth(self.WIDTH)
  67. wf.setframerate(self.RATE)
  68. wf.writeframes(b''.join(frames))
  69. wf.close()
  70. def monitor(self,timeL,saveWave = False, waveFile=None, buf_time=None):
  71. self.recordLock.acquire()
  72. if waveFile is not None:
  73. self.waveFile = waveFile
  74. else:
  75. self.waveFile = None
  76. if buf_time is None:
  77. # 每次读取的帧数。人耳最低分辨频率20Hz,所以每次抓取0.02秒的数据。方便计算短时能。
  78. self.CHUNK = int(self.RATE * READ_BUF_TIME)
  79. else:
  80. self.CHUNK = int(self.RATE * buf_time)
  81. self.frameBufMax = timeL * (self.RATE/self.CHUNK)
  82. self.frameBufDel = 1*(self.RATE/self.CHUNK) #前1秒录取的音频,需要删掉,采集的音频不准。
  83. tryMax = 6
  84. audioEnable = False
  85. while tryMax > 0:#在音频设备启动失败时,尝试6次,每次间隔0.5秒
  86. tryMax -= 1
  87. try:
  88. self.pyaudio = pyaudio.PyAudio()
  89. LoggingUtil.printLog(TAG,self.pyaudio.get_default_input_device_info())
  90. self.pyStream = self.pyaudio.open(rate=self.RATE,
  91. channels=self.CHANNELS,
  92. format=self.FORMAT,
  93. input=True,
  94. frames_per_buffer=self.CHUNK,
  95. stream_callback=self.streamCallBack)
  96. LoggingUtil.printLog("AudioRecorder monitor, device init success!")
  97. audioEnable = True
  98. break
  99. except Exception,e:
  100. audioEnable = False
  101. LoggingUtil.printLog("AudioRecorder monitor, Error:"+e.message)
  102. if self.pyStream is not None:
  103. self.pyStream.close()
  104. self.pyStream = None
  105. if self.pyaudio is not None:
  106. self.pyaudio.terminate()
  107. self.pyaudio = None
  108. time.sleep(0.5)
  109. if audioEnable is False:
  110. return
  111. self.initRecordStatus(saveWave)
  112. LoggingUtil.printLog("Record sound....")
  113. self.pyStream.start_stream()
  114. self.recordLock.wait() #等待录音结束
  115. self.recordLock.release()
  116. LoggingUtil.printLog("Record sound End")
  117. def streamCallBack(self, in_data,frame_count,time_info,status_flags):
  118. # print "streamCallBack.Thread:", threading.currentThread().getName()
  119. # print "Recording.streamCallBack:frame_count:",frame_count,";time_info:",time_info,";status_flags:",status_flags
  120. self.frameBufDel = self.frameBufDel - 1
  121. #舍弃前1秒钟的音频内容
  122. if self.frameBufDel > 0:
  123. return (None, pyaudio.paContinue)
  124. self.frameBufMax = self.frameBufMax - 1
  125. self.frameQue.put_nowait(in_data)
  126. if self.saveWav is True:
  127. self.saveWavFrame(in_data)
  128. if self.frameBufMax <= 0:
  129. self.closeRecord()
  130. return (None, pyaudio.paComplete)
  131. else:
  132. return (None, pyaudio.paContinue)
  133. def initRecordStatus(self,saveWave):
  134. self.RecordStatus = 1
  135. self.saveWav = saveWave
  136. if self.saveWav is True:
  137. self.initWavSave()
  138. def closeRecord(self):
  139. self.RecordStatus = 0
  140. self.recordLock.acquire()
  141. self.recordLock.notify()
  142. self.recordLock.release()
  143. # self.pyStream.stop_stream()
  144. self.pyStream.close()
  145. self.pyaudio.terminate()
  146. if self.saveWav is True:
  147. self.closeWavSave()
  148. def initWavSave(self):
  149. if self.waveFile is None:
  150. self.waveFile = os.path.join(getSATTmpDIR(), "monitorSound" + str(time.time()) + ".wav")
  151. print "SoundTool, initWaveSave,audioRecord:", self.waveFile
  152. try:
  153. self.wf = wave.open(self.waveFile, 'wb')
  154. self.wf.setnchannels(self.CHANNELS)
  155. self.wf.setsampwidth(self.WIDTH)
  156. self.wf.setframerate(self.RATE)
  157. self.waveStatus = 1
  158. return self.waveFile
  159. except Exception,e:
  160. LoggingUtil.printLog(TAG, "initWavSave.Audio Recorder File Open Fail!")
  161. def saveWavFrame(self, frame):
  162. # print "saveWavFrame,frame:",frame
  163. try:
  164. self.wf.writeframes(frame)
  165. except Exception,e:
  166. LoggingUtil.printLog(TAG, "saveWavFrame.Audio Recorder wave not exits!")
  167. def closeWavSave(self):
  168. try:
  169. self.wf.close()
  170. self.wf = None
  171. self.waveStatus = 0
  172. except Exception,e:
  173. LoggingUtil.printLog(TAG, "closeWavSave.Audio Recorder wave not exits!")
  174. # print "closeWavSave.Audio Recorder wave not exits!", e
  175. def getWavFile(self):
  176. if self.saveWav is True:
  177. return self.waveFile
  178. else:
  179. return None
  180. def getFrameQue(self):
  181. return self.frameQue
  182. if __name__ == "__main__":
  183. recorder = ARecorder()
  184. # recorder.recordWave("test1.wav",5)
  185. recorder.monitor(3,True)
  186. # print 11111
  187. # recorder.monitor(3,True)
  188. # print 22222
  189. # recorder.monitor(3,True)
  190. # print 33333