Python函数不能按预期工作

时间:2013-09-05 15:46:35

标签: python audio raspberry-pi

这是帖子的后续内容: Python record audio on detected sound

我现在大部分时间排序但仍然有一个错误?

程序运行后,一旦保存一个录音并将其输入数据库,它将返回打印监听并等待语音。无论音量多么大,它都不会再次录音,你必须打破程序吗?

我已经删除了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()

我肯定在此提前遗漏了一些简单的事情

亚历

1 个答案:

答案 0 :(得分:0)

我强烈建议您阅读以下内容,但WriteSpeech似乎停止并关闭stream,但永远不会重新开启。这很可能被你的try / except块掩盖了。

while silence:
    try:
        input = GetStream(chunk)
    except:
        continue

现在说,

  1. 尝试从流中读取。
  2. 如果有异常,请返回循环顶部。
  3. 重复步骤1-2 ad-nauseum
  4. 要解决此问题,您可以尝试在except块中重新打开流。


    在我试图回答你的问题之前我写的唠叨

    由于没有实际提供问题的答案而被贬低的风险,我认为您需要重新构建一些代码才能解决问题。以下内容旨在完全具有建设性,请在任何其他方式下告诉我。

    您的listen()函数对自己进行了几次recursive次调用,这似乎不是您想要的。这与将jumpgoto命令转移到代码的该部分的命令不同。这实际上创建了另一个堆栈帧,用于单独执行listen()函数。这会对您的代码产生一些影响。

    1. 所有局部变量都在listen()的每个堆栈帧的本地范围内重新定义。这将导致内存使用量急剧增加。例如,你在内存中实际上有很多很多SHORT_NORMALIZE个变量。

    2. 正在为每个listen()的本地范围重新定义您定义的闭包(函数内的函数)。同样的问题。

    3. 在以下部分中:

      listen()
      Time = Time + 1
      
      if (Time > TimeoutSignal):
          print "Waiting No Speech Detected"
          listen()
      
      listen()的初始调用之后

      没有执行任何操作,因为return中的任何位置都没有退出条件(listen)。

    4. 那么,在尝试解决这个问题然后遇到性能/稳定性问题之前,我会建议:

      1. listen()

      2. 等while循环中包装while True:内的所有代码(但不包括变量声明)
      3. listen()函数本身内的listen所处的任何地方都将其替换为continue。这将告诉python不再从循环中执行任何代码,而是继续执行下一个循环迭代,将执行返回到循环的顶部。

      4. 向此主循环添加退出条件:

        if exit:
            print 'Terminating normally'
            break
        
      5. 底部没有KeepRecord来电listen()。只是让它完成执行。完成后,执行将返回listen,因为这是对KeepRecord的调用。

      6. 找到一种方法将Time = Time + 1部分移动到其他地方,以便实际执行。即使在此处的步骤1-4之后,此代码仍然永远不会执行。

      7. 实施此功能后,请验证您当前的结果是否相同。在重构此代码的某个地方,您可能会解决您的问题。我会将你的代码复制到一个新的脚本中并在那个脚本中工作以保留你当前拥有的内容。

        P.S。

        如果这是您第一次尝试编码,那么发布此信息并寻求帮助一点也不应该感到羞耻。你在这里有很多事情,作为编程的第一次尝试,实际上非常令人印象深刻。