这是帖子的后续:Python 在检测到的声音上录制音频
我现在已对大部分内容进行了排序,但仍然有一个错误。
程序运行一次后,保存一个录音并将其输入数据库,它返回打印收听和等待语音。 无论音量有多大,它都不会再次录制,您必须突破程序?
我已经删除了listen()
功能,所以现在回到基础,寻找一种方法,在录制完成后从头开始并等待下一个音频。
这里有现在的代码:
import pyaudio
import math
import struct
import wave
import datetime
import os
import sys
import MySQLdb
utc_datetime = datetime.datetime.utcnow()
FileTime = utc_datetime.strftime("%Y-%m-%d-%H%M")
#Assuming Energy threshold upper than 30 dB
Threshold = 30
SHORT_NORMALIZE = (1.0/32768.0)
chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
swidth = 2
Max_Seconds = 5
TimeoutSignal=((RATE / chunk * Max_Seconds) + 2)
silence = True
FileNameTmp = '/var/www/Recordings/'+FileTime+'.wav'
FileNameWWW = 'Recordings/'+FileTime+'.wav'
Time=0
all =[]
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)
# SQL DB Connection
db = MySQLdb.connect("localhost","root","*****","radiolink" )
cursor = db.cursor()
def GetStream(chunk):
return stream.read(chunk)
def rms(frame):
count = len(frame)/swidth
format = "%dh"%(count)
shorts = struct.unpack( format, frame )
sum_squares = 0.0
for sample in shorts:
n = sample * SHORT_NORMALIZE
sum_squares += n*n
rms = math.pow(sum_squares/count,0.5);
return rms * 1000
# Define What to Do When WriteSpeech is Called
def WriteSpeech(WriteData):
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(FileNameTmp, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(WriteData)
wf.close()
def KeepRecord(TimeoutSignal, LastBlock):
all.append(LastBlock)
for i in range(0, TimeoutSignal):
try:
data = GetStream(chunk)
except:
continue
all.append(data)
print "end record after timeout";
data = ''.join(all)
print "Creating File " +FileNameTmp;
WriteSpeech(data)
print "Entering Record into DB";
File = FileNameWWW
query ="""
INSERT INTO recordings
(`id`, `time`,`filename`,`active`,`status`)
VALUES
(NULL,NOW(), %s,1,1) """
cursor.execute(query,(File))
db.commit()
silence = True
Time=0
print "Listening......"
print "Waiting for Speech"
while silence:
try:
input = GetStream(chunk)
except:
continue
rms_value = rms(input)
if (rms_value > Threshold):
silence=False
LastBlock=input
print "Recording...."
KeepRecord(TimeoutSignal, LastBlock)
Time = Time + 1
if (Time > TimeoutSignal):
print "Waiting No Speech Detected"
sys.exit()
我强烈建议您阅读以下内容 但是,似乎WriteSpeech
停止并关闭stream
,永远不会重新打开。这可能被您的 try/except 块所掩盖。
while silence:
try:
input = GetStream(chunk)
except:
continue
现在说,
- 尝试从流中读取。
- 如果存在异常,请返回到循环的顶部。
- 重复步骤1-2 ad-恶心
要解决此问题,您可以尝试在 except 块中重新打开流。
我在试图回答你的问题之前写的咆哮
冒着因实际上没有提供问题的答案而被否决的风险,我认为您需要重组一些代码才能解决此问题。以下内容旨在完全具有建设性,如果它以任何其他方式出现,请告诉我。
您的listen()
函数对自身进行了多次递归调用,这似乎不是您想要的。这不像将控制权转移到代码的该部分的 jump
或 goto
命令。这实际上会创建另一个堆栈帧,用于单独执行listen()
函数。这对整个代码有几个影响。
所有局部变量都在
listen()
的每个堆栈帧的局部范围内重新定义。这将导致内存使用量急剧增加。例如,内存中实际上有很多很多SHORT_NORMALIZE
变量。您定义的闭包(函数中的函数)将针对每个
listen()
的本地范围重新定义。同样的问题。在这样的部分中:
listen() Time = Time + 1 if (Time > TimeoutSignal): print "Waiting No Speech Detected" listen()
在对
listen()
的初始调用之后,不会执行任何内容,因为您在listen
的任何地方都没有退出条件(return
)。
因此,在尝试解决此问题然后遇到性能/稳定性问题之前,我的建议是:
- 将所有
代码包装在
listen()
内(但不是变量声明)中
,就像 在
listen
函数本身中当前listen()
的所有位置,请将其替换为continue
。这将告诉 python 不要再从循环中执行任何代码,而是继续下一个循环迭代,将执行带回循环的顶部。
向此主循环添加退出条件:
if exit: print 'Terminating normally' break
不要在底部
KeepRecord
呼叫listen()
。只需让它完成执行即可。执行完成后将返回到listen
,因为这是调用KeepRecord
的位置。找到一种方法将
Time = Time + 1
部分移动到其他地方,以便实际执行。即使在此处的步骤 1-4 之后,此代码仍然永远不会执行。
while True:
实现此操作后,请验证当前结果是否相同。在重组此代码的某个地方,您实际上可能会解决您的问题。我会将您的代码复制到新脚本中,并在该脚本中工作以保留您当前拥有的内容。
附言
如果这是您第一次尝试编码,您根本不应该为发布此内容并寻求帮助而感到羞耻。你在这里有很多事情要做,作为编程的第一次尝试,它实际上非常令人印象深刻。