Class done - need test / fix silent mode and callback

prd
Ivan Maslov 2 years ago
parent 297e3ba9fa
commit acc59de61b

@ -5,6 +5,9 @@ import threading
import wave import wave
import time import time
from pyOpenRPA.Utils import Text from pyOpenRPA.Utils import Text
import os
def DeviceMicrophoneIndex(): def DeviceMicrophoneIndex():
@ -34,7 +37,9 @@ def DeviceSystemSoundIndex():
elif inIsLoopbackBool==False: lCompareBool = True elif inIsLoopbackBool==False: lCompareBool = True
if lCompareBool == True: if lCompareBool == True:
lDiffRationFloat = Text.SimilarityNoCase(in1Str=lDefaultNameStr, in2Str=lItemDict["NameStr"]) lDiffRationFloat = Text.SimilarityNoCase(in1Str=lDefaultNameStr, in2Str=lItemDict["NameStr"])
if lDiffRationFloat> lCatchDiffRatioFloat: lCatchIndexInt=lItemDict["IndexInt"] if lDiffRationFloat> lCatchDiffRatioFloat:
lCatchDiffRatioFloat = lDiffRationFloat
lCatchIndexInt=lItemDict["IndexInt"]
else: else:
lDeviceInfoDict = p.get_default_output_device_info() lDeviceInfoDict = p.get_default_output_device_info()
lDefaultIndexInt = lDeviceInfoDict["index"] lDefaultIndexInt = lDeviceInfoDict["index"]
@ -81,8 +86,8 @@ def DeviceListGet():
return l_result return l_result
class Recorder: class Recorder:
mT=[]
mStatusStr = "0_READY" mStatusStr = "0_READY" # "0_READY", "1_RECORDING"
mAudio = None mAudio = None
mCaptureThread = None mCaptureThread = None
mStream = None mStream = None
@ -91,21 +96,50 @@ class Recorder:
mChannelCountInt = None mChannelCountInt = None
mFramesInt = 512 mFramesInt = 512
mRecordedFramesList = [] mRecordedFramesList = []
mUseLoopbackBool = True
mSampleRateInt = None mSampleRateInt = None
mSampleSizeInt = None mSampleSizeInt = None
mCaptureBool = True mCaptureBool = True
mFilePathStr = "out" mFolderPathStr = None
mFileFormatStr = "mp3" mFileNameStr = None
mFileFormatStr = None
mFileAvailableChunkInt = None
mFileNameList=None
mChunkSecFloat = None
mChunkSilentSecFloat = None
mStartSecFloat = None
mStartChunkSecFloat = None
mDurationSecFloat = None
mThresholdInt = 500
mSilentLastCheckTimeFloat = None
mIsMicrophoneBool=None
def __init__(self, inDeviceInt=None): def __init__(self, inDeviceInt=None):
self.mDeviceInt = inDeviceInt self.mDeviceInt = inDeviceInt
if inDeviceInt == None: self.mDeviceInt = DeviceSystemSoundIndex() if inDeviceInt == None: inDeviceInt = DeviceSystemSoundIndex()
self.mDeviceInt = inDeviceInt
if DeviceListGet()[inDeviceInt]["MaxInputChannelsInt"]>0: self.mIsMicrophoneBool = True
else: self.mIsMicrophoneBool = False
def CaptureStart(self, inFilePathStr = "out", inFileFormatStr = "mp3", inDoChunkBool = False): def StatusGet(self):
self.mFilePathStr = inFilePathStr return self.mStatusStr
def CaptureStart(self, inFolderPathStr="",inFileNameStr = "out", inFileFormatStr = "mp3", inDurationSecFloat = None, inChunkSecFloat = 300.0, inChunkSilentSecFloat = 10.0):
# CHECK AUX.mp3
self.mFileNameList=[]
self.mRecordedFramesList=[]
self.mStatusStr = "1_RECORDING"
if inChunkSecFloat != None or inChunkSilentSecFloat != None: self.mFileAvailableChunkInt = 0
self.mDurationSecFloat = inDurationSecFloat
self.mChunkSecFloat = inChunkSecFloat
self.mChunkSilentSecFloat = inChunkSilentSecFloat
self.mSilentLastCheckTimeFloat=time.time()
self.mFolderPathStr = inFolderPathStr
self.mFileNameStr = inFileNameStr
self.mFileFormatStr = inFileFormatStr self.mFileFormatStr = inFileFormatStr
self.mAudio = pyaudio.PyAudio() self.mAudio = pyaudio.PyAudio()
self.mSampleSizeInt = self.mAudio.get_sample_size(pyaudio.paInt16) self.mSampleSizeInt = self.mAudio.get_sample_size(pyaudio.paInt16)
@ -119,24 +153,32 @@ class Recorder:
input = True, input = True,
frames_per_buffer = self.mFramesInt, frames_per_buffer = self.mFramesInt,
input_device_index = lDeviceInfoDict["index"], input_device_index = lDeviceInfoDict["index"],
as_loopback = self.mUseLoopbackBool) as_loopback = not self.mIsMicrophoneBool)
self.mCaptureThread = threading.Thread(target=self.__Capture__) self.mCaptureThread = threading.Thread(target=self.__Capture__)
self.mStartSecFloat = time.time()
self.mStartChunkSecFloat = self.mStartSecFloat
self.mCaptureThread.start() self.mCaptureThread.start()
def __Capture__(self): def __Capture__(self):
while self.mCaptureBool==True: while self.mCaptureBool==True:
self.mRecordedFramesList.append(self.mStream.read(self.mFramesInt)) self.mRecordedFramesList.append(self.mStream.read(self.mFramesInt))
self.__TriggerCheck__()
def CaptureStop(self, inWaitStream=True):
self.mCaptureBool=False
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()
def CaptureStop(self):
self.mCaptureBool=False
self.mCaptureThread.join()
self.CaptureChunk() self.CaptureChunk()
self.mStatusStr = "0_READY"
def CaptureChunk(self): def CaptureChunk(self):
lFileNameStr = self.mFileNameStr
if self.mFileAvailableChunkInt!=None:
lFileNameStr+=f"_{self.mFileAvailableChunkInt:05}"
self.mFileAvailableChunkInt = self.mFileAvailableChunkInt + 1
# 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)
@ -148,13 +190,16 @@ class Recorder:
# stereo # stereo
channels=self.mChannelCountInt channels=self.mChannelCountInt
) )
sound.export(f"{self.mFilePathStr}.{self.mFileFormatStr}", format=f"{self.mFileFormatStr}") 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()
def FileListGet(self): def FileListGet(self):
pass return self.mFileNameList
def FileLastGet(self): def FileLastGet(self):
pass return self.mFileNameList[-1]
def __Callback__(self, inDefList): def __Callback__(self, inDefList):
pass pass
@ -165,11 +210,27 @@ class Recorder:
def __CallbackIsStopped__(self): def __CallbackIsStopped__(self):
pass pass
def __TriggerCenter__(self): def IsSilent(self, inLastSecFloat=None):
"Returns 'True' if below the 'silent' threshold"
self.mSilentLastCheckTimeFloat = time.time()
if inLastSecFloat == None: inLastSecFloat = self.mChunkSilentSecFloat
lFrameLenInt = int(self.mSampleSizeInt*inLastSecFloat)
if lFrameLenInt<len(self.mRecordedFramesList): lData = self.mRecordedFramesList[-lFrameLenInt:]
else: lData = self.mRecordedFramesList
return max(lData) < self.mThresholdInt
def __TriggerCheck__(self):
"""L-,W+: Контроль записи / остановки аудио по следующим критериям: """L-,W+: Контроль записи / остановки аудио по следующим критериям:
- Общая длительность, - Общая длительность,
- Максимальная длительность части, - Максимальная длительность части,
- Максимальная длит тишины (часть), - Максимальная длит тишины (часть),
- Максимальная длительность тишины (остановка), - Максимальная длительность тишины (остановка),
""" """
pass # Проверка по длине записи (CHUNK)
if self.mChunkSecFloat != None and time.time() - self.mStartChunkSecFloat > self.mChunkSecFloat: self.CaptureChunk()
# Остановка записи по максимальной длине
if self.mDurationSecFloat != None and time.time() - self.mStartSecFloat > self.mDurationSecFloat: self.CaptureStop(inWaitStream=False)
# Проверка тишины
#if self.mChunkSilentSecFloat != None and time.time() - self.mSilentLastCheckTimeFloat and self.IsSilent(): self.mT.append("ТИШИНА!!")

