Python 音频函数无法按预期工作



这是帖子的后续: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. 如果存在异常,请返回到循环的顶部。
  3. 重复步骤1-2 ad-恶心

要解决此问题,您可以尝试在 except 块中重新打开流。


我在试图回答你的问题之前写的咆哮

冒着因

实际上没有提供问题的答案而被否决的风险,我认为您需要重组一些代码才能解决此问题。以下内容旨在完全具有建设性,如果它以任何其他方式出现,请告诉我。

您的listen()函数对自身进行了多次递归调用,这似乎不是您想要的。这不像将控制权转移到代码的该部分的 jumpgoto 命令。这实际上会创建另一个堆栈帧,用于单独执行listen()函数。这对整个代码有几个影响。

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

  2. 您定义的闭包(函数中的函数)将针对每个listen()的本地范围重新定义。同样的问题。

  3. 在这样的部分中:

    listen()
    Time = Time + 1
    if (Time > TimeoutSignal):
        print "Waiting No Speech Detected"
        listen()
    

    在对listen()的初始调用之后,不会执行任何内容,因为您在listen的任何地方都没有退出条件(return)。

因此,在尝试解决此问题然后遇到性能/稳定性问题之前,我的建议是:

    将所有
  1. 代码包装在 listen() 内(但不是变量声明)中

  2. ,就像 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 之后,此代码仍然永远不会执行。

实现此操作后,请验证当前结果是否相同。在重组此代码的某个地方,您实际上可能会解决您的问题。我会将您的代码复制到新脚本中,并在该脚本中工作以保留您当前拥有的内容。

附言

如果这是您第一次尝试编码,您根本不应该为发布此内容并寻求帮助而感到羞耻。你在这里有很多事情要做,作为编程的第一次尝试,它实际上非常令人印象深刻。

最新更新