Python音频功能无法正常工作

 2021-04-26 

Python audio function not working as expected

这是该帖子的后续内容:
Python在检测到的声音上记录音频

我现在对其中的大多数进行了排序,但是仍然存在一个错误。

程序运行一次后,保存一个录音并将其输入到DB中,然后返回以打印收听和等待语音。不管音量有多大,它都不会再次录制,您必须退出程序吗?

我已经删除了listen()功能,所以现在回到基础知识,寻找从头开始录音结束后等待下一个音频的方法。

此处显示当前代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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()


我强烈建议您阅读BUT之后的内容,看来WriteSpeech停止并关闭stream,但从未重新打开。这可能被您的try / except块掩盖了。

1
2
3
4
5
while silence:
    try:
        input = GetStream(chunk)
    except:
        continue

现在说,

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

    在试图回答你的问题之前我写的那句话

    冒着没有为问题提供答案的风险,我认为您需要重组一些代码,然后才能解决该问题。以下内容旨在完全具有建设性,请通过其他方式告知我。

    您的listen()函数具有多个对其自身的递归调用,这似乎并不是您想要的。这与将控制权转移到代码的那部分的jumpgoto命令不同。实际上,这将为单独执行listen()函数创建另一个堆栈框架。总体上,这对您的代码有几个影响。

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

  • 您为每个listen()的本地范围重新定义的闭包(函数内的函数)。相同的问题。

  • 在这样的部分中:

    1
    2
    3
    4
    5
    6
    listen()
    Time = Time + 1

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

    listen()的初始调用之后没有执行任何操作,因为在listen中的任何地方都没有退出条件(return)。

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

  • 在类似while True:

    的while循环中packagelisten()内的所有代码(而不是变量声明)。

  • listen函数自身内部当前具有listen()的所有位置,请将其替换为continue。这将告诉python不要从循环中执行更多代码,而只是继续进行下一个循环迭代,从而使执行回到循环顶部。

  • 在此主循环中添加退出条件:

    1
    2
    3
    if exit:
        print 'Terminating normally'
        break
  • 底部没有KeepRecord调用listen()。只要让它完成执行即可。执行结束后,执行将返回到listen,因为这是对KeepRecord的调用。

  • 找到一种方法将Time = Time + 1节移动到其他地方,以便它实际上得到执行。即使在这里执行了步骤1-4,此代码仍将永远不会执行。

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

    P.S.

    如果这是您首次尝试编码,那么您完全不应该为发布此代码并寻求帮助而感到羞耻。您在这里进行了很多工作,并且第一次尝试编程时,实际上给人留下了深刻的印象。