@ -15,25 +15,40 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"ename": "AttributeError", "name": "stdout",
"evalue": "'Recorder' object has no attribute 'test'", "output_type": "stream",
"output_type": "error", "text": [
"traceback": [ "2 - NEC LCD1703M (AMD High Definition Audio Device): 0.2926829268292683 _ 0.0\n",
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "Динамики (USB PnP Sound Device): 0.7419354838709677 _ 0.2926829268292683\n",
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", "Динамики (Realtek High Definition Audio): 0.22535211267605634 _ 0.7419354838709677\n",
"\u001b[1;32m<ipython-input-1-ef80e2b488aa>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mpyOpenRPA\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mRobot\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mAudio\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mlRec\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mAudio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mRecorder\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0minDeviceInt\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mlRec\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "9\n"
"\u001b[1;31mAttributeError\u001b[0m: 'Recorder' object has no attribute 'test'"
] ]
},
{
"data": {
"text/plain": [
"{'IndexInt': 9,\n",
" 'NameStr': 'Динамики (USB PnP Sound Device)',\n",
" 'MaxInputChannelsInt': 0,\n",
" 'MaxOutputChannelsInt': 2,\n",
" 'HostApiInt': 1,\n",
" 'DefaultSampleRateFloat': 44100.0,\n",
" 'HostApiStr': 'Windows WASAPI'}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
} }
], ],
"source": [ "source": [
"from pyOpenRPA.Robot import Audio\n", "from pyOpenRPA.Robot import Audio\n",
"lRec = Audio.Recorder(inDeviceInt=10)\n", "print(Audio.DeviceSystemSoundIndex())\n",
"lRec.test()" "Audio.DeviceListGet()[9]"
] ]
}, },
{ {
@ -43,8 +58,39 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"from pyOpenRPA.Robot import Audio\n", "from pyOpenRPA.Robot import Audio\n",
"lRec = Audio.Recorder(inDeviceInt=10)\n", "lRec = Audio.Recorder(inDeviceInt = Audio.DeviceMicrophoneIndex())\n",
"lRec.CaptureStart()" "lRec.CaptureStart(inFileNameStr = \"out2\", inFileFormatStr = \"mp3\", inDurationSecFloat = None, inChunkSecFloat = 15.0, inChunkSilentSecFloat = 3.0)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from pyOpenRPA.Robot import Audio\n",
"lRec = Audio.Recorder()\n",
"lRec.CaptureStart(inFileNameStr = \"out\", inFileFormatStr = \"mp3\", inDurationSecFloat = None, inChunkSecFloat = 5.0, inChunkSilentSecFloat = 10.0)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lRec.FileListGet()"
] ]
}, },
{ {
@ -56,6 +102,46 @@
"lRec.CaptureStop()" "lRec.CaptureStop()"
] ]
}, },
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lRec.mT"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1_RECORDING'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lRec.StatusGet()"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 10,

@ -0,0 +1,86 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"import os\n",
"sys.path.insert(0, os.path.abspath(\"..\\\\..\\\\Sources\"))\n",
"sys.path.insert(0, os.path.abspath(\"..\\\\..\\\\..\\\\KPI_Effect\\\\packages\"))\n",
"import time\n",
"import kpi_client\n",
"kpi_client.init(\"http://localhost:1024\", \"1992-04-03-0643-ru-b4ff-openrpa52zzz\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"l_start_float = time.time()-200\n",
"kpi_client.log(in_code_str=\"Zzz\",in_group_str=\"БУХГАЛТЕР - ПЛАТЕЖНЫЕ поручения 2\",in_manual_operation_float=300, in_auto_operation_float=200, in_start_time_float=l_start_float)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Loading…
Cancel
Save