123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- # -*- coding:utf-8 -*-
- from ssat_sdk.sat_environment import *
- from ssat_sdk.utils import LoggingUtil
- import os, sys, time
- import pyaudio
- import wave
- import threading
- import Queue
- READ_BUF_TIME = 0.02 #每帧长度20ms
- TAG = "audio_recorder"
- class ARecorder():
- def __init__(self, CHANNELS=2,RATE=44100,WIDTH=2):
- self.pyaudio = None
- self.pyStream = None
- self.saveWav = False
- self.RecordStatus = 0#0停止录制,1正在录制
- self.recordLock = threading.Condition()
- self.waveStatus = 0#0录制文件停止,1正在录制文件
- self.waveFile = ""
- self.frameQue = Queue.Queue()#存储录制的音频帧
- self.frameBufMax = 0 #每次录取的Buffer采集次数,也就是frameQue会存数据的次数。做到音频长度精准控制
- '''Record param
- 44.1KHZ,16bit;96khz,24bit;192Khz,32bit
- '''
- self.CHANNELS = CHANNELS
- self.RATE = RATE
- self.WIDTH = WIDTH # 采样时的字节宽度。2代表16bit
- self.FORMAT = pyaudio.get_format_from_width(WIDTH)
- # RATE = 192000
- # FORMAT = pyaudio.paInt32
- '''
- 查询录音设备状态
- True:正常,False:异常
- '''
- def getStatus(self):
- pa = pyaudio.PyAudio()
- devInfo = pa.get_default_input_device_info()
- print "getDeviceStatus,",devInfo
- if devInfo is None or len(devInfo) < 1:
- return False
- else:
- return True
- '''
- 录制wave文件,可以设定录制的时间,单位s。
- '''
- def recordWave(self, filePath, time, channels = 2):
- print "Recording wave..."
- self.pyaudio = pyaudio.PyAudio()
- self.pyStream = self.pyaudio.open(format=self.FORMAT,
- channels=channels,
- rate=self.RATE,
- input=True,
- output=False,
- frames_per_buffer=self.CHUNK*channels)
- print("* recording")
- frames = []
- for i in range(0, int(self.RATE / self.CHUNK * time)):
- data = self.pyStream.read(self.CHUNK)
- frames.append(data)
- print("* done")
- self.pyStream.stop_stream()
- self.pyStream.close()
- self.pyaudio.terminate()
- wf = wave.open(filePath, 'wb')
- wf.setnchannels(channels)
- wf.setsampwidth(self.WIDTH)
- wf.setframerate(self.RATE)
- wf.writeframes(b''.join(frames))
- wf.close()
- def monitor(self,timeL,saveWave = False, waveFile=None, buf_time=None):
- self.recordLock.acquire()
- if waveFile is not None:
- self.waveFile = waveFile
- else:
- self.waveFile = None
- if buf_time is None:
- # 每次读取的帧数。人耳最低分辨频率20Hz,所以每次抓取0.02秒的数据。方便计算短时能。
- self.CHUNK = int(self.RATE * READ_BUF_TIME)
- else:
- self.CHUNK = int(self.RATE * buf_time)
- self.frameBufMax = timeL * (self.RATE/self.CHUNK)
- self.frameBufDel = 1*(self.RATE/self.CHUNK) #前1秒录取的音频,需要删掉,采集的音频不准。
- tryMax = 6
- audioEnable = False
- while tryMax > 0:#在音频设备启动失败时,尝试6次,每次间隔0.5秒
- tryMax -= 1
- try:
- self.pyaudio = pyaudio.PyAudio()
- LoggingUtil.printLog(TAG,self.pyaudio.get_default_input_device_info())
- self.pyStream = self.pyaudio.open(rate=self.RATE,
- channels=self.CHANNELS,
- format=self.FORMAT,
- input=True,
- frames_per_buffer=self.CHUNK,
- stream_callback=self.streamCallBack)
- LoggingUtil.printLog("AudioRecorder monitor, device init success!")
- audioEnable = True
- break
- except Exception,e:
- audioEnable = False
- LoggingUtil.printLog("AudioRecorder monitor, Error:"+e.message)
- if self.pyStream is not None:
- self.pyStream.close()
- self.pyStream = None
- if self.pyaudio is not None:
- self.pyaudio.terminate()
- self.pyaudio = None
- time.sleep(0.5)
- if audioEnable is False:
- return
- self.initRecordStatus(saveWave)
- LoggingUtil.printLog("Record sound....")
- self.pyStream.start_stream()
- self.recordLock.wait() #等待录音结束
- self.recordLock.release()
- LoggingUtil.printLog("Record sound End")
- def streamCallBack(self, in_data,frame_count,time_info,status_flags):
- # print "streamCallBack.Thread:", threading.currentThread().getName()
- # print "Recording.streamCallBack:frame_count:",frame_count,";time_info:",time_info,";status_flags:",status_flags
- self.frameBufDel = self.frameBufDel - 1
- #舍弃前1秒钟的音频内容
- if self.frameBufDel > 0:
- return (None, pyaudio.paContinue)
- self.frameBufMax = self.frameBufMax - 1
- self.frameQue.put_nowait(in_data)
- if self.saveWav is True:
- self.saveWavFrame(in_data)
- if self.frameBufMax <= 0:
- self.closeRecord()
- return (None, pyaudio.paComplete)
- else:
- return (None, pyaudio.paContinue)
- def initRecordStatus(self,saveWave):
- self.RecordStatus = 1
- self.saveWav = saveWave
- if self.saveWav is True:
- self.initWavSave()
- def closeRecord(self):
- self.RecordStatus = 0
- self.recordLock.acquire()
- self.recordLock.notify()
- self.recordLock.release()
- # self.pyStream.stop_stream()
- self.pyStream.close()
- self.pyaudio.terminate()
- if self.saveWav is True:
- self.closeWavSave()
- def initWavSave(self):
- if self.waveFile is None:
- self.waveFile = os.path.join(getSATTmpDIR(), "monitorSound" + str(time.time()) + ".wav")
- print "SoundTool, initWaveSave,audioRecord:", self.waveFile
- try:
- self.wf = wave.open(self.waveFile, 'wb')
- self.wf.setnchannels(self.CHANNELS)
- self.wf.setsampwidth(self.WIDTH)
- self.wf.setframerate(self.RATE)
- self.waveStatus = 1
- return self.waveFile
- except Exception,e:
- LoggingUtil.printLog(TAG, "initWavSave.Audio Recorder File Open Fail!")
- def saveWavFrame(self, frame):
- # print "saveWavFrame,frame:",frame
- try:
- self.wf.writeframes(frame)
- except Exception,e:
- LoggingUtil.printLog(TAG, "saveWavFrame.Audio Recorder wave not exits!")
- def closeWavSave(self):
- try:
- self.wf.close()
- self.wf = None
- self.waveStatus = 0
- except Exception,e:
- LoggingUtil.printLog(TAG, "closeWavSave.Audio Recorder wave not exits!")
- # print "closeWavSave.Audio Recorder wave not exits!", e
- def getWavFile(self):
- if self.saveWav is True:
- return self.waveFile
- else:
- return None
- def getFrameQue(self):
- return self.frameQue
- if __name__ == "__main__":
- recorder = ARecorder()
- # recorder.recordWave("test1.wav",5)
- recorder.monitor(3,True)
- # print 11111
- # recorder.monitor(3,True)
- # print 22222
- # recorder.monitor(3,True)
- # print 33333
|