audio_recorder.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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.recordLastTime = 0
  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. self.devName = ""
  32. def setDeviceName(self,devName):
  33. self.devName = devName
  34. '''
  35. 查找设备index。
  36. :return :None表示用默认设备,-1表示找不到指定设备,正整数表示找到的设备索引index。
  37. '''
  38. def getDeviceIndex(self):
  39. if self.devName.__len__() < 1:
  40. LoggingUtil.printLog("采用默认录音设备")
  41. return None
  42. else:
  43. pa = pyaudio.PyAudio()
  44. count = pa.get_device_count()
  45. realName = getSoundDevice(self.devName)
  46. print "getDeviceIndex,devName:%s, realName:%s"%(self.devName,realName)
  47. for index in range(count):
  48. soundDev = pa.get_device_info_by_index(index)
  49. print "getDeviceIndex,soundDev:",soundDev
  50. if soundDev.has_key("name") and soundDev["name"].find(realName) > -1:
  51. LoggingUtil.printLog("采用录音设备:"+realName)
  52. return index
  53. LoggingUtil.printLog("未找到指定录音设备")
  54. return -1
  55. '''
  56. 查询录音设备状态
  57. True:正常,False:异常
  58. '''
  59. def getStatus(self):
  60. pa = pyaudio.PyAudio()
  61. devInfo = pa.get_default_input_device_info()
  62. print "getDeviceStatus,",devInfo
  63. if devInfo is None or len(devInfo) < 1:
  64. return False
  65. else:
  66. return True
  67. '''
  68. 录制wave文件,可以设定录制的时间,单位s。
  69. '''
  70. def recordWave(self, filePath, time, channels = 2):
  71. print "recordWave,Start to record wave..."
  72. self.pyaudio = pyaudio.PyAudio()
  73. # 获取设备数量;
  74. # device_count = self.pyaudio.get_device_count()
  75. # http://people.csail.mit.edu/hubert/pyaudio/docs/
  76. devIndex = self.getDeviceIndex()
  77. if devIndex == -1:
  78. return
  79. self.pyStream = self.pyaudio.open(format=self.FORMAT,
  80. channels=channels,
  81. rate=self.RATE,
  82. input=True,
  83. output=False,
  84. frames_per_buffer=self.CHUNK*channels,
  85. input_device_index = devIndex,
  86. output_device_index = None)
  87. print("recordWave, recording")
  88. frames = []
  89. for i in range(0, int(self.RATE / self.CHUNK * time)):
  90. data = self.pyStream.read(self.CHUNK)
  91. frames.append(data)
  92. print("recordWave, done")
  93. self.pyStream.stop_stream()
  94. self.pyStream.close()
  95. self.pyaudio.terminate()
  96. wf = wave.open(filePath, 'wb')
  97. wf.setnchannels(channels)
  98. wf.setsampwidth(self.WIDTH)
  99. wf.setframerate(self.RATE)
  100. wf.writeframes(b''.join(frames))
  101. wf.close()
  102. def monitor(self,timeL,saveWave = False, waveFile=None, buf_time=None):
  103. print "audio_recorder,monitor start"
  104. if waveFile is not None:
  105. self.waveFile = waveFile
  106. else:
  107. self.waveFile = None
  108. if buf_time is None:
  109. # 每次读取的帧数。人耳最低分辨频率20Hz,所以每次抓取0.02秒的数据。方便计算短时能。
  110. self.CHUNK = int(self.RATE * READ_BUF_TIME)
  111. else:
  112. self.CHUNK = int(self.RATE * buf_time)
  113. self.frameBufMax = timeL * (self.RATE/self.CHUNK)
  114. self.frameBufDel = 1*(self.RATE/self.CHUNK) #前1秒录取的音频,需要删掉,采集的音频不准。
  115. tryMax = 6
  116. audioEnable = False
  117. while tryMax > 0:#在音频设备启动失败时,尝试6次,每次间隔0.5秒
  118. tryMax -= 1
  119. print "audio_recorder,tryMax:",tryMax
  120. try:
  121. self.pyaudio = pyaudio.PyAudio()
  122. devIndex = self.getDeviceIndex()
  123. if devIndex == -1:
  124. LoggingUtil.printLog(TAG, self.pyaudio.get_default_input_device_info())
  125. return
  126. elif devIndex is None:
  127. LoggingUtil.printLog(TAG,self.pyaudio.get_default_input_device_info())
  128. else:
  129. LoggingUtil.printLog(TAG, self.pyaudio.get_device_info_by_index(devIndex))
  130. self.pyStream = self.pyaudio.open(rate=self.RATE,
  131. channels=self.CHANNELS,
  132. format=self.FORMAT,
  133. input=True,
  134. frames_per_buffer=self.CHUNK,
  135. stream_callback=self.streamCallBack,
  136. input_device_index = devIndex)
  137. LoggingUtil.printLog("AudioRecorder monitor, device init success!")
  138. audioEnable = True
  139. break
  140. except Exception,e:
  141. audioEnable = False
  142. LoggingUtil.printLog("AudioRecorder monitor, Error:"+e.message)
  143. self.releaseRecord()
  144. self.closeRecord()
  145. time.sleep(0.5)
  146. if audioEnable is False:
  147. return
  148. self.initRecordStatus(saveWave)
  149. LoggingUtil.printLog("Record sound....")
  150. self.recordLastTime = time.time()
  151. self.pyStream.start_stream()
  152. while self.RecordStatus == 1:#等待录音结束
  153. curTime = time.time()
  154. dtime = curTime - self.recordLastTime
  155. if buf_time is None and dtime > READ_BUF_TIME * 10:
  156. self.releaseRecord()
  157. elif dtime > buf_time*10:
  158. self.releaseRecord()
  159. self.closeRecord()
  160. LoggingUtil.printLog("Record sound End")
  161. def streamCallBack(self, in_data,frame_count,time_info,status_flags):
  162. # print "streamCallBack.Thread:", threading.currentThread().getName()
  163. # print "Recording.streamCallBack:frame_count:",frame_count,";time_info:",time_info,";status_flags:",status_flags
  164. self.recordLastTime = time.time()
  165. self.frameBufDel = self.frameBufDel - 1
  166. #舍弃前1秒钟的音频内容
  167. if self.frameBufDel > 0:
  168. return (None, pyaudio.paContinue)
  169. self.frameBufMax = self.frameBufMax - 1
  170. self.frameQue.put_nowait(in_data)
  171. if self.saveWav is True:
  172. self.saveWavFrame(in_data)
  173. if self.frameBufMax <= 0:
  174. self.releaseRecord()
  175. return (None, pyaudio.paComplete)
  176. else:
  177. return (None, pyaudio.paContinue)
  178. def initRecordStatus(self,saveWave):
  179. self.RecordStatus = 1
  180. self.saveWav = saveWave
  181. if self.saveWav is True:
  182. self.initWavSave()
  183. def releaseRecord(self):
  184. print "releaseRecord"
  185. self.RecordStatus = 0
  186. def closeRecord(self):
  187. print "closeRecord"
  188. # self.pyStream.stop_stream()
  189. if self.pyStream is not None and self.pyStream.is_stopped():
  190. # print "stop pyStream"
  191. self.pyStream.stop_stream()
  192. if self.pyStream is not None:
  193. # print "close pyStream"
  194. self.pyStream.close()
  195. self.pyStream = None
  196. if self.pyaudio is not None:
  197. # print "close pyaudio"
  198. self.pyaudio.terminate()
  199. self.pyaudio = None
  200. if self.saveWav is True:
  201. self.closeWavSave()
  202. def initWavSave(self):
  203. if self.waveFile is None:
  204. self.waveFile = os.path.join(getSATTmpDIR(), "monitorSound" + str(time.time()) + ".wav")
  205. print "SoundTool, initWaveSave,audioRecord:", self.waveFile
  206. try:
  207. self.wf = wave.open(self.waveFile, 'wb')
  208. self.wf.setnchannels(self.CHANNELS)
  209. self.wf.setsampwidth(self.WIDTH)
  210. self.wf.setframerate(self.RATE)
  211. self.waveStatus = 1
  212. return self.waveFile
  213. except Exception,e:
  214. LoggingUtil.printLog(TAG, "initWavSave.Audio Recorder File Open Fail!")
  215. def saveWavFrame(self, frame):
  216. # print "saveWavFrame,frame:",frame
  217. try:
  218. self.wf.writeframes(frame)
  219. except Exception,e:
  220. LoggingUtil.printLog(TAG, "saveWavFrame.Audio Recorder wave not exits!")
  221. def closeWavSave(self):
  222. try:
  223. print "close Wave file"
  224. self.wf.close()
  225. self.wf = None
  226. self.waveStatus = 0
  227. except Exception,e:
  228. LoggingUtil.printLog(TAG, "closeWavSave.Audio Recorder wave not exits!")
  229. # print "closeWavSave.Audio Recorder wave not exits!", e
  230. def getWavFile(self):
  231. if self.saveWav is True:
  232. return self.waveFile
  233. else:
  234. return None
  235. def getFrameQue(self):
  236. return self.frameQue
  237. if __name__ == "__main__":
  238. recorder = ARecorder()
  239. # recorder.recordWave("test1.wav",5)
  240. recorder.monitor(3,True)
  241. # print 11111
  242. # recorder.monitor(3,True)
  243. # print 22222
  244. # recorder.monitor(3,True)
  245. # print 33333