@ -86,7 +86,6 @@ def DeviceListGet():
return l_result
return l_result
class Recorder :
class Recorder :
mT = [ ]
mStatusStr = " 0_READY " # "0_READY", "1_RECORDING"
mStatusStr = " 0_READY " # "0_READY", "1_RECORDING"
mAudio = None
mAudio = None
mCaptureThread = None
mCaptureThread = None
@ -106,8 +105,9 @@ class Recorder:
mFileAvailableChunkInt = None
mFileAvailableChunkInt = None
mFileNameList = None
mFileNameList = None
mFileInfoDict = None # {"file.mp3":{StartSecFloat:, EndSecFloat:, Extra:,PathStr, }}
mChunkSecFloat = None
mChunkSecFloat = None
mChunkSilentSecFloat = None
mStartSecFloat = None
mStartSecFloat = None
mStartChunkSecFloat = None
mStartChunkSecFloat = None
@ -119,6 +119,16 @@ class Recorder:
mIsMicrophoneBool = None
mIsMicrophoneBool = None
def __init__ ( self , inDeviceInt = None ) :
def __init__ ( self , inDeviceInt = None ) :
""" L-,W+: Инициализация экземпляра класса записи звука
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
: param inDeviceInt : , по умолчанию None ( использование устройства , полученного от DeviceSystemSoundIndex ( ) )
: type inDeviceInt : int , опционально
"""
self . mDeviceInt = inDeviceInt
self . mDeviceInt = inDeviceInt
if inDeviceInt == None : inDeviceInt = DeviceSystemSoundIndex ( )
if inDeviceInt == None : inDeviceInt = DeviceSystemSoundIndex ( )
self . mDeviceInt = inDeviceInt
self . mDeviceInt = inDeviceInt
@ -126,17 +136,46 @@ class Recorder:
else : self . mIsMicrophoneBool = False
else : self . mIsMicrophoneBool = False
def StatusGet ( self ) :
def StatusGet ( self ) :
""" L-,W+: Вернуть статус записи звука
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . StatusGet ( )
: return : " 0_READY " или " 1_RECORDING "
: rtype : str
"""
return self . mStatusStr
return self . mStatusStr
def CaptureStart ( self , inFolderPathStr = " " , inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 300.0 , inChunkSilentSecFloat = 10.0 ) :
def CaptureStart ( self , inFolderPathStr = " " , inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 300.0 ) :
""" L-,W+: Начать запись звука
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureStop ( )
: param inFolderPathStr : Путь к папке , в которую сохранять аудиофайлы захвата , по умолчанию " "
: type inFolderPathStr : str , опционально
: param inFileNameStr : Наименование файла без расширения , по умолчанию " out "
: type inFileNameStr : str , опционально
: param inFileFormatStr : Наименование формата , в который будет происходить сохранение ( " mp3 " или " wav " или " raw " или " aif " ) , по умолчанию " mp3 "
: type inFileFormatStr : str , опционально
: param inDurationSecFloat : Длительность захвата аудио , по умолчанию None ( пока не поступит команда CaptureStop ( ) )
: type inDurationSecFloat : float , опционально
: param inChunkSecFloat : Максимальная длина части аудиофайла , по умолчанию 300.0
: type inChunkSecFloat : float , опционально
"""
# CHECK AUX.mp3
# CHECK AUX.mp3
self . mFileInfoDict = { }
self . mFileNameList = [ ]
self . mFileNameList = [ ]
self . mRecordedFramesList = [ ]
self . mRecordedFramesList = [ ]
self . mStatusStr = " 1_RECORDING "
self . mStatusStr = " 1_RECORDING "
if inChunkSecFloat != None or inChunkSilentSecFloat != None : self . mFileAvailableChunkInt = 0
if inChunkSecFloat != None : self . mFileAvailableChunkInt = 0
self . mDurationSecFloat = inDurationSecFloat
self . mDurationSecFloat = inDurationSecFloat
self . mChunkSecFloat = inChunkSecFloat
self . mChunkSecFloat = inChunkSecFloat
self . mChunkSilentSecFloat = inChunkSilentSecFloat
self . mSilentLastCheckTimeFloat = time . time ( )
self . mSilentLastCheckTimeFloat = time . time ( )
self . mFolderPathStr = inFolderPathStr
self . mFolderPathStr = inFolderPathStr
self . mFileNameStr = inFileNameStr
self . mFileNameStr = inFileNameStr
@ -164,21 +203,60 @@ class Recorder:
self . mRecordedFramesList . append ( self . mStream . read ( self . mFramesInt ) )
self . mRecordedFramesList . append ( self . mStream . read ( self . mFramesInt ) )
self . __TriggerCheck__ ( )
self . __TriggerCheck__ ( )
def CaptureStop ( self , inWaitStream = True ) :
def CaptureWait ( self ) :
""" L-,W+: Ожидать окончания захвата аудио
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = 10.0 , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureWait ( )
"""
self . mCaptureThread . join ( )
def CaptureStop ( self , inWaitStream = True , inExtra = None ) :
""" L-,W+: Остановить захват аудио
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureStop ( )
: param inWaitStream : True - выполнить ожидание окончания потока захвата перед окончанием , по умолчанию True
: type inWaitStream : bool , опционально
: param inExtra : Дополнительный контент , необходимый для идентификации файла . В дальнейшем получить структуру можно с помощью функции FileInfoGet ( ) [ ' Extra ' ] , по умолчанию None
: type inExtra : any , опционально
"""
self . mCaptureBool = False
self . mCaptureBool = False
if inWaitStream == True : self . mCaptureThread . join ( )
if inWaitStream == True : self . mCaptureThread . join ( )
self . mStream . stop_stream ( )
self . mStream . stop_stream ( )
self . mStream . close ( )
self . mStream . close ( )
#Close module
#Close module
self . mAudio . terminate ( )
self . mAudio . terminate ( )
self . CaptureChunk ( )
self . CaptureChunk ( inExtra = inExtra , inForceChunkBool = False )
self . mStatusStr = " 0_READY "
self . mStatusStr = " 0_READY "
def CaptureChunk ( self ) :
def CaptureChunk ( self , inExtra = None , inForceChunkBool = True ) :
""" L-,W+: Зафиксировать захват аудио в виде промежуточного файла вида: <имя файла>_00000.mp3
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureChunk ( )
: param inExtra : Дополнительный контент , необходимый для идентификации файла . В дальнейшем получить структуру можно с помощью функции FileInfoGet ( ) [ ' Extra ' ] , по умолчанию None
: type inExtra : any , опционально
: param inForceChunkBool : True - вне зависимости от текущего режима перейти на режим сохранения по частям , по умолчанию True
: type inForceChunkBool : bool , опционально
"""
if inForceChunkBool == True and self . mFileAvailableChunkInt == None : self . mFileAvailableChunkInt = 0
lFileNameStr = self . mFileNameStr
lFileNameStr = self . mFileNameStr
if self . mFileAvailableChunkInt != None :
if self . mFileAvailableChunkInt != None :
lFileNameStr + = f " _ { self . mFileAvailableChunkInt : 05 } "
lFileNameStr + = f " _ { self . mFileAvailableChunkInt : 05 } "
self . mFileAvailableChunkInt = self . mFileAvailableChunkInt + 1
self . mFileAvailableChunkInt = self . mFileAvailableChunkInt + 1
lFilePathStr = os . path . abspath ( os . path . join ( self . mFolderPathStr , f " { lFileNameStr } . { self . mFileFormatStr } " ) )
# Advanced usage, if you have raw audio data:
# Advanced usage, if you have raw audio data:
sound = AudioSegment (
sound = AudioSegment (
# raw audio data (bytes)
# raw audio data (bytes)
@ -190,37 +268,86 @@ class Recorder:
# stereo
# stereo
channels = self . mChannelCountInt
channels = self . mChannelCountInt
)
)
sound . export ( os . path . join ( self . mFolderPathStr , f " { lFileNameStr } . { self . mFileFormatStr } " ) , format = f " { self . mFileFormatStr } " )
self . mFileNameList . append ( f " { lFileNameStr } . { self . mFileFormatStr } " )
self . mRecordedFramesList = [ ]
self . mRecordedFramesList = [ ]
self . mStartChunkSecFloat = time . time ( )
lTimeSecFloat = time . time ( )
sound . export ( lFilePathStr , format = f " { self . mFileFormatStr } " )
self . mFileNameList . append ( f " { lFileNameStr } . { self . mFileFormatStr } " )
self . mFileInfoDict [ f " { lFileNameStr } . { self . mFileFormatStr } " ] = {
" StartSecFloat " : self . mStartChunkSecFloat ,
" EndSecFloat " : lTimeSecFloat ,
" Extra " : inExtra ,
" PathStr " : lFilePathStr
}
self . mStartChunkSecFloat = lTimeSecFloat
def FileInfoGet ( self , inFileNameStr = None ) :
""" L-,W+: Вернуть информацию по аудиофайлу inFileNameStr. Если inFileNameStr == None -> Функция вернет информацию по последнему записанному файлу
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureChunk ( )
lFileInfoDict = lRec . FileInfoGet ( )
: param inFileNameStr : Наименование аудиофайла с указанием расширения , по умолчанию None ( взять последний записанный файл )
: type inFileNameStr : str , опционально
: return : { StartSecFloat : , EndSecFloat : , Extra : , PathStr : , } или None
: rtype : dict
"""
if inFileNameStr == None : inFileNameStr = self . FileLastGet ( )
return self . mFileInfoDict . get ( inFileNameStr , None )
def FileListGet ( self ) :
def FileListGet ( self ) :
""" L-,W+: Вернуть список сохраненных аудиофайлов (наименования)
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureChunk ( )
lRec . CaptureChunk ( )
lRec . FileListGet ( )
: return : [ " out_00000.mp3 " , " out_00001.mp3 " , . . . ]
: rtype : list
"""
return self . mFileNameList
return self . mFileNameList
def FileLastGet ( self ) :
def FileLastGet ( self ) :
""" L-,W+: Вернуть наименование последнего сохраненного аудиофайла
. . code - block : : python
from pyOpenRPA . Robot import Audio
lRec = Audio . Recorder ( )
lRec . CaptureStart ( inFileNameStr = " out " , inFileFormatStr = " mp3 " , inDurationSecFloat = None , inChunkSecFloat = 5.0 , inChunkSilentSecFloat = 10.0 )
lRec . CaptureChunk ( )
lRec . CaptureChunk ( )
lRec . FileListGet ( )
: return : [ " out_00000.mp3 " , " out_00001.mp3 " , . . . ]
: rtype : list
"""
return self . mFileNameList [ - 1 ]
return self . mFileNameList [ - 1 ]
def __Callback__ ( self , inDefList ) :
def __Callback__ ( self , inDefList ) :
pass
pass
def __CallbackIsSilent__ ( self ) :
pass
def __CallbackIsChunked__ ( self ) :
def __CallbackIsChunked__ ( self ) :
pass
pass
def __CallbackIsStopped__ ( self ) :
def __CallbackIsStopped__ ( self ) :
pass
pass
def IsSilent ( self , inLastSecFloat = None ) :
#def IsSilent(self, inLastSecFloat=None) :
" Returns ' True ' if below the ' silent ' threshold "
# "Returns 'True' if below the 'silent' threshold"
self . mSilentLastCheckTimeFloat = time . time ( )
# self.mSilentLastCheckTimeFloat = time.time()
if inLastSecFloat == None : inLastSecFloat = self . mChunkSilentSecFloat
# if inLastSecFloat == None: inLastSecFloat = self.mChunkSilentSecFloat
lFrameLenInt = int ( self . mSampleSizeInt * inLastSecFloat )
# lFrameLenInt = int(self.mSampleSizeInt*inLastSecFloat)
if lFrameLenInt < len ( self . mRecordedFramesList ) : lData = self . mRecordedFramesList [ - lFrameLenInt : ]
# if lFrameLenInt<len(self.mRecordedFramesList): lData = self.mRecordedFramesList[-lFrameLenInt:]
else : lData = self . mRecordedFramesList
# else: lData = self.mRecordedFramesList
return max ( lData ) < self . mThresholdInt
# return max(lData) < self.mThresholdInt
def __TriggerCheck__ ( self ) :
def __TriggerCheck__ ( self ) :
""" L-,W+: Контроль записи / остановки аудио по следующим критериям:
""" Контроль записи / остановки аудио по следующим критериям:
- Общая длительность ,
- Общая длительность ,
- Максимальная длительность части ,
- Максимальная длительность части ,
- Максимальная длит тишины ( часть ) ,
- Максимальная длит тишины ( часть ) ,