robot.audio added and tested!

prd
Ivan Maslov 2 years ago
parent acc59de61b
commit 20988db521

@ -25,6 +25,10 @@
- Mouse: инструменты взаимодействия с мышью. Перейти к описанию функций: :ref:`module.robot.mouse` - Mouse: инструменты взаимодействия с мышью. Перейти к описанию функций: :ref:`module.robot.mouse`
- Screen: инструменты взаимодействия с эраном рабочего стола. Перейти к описанию функций: :ref:`module.robot.screen` - Screen: инструменты взаимодействия с эраном рабочего стола. Перейти к описанию функций: :ref:`module.robot.screen`
- **Уровень доступа к звуковым каналам передачи данных (микрофон, динамик)**
- Audio: инструменты взаимодействия с аудио. Перейти к описанию функций: :ref:`module.robot.audio`
Дорогие коллеги! Дорогие коллеги!

@ -0,0 +1,49 @@
.. _module.robot.audio:
####################################
7. Функции Audio
####################################
************************
Общее
************************
Дорогие коллеги!
Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы!
Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts`
pyOpenRPA - роботы помогут!
************************
Класс Recorder
************************
Экземпляр класса pyOpenRPA.Robot.Audio.Recorder, который обеспечивает захват звука (с микрофона или из приложений) и сохраняет в виде аудиофайла (множества аудиофайлов)
**************************************************
Описание функций
**************************************************
Описание каждой функции начинается с обозначения L-,W+, что означает, что функция не поддерживается в ОС Linux (L) и поддерживается в Windows (W)
.. automodule:: pyOpenRPA.Robot.Audio
:members:
:autosummary:
.. autoclass:: pyOpenRPA.Robot.Audio.Recorder
:members:
:autosummary:
******************************
Быстрая навигация
******************************
- `Сообщество pyOpenRPA (telegram) <https://t.me/pyOpenRPA>`_
- `Сообщество pyOpenRPA (tenchat) <https://tenchat.ru/iMaslov?utm_source=19f2a84f-3268-437f-950c-d987ae42af24>`_
- `Сообщество pyOpenRPA (вконтакте) <https://vk.com/pyopenrpa>`_
- `Презентация pyOpenRPA <https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf>`_
- `Портал pyOpenRPA <https://pyopenrpa.ru>`_
- `Репозиторий pyOpenRPA <https://gitlab.com/UnicodeLabs/OpenRPA>`_

@ -1,5 +1,5 @@
#################################### ####################################
8. Как использовать? 9. Как использовать?
#################################### ####################################
Модуль РОБОТ - это ключевое звено, которое отвечает за продуктивную роботизацию процесса. Данный модуль не имеет графический или консольный интерфейс - он подключается в качестве библиотеки в проект робота, что позволяет выполнять операции максимально быстро. А также позволяет с легкостью интегрировать робота в другие проекты. Модуль РОБОТ - это ключевое звено, которое отвечает за продуктивную роботизацию процесса. Данный модуль не имеет графический или консольный интерфейс - он подключается в качестве библиотеки в проект робота, что позволяет выполнять операции максимально быстро. А также позволяет с легкостью интегрировать робота в другие проекты.

@ -1 +1 @@
"..\..\Resources\wkhtmltopdf\bin\wkhtmltopdf.exe" --javascript-delay 5000 --load-error-handling ignore --enable-local-file-access ..\..\Wiki\RUS_Guide\html\index.html ..\..\Wiki\RUS_Guide\html\01_HowToInstall.html ..\..\Wiki\RUS_Guide\html\03_Copyrights_Contacts.html ..\..\Wiki\RUS_Guide\html\Robot\01_Robot.html ..\..\Wiki\RUS_Guide\html\Robot\02_uidesktop.html ..\..\Wiki\RUS_Guide\html\Robot\03_uiweb.html ..\..\Wiki\RUS_Guide\html\Robot\04_keyboard.html ..\..\Wiki\RUS_Guide\html\Robot\05_clipboard.html ..\..\Wiki\RUS_Guide\html\Robot\06_mouse.html ..\..\pyOpenRPA\Wiki\RUS_Guide\html\Robot\07_screen.html ..\..\Wiki\RUS_Guide\html\Robot\08_HowToUse.html ..\..\Wiki\RUS_Guide\html\Studio\01_Studio.html ..\..\Wiki\RUS_Guide\html\Studio\02_HowToUse.html ..\..\Wiki\RUS_Guide\html\Orchestrator\01_Orchestrator.html ..\..\Wiki\RUS_Guide\html\Orchestrator\02_Defs.html ..\..\Wiki\RUS_Guide\html\Orchestrator\03_gSettingsTemplate.html ..\..\Wiki\RUS_Guide\html\Orchestrator\04_HowToUse.html ..\..\Wiki\RUS_Guide\html\Orchestrator\05_UAC.html ..\..\Wiki\RUS_Guide\pdf\pyOpenRPA_Guide_RUS.pdf "..\..\Resources\wkhtmltopdf\bin\wkhtmltopdf.exe" --javascript-delay 5000 --load-error-handling ignore --enable-local-file-access ..\..\Wiki\RUS_Guide\html\index.html ..\..\Wiki\RUS_Guide\html\01_HowToInstall.html ..\..\Wiki\RUS_Guide\html\03_Copyrights_Contacts.html ..\..\Wiki\RUS_Guide\html\Robot\01_Robot.html ..\..\Wiki\RUS_Guide\html\Robot\02_uidesktop.html ..\..\Wiki\RUS_Guide\html\Robot\03_uiweb.html ..\..\Wiki\RUS_Guide\html\Robot\04_keyboard.html ..\..\Wiki\RUS_Guide\html\Robot\05_clipboard.html ..\..\Wiki\RUS_Guide\html\Robot\06_mouse.html ..\..\pyOpenRPA\Wiki\RUS_Guide\html\Robot\07_screen.html ..\..\Wiki\RUS_Guide\html\Robot\08_audio.html ..\..\Wiki\RUS_Guide\html\Robot\09_HowToUse.html ..\..\Wiki\RUS_Guide\html\Studio\01_Studio.html ..\..\Wiki\RUS_Guide\html\Studio\02_HowToUse.html ..\..\Wiki\RUS_Guide\html\Orchestrator\01_Orchestrator.html ..\..\Wiki\RUS_Guide\html\Orchestrator\02_Defs.html ..\..\Wiki\RUS_Guide\html\Orchestrator\03_gSettingsTemplate.html ..\..\Wiki\RUS_Guide\html\Orchestrator\04_HowToUse.html ..\..\Wiki\RUS_Guide\html\Orchestrator\05_UAC.html ..\..\Wiki\RUS_Guide\pdf\pyOpenRPA_Guide_RUS.pdf

@ -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+: Контроль записи / остановки аудио по следующим критериям: """Контроль записи / остановки аудио по следующим критериям:
- Общая длительность, - Общая длительность,
- Максимальная длительность части, - Максимальная длительность части,
- Максимальная длит тишины (часть), - Максимальная длит тишины (часть),

@ -497,6 +497,28 @@
"Audio.DeviceMicrophoneIndex()" "Audio.DeviceMicrophoneIndex()"
] ]
}, },
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "abspath() takes 1 positional argument but 2 were given",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-1-8d5d932ca99b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mabspath\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m\"\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m: abspath() takes 1 positional argument but 2 were given"
]
}
],
"source": [
"import os\n",
"os.path.abspath(\"\",\"\")"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,

Loading…
Cancel
Save