0

これは投稿からの続きです: Python は、検出されたサウンドでオーディオを録音します

現在、ほとんどをソートしましたが、まだ 1 つのバグがあります。

プログラムが実行された後、1 つの録音を保存して DB に入力すると、印刷に戻り、音声を聞いて待機します。ボリュームをどれだけ大きくしても、再び録音されない場合は、プログラムを中断する必要がありますか?

機能を削除した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()
4

1 に答える 1

0

次の内容をお読みになることを強くお勧めしますが、WriteSpeech停止して閉じstream、再開されることはないようです。これは、try/except ブロックによってマスクされている可能性があります。

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

これは今言う、

  1. ストリームから読み取ろうとします。
  2. 例外が発生した場合は、ループの先頭に戻ります。
  3. 手順 1 ~ 2 を繰り返します。

これを修正するには、except ブロック内でストリームを再度開いてみてください。


あなたの質問に答える前に書いた暴言

質問に対する回答を実際に提供していないために反対票を投じられるリスクがあるため、これを解決するには、コードを再構築する必要があると思います。以下は完全に建設的なものであることを意図しています。

関数にはそれ自体への再帰listen()呼び出しがいくつかありますが、これは意図したものではないようです。これは、コードのその部分に制御を移すorコマンドとは異なります。これにより、関数を個別に実行するための別のスタック フレームが実際に作成されます。これは、コード全体にいくつかの影響を及ぼします。jumpgotolisten()

  1. すべてのローカル変数は、すべてのスタック フレームのローカル スコープ内で再定義されますlisten()。これにより、メモリ使用量が大幅に増加します。SHORT_NORMALIZEたとえば、実際にはメモリ内に非常に多くの変数があります。

  2. あなたが定義するクロージャー (関数内の関数) は、 every のローカル スコープに対して再定義されていlisten()ます。同じ問題。

  3. このようなセクションでは:

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

    のどこにも終了条件 ()がないため、 everへの最初の呼び出しの後は何もlisten()実行されません。returnlisten

したがって、この問題を解決しようとする前に、パフォーマンス/安定性の問題に遭遇する前に、私が提案することは次のとおりです。

  1. 内部のすべてのコードlisten()(変数宣言は除く) を while ループのようにラップします。while True:

  2. 現在関数自体listen()の内部にあるすべての場所でlisten、これを に置き換えますcontinue。これは、ループからこれ以上コードを実行しないように python に指示しますが、代わりに次のループ反復に移動し、実行をループの先頭に戻します。

  3. このメイン ループに終了条件を追加します。

    if exit:
        print 'Terminating normally'
        break
    
  4. 下部にKeepRecord呼び出しはありません。listen()実行を終了させるだけです。listenへの呼び出しが行われた場所であるため、実行は終了すると に戻りKeepRecordます。

  5. Time = Time + 1実際に実行されるように、セクションを別の場所に移動する方法を見つけてください。ここの手順 1 ~ 4 の後でも、このコードは実行されることはありません。

これを実装したら、現在の結果が同じであることを確認します。このコードを再構築する行のどこかで、実際に問題を修正できる可能性があります。あなたのコードを新しいスクリプトにコピーし、そのスクリプトで作業して、現在持っているものを保持します。

PS

これがコーディングへの最初の試みである場合、これを投稿して助けを求めることを恥じるべきではありません。ここでは多くのことが行われています。プログラミングの最初の試みとしては、実際には非常に印象的です。

于 2013-09-05T16:58:07.463 に答える