|
|
|
@ -7,9 +7,6 @@ import time
|
|
|
|
|
from pyOpenRPA.Utils import Text
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def DeviceMicrophoneIndex():
|
|
|
|
|
"""L-,W+: Выполнить поиск устройства, с помощью которого можно будет выполнить захват c микрофона.
|
|
|
|
|
"""
|
|
|
|
@ -115,8 +112,10 @@ class Recorder:
|
|
|
|
|
mThresholdInt = 500
|
|
|
|
|
|
|
|
|
|
mSilentLastCheckTimeFloat = None
|
|
|
|
|
|
|
|
|
|
mIsMicrophoneBool=None
|
|
|
|
|
|
|
|
|
|
mCallbackChunkDef = None
|
|
|
|
|
mCallbackStopDef = None
|
|
|
|
|
|
|
|
|
|
def __init__(self, inDeviceInt=None):
|
|
|
|
|
"""L-,W+: Инициализация экземпляра класса записи звука
|
|
|
|
@ -148,13 +147,17 @@ class Recorder:
|
|
|
|
|
"""
|
|
|
|
|
return self.mStatusStr
|
|
|
|
|
|
|
|
|
|
def CaptureStart(self, inFolderPathStr="",inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 300.0):
|
|
|
|
|
def CaptureStart(self, inFolderPathStr="",inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 300.0, inCallbackChunkDef = None, inCallbackStopDef = None):
|
|
|
|
|
"""L-,W+: Начать запись звука
|
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
|
|
def CallbackChunk(lRec, lFilenameStr):
|
|
|
|
|
pass # КОД ОБРАБОТКИ ПОСЛЕ СОХРАНЕНИЯ ЧАСТИ
|
|
|
|
|
|
|
|
|
|
from pyOpenRPA.Robot import Audio
|
|
|
|
|
lRec = Audio.Recorder()
|
|
|
|
|
lRec.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0, inChunkSilentSecFloat = 10.0)
|
|
|
|
|
lRec.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0, inCallbackChunkDef=CallbackChunk)
|
|
|
|
|
lRec.CaptureStop()
|
|
|
|
|
|
|
|
|
|
:param inFolderPathStr: Путь к папке, в которую сохранять аудиофайлы захвата , по умолчанию ""
|
|
|
|
@ -167,6 +170,10 @@ class Recorder:
|
|
|
|
|
:type inDurationSecFloat: float, опционально
|
|
|
|
|
:param inChunkSecFloat: Максимальная длина части аудиофайла, по умолчанию 300.0
|
|
|
|
|
:type inChunkSecFloat: float, опционально
|
|
|
|
|
:param inCallbackChunkDef: Функция, которая будет инициирована в случае выполнения Chunk сохранения (сохранение части). Callback функция должна принимать 2 аргумента: экземпляр класса Recorder и наименование сохраненного файла. Внимание! Функция запускается асинхронно!
|
|
|
|
|
:type inCallbackChunkDef: def, опционально
|
|
|
|
|
:param inCallbackStopDef: Функция, которая будет инициирована в случае окончания записи. Callback функция должна принимать 2 аргумента: экземпляр класса Recorder и наименование сохраненного файла. Внимание! Функция запускается асинхронно!
|
|
|
|
|
:type inCallbackStopDef: def, опционально
|
|
|
|
|
"""
|
|
|
|
|
# CHECK AUX.mp3
|
|
|
|
|
self.mFileInfoDict = {}
|
|
|
|
@ -182,6 +189,8 @@ class Recorder:
|
|
|
|
|
self.mFileFormatStr = inFileFormatStr
|
|
|
|
|
self.mAudio = pyaudio.PyAudio()
|
|
|
|
|
self.mSampleSizeInt = self.mAudio.get_sample_size(pyaudio.paInt16)
|
|
|
|
|
self.mCallbackChunkDef = inCallbackChunkDef
|
|
|
|
|
self.mCallbackStopDef = inCallbackStopDef
|
|
|
|
|
lDeviceInfoDict = self.mAudio.get_device_info_by_index(self.mDeviceInt)
|
|
|
|
|
#Open stream
|
|
|
|
|
self.mSampleRateInt = int(lDeviceInfoDict["defaultSampleRate"])
|
|
|
|
@ -209,7 +218,7 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = 10.0, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureWait()
|
|
|
|
|
"""
|
|
|
|
|
self.mCaptureThread.join()
|
|
|
|
@ -220,7 +229,7 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureStop()
|
|
|
|
|
|
|
|
|
|
:param inWaitStream: True - выполнить ожидание окончания потока захвата перед окончанием, по умолчанию True
|
|
|
|
@ -234,8 +243,12 @@ class Recorder:
|
|
|
|
|
self.mStream.close()
|
|
|
|
|
#Close module
|
|
|
|
|
self.mAudio.terminate()
|
|
|
|
|
self.CaptureChunk(inExtra=inExtra, inForceChunkBool=False)
|
|
|
|
|
lFileNameStr = self.CaptureChunk(inExtra=inExtra, inForceChunkBool=False)
|
|
|
|
|
self.mStatusStr = "0_READY"
|
|
|
|
|
if self.mCallbackStopDef != None:
|
|
|
|
|
lCallbackThread = threading.Thread(target=self.mCallbackStopDef,args=[self, lFileNameStr])
|
|
|
|
|
lCallbackThread.start()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CaptureChunk(self, inExtra=None, inForceChunkBool=True):
|
|
|
|
|
"""L-,W+: Зафиксировать захват аудио в виде промежуточного файла вида: <имя файла>_00000.mp3
|
|
|
|
@ -243,20 +256,23 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
|
|
|
|
|
:param inExtra: Дополнительный контент, необходимый для идентификации файла. В дальнейшем получить структуру можно с помощью функции FileInfoGet()['Extra'], по умолчанию None
|
|
|
|
|
:type inExtra: any, опционально
|
|
|
|
|
:param inForceChunkBool: True - вне зависимости от текущего режима перейти на режим сохранения по частям, по умолчанию True
|
|
|
|
|
:type inForceChunkBool: bool, опционально
|
|
|
|
|
:return: Наименование сохраненного аудиофайла
|
|
|
|
|
:rtype: str
|
|
|
|
|
"""
|
|
|
|
|
if inForceChunkBool==True and self.mFileAvailableChunkInt==None: self.mFileAvailableChunkInt=0
|
|
|
|
|
lFileNameStr = self.mFileNameStr
|
|
|
|
|
if self.mFileAvailableChunkInt!=None:
|
|
|
|
|
lFileNameStr+=f"_{self.mFileAvailableChunkInt:05}"
|
|
|
|
|
self.mFileAvailableChunkInt = self.mFileAvailableChunkInt + 1
|
|
|
|
|
lFilePathStr = os.path.abspath(os.path.join(self.mFolderPathStr,f"{lFileNameStr}.{self.mFileFormatStr}"))
|
|
|
|
|
lFileNameWExtStr = f"{lFileNameStr}.{self.mFileFormatStr}"
|
|
|
|
|
lFilePathStr = os.path.abspath(os.path.join(self.mFolderPathStr,lFileNameWExtStr))
|
|
|
|
|
# Advanced usage, if you have raw audio data:
|
|
|
|
|
sound = AudioSegment(
|
|
|
|
|
# raw audio data (bytes)
|
|
|
|
@ -271,14 +287,18 @@ class Recorder:
|
|
|
|
|
self.mRecordedFramesList = []
|
|
|
|
|
lTimeSecFloat = time.time()
|
|
|
|
|
sound.export(lFilePathStr, format=f"{self.mFileFormatStr}")
|
|
|
|
|
self.mFileNameList.append(f"{lFileNameStr}.{self.mFileFormatStr}")
|
|
|
|
|
self.mFileInfoDict[f"{lFileNameStr}.{self.mFileFormatStr}"]= {
|
|
|
|
|
self.mFileNameList.append(lFileNameWExtStr)
|
|
|
|
|
self.mFileInfoDict[lFileNameWExtStr]= {
|
|
|
|
|
"StartSecFloat": self.mStartChunkSecFloat,
|
|
|
|
|
"EndSecFloat": lTimeSecFloat,
|
|
|
|
|
"Extra": inExtra,
|
|
|
|
|
"PathStr": lFilePathStr
|
|
|
|
|
}
|
|
|
|
|
if self.mCallbackChunkDef != None and self.mFileAvailableChunkInt!=None:
|
|
|
|
|
lCallbackThread = threading.Thread(target=self.mCallbackChunkDef,args=[self, lFileNameWExtStr])
|
|
|
|
|
lCallbackThread.start()
|
|
|
|
|
self.mStartChunkSecFloat = lTimeSecFloat
|
|
|
|
|
return lFileNameWExtStr
|
|
|
|
|
|
|
|
|
|
def FileInfoGet(self, inFileNameStr=None):
|
|
|
|
|
"""L-,W+: Вернуть информацию по аудиофайлу inFileNameStr. Если inFileNameStr == None -> Функция вернет информацию по последнему записанному файлу
|
|
|
|
@ -286,7 +306,7 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
lFileInfoDict = lRec.FileInfoGet()
|
|
|
|
|
|
|
|
|
@ -304,7 +324,7 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
lRec.FileListGet()
|
|
|
|
@ -320,7 +340,7 @@ class Recorder:
|
|
|
|
|
.. 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.CaptureStart(inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 5.0)
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
lRec.CaptureChunk()
|
|
|
|
|
lRec.FileListGet()
|
|
|
|
@ -329,13 +349,6 @@ class Recorder:
|
|
|
|
|
:rtype: list
|
|
|
|
|
"""
|
|
|
|
|
return self.mFileNameList[-1]
|
|
|
|
|
|
|
|
|
|
def __Callback__(self, inDefList):
|
|
|
|
|
pass
|
|
|
|
|
def __CallbackIsChunked__(self):
|
|
|
|
|
pass
|
|
|
|
|
def __CallbackIsStopped__(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
#def IsSilent(self, inLastSecFloat=None):
|
|
|
|
|
# "Returns 'True' if below the 'silent' threshold"
|
|
|
|
|