2

こんにちは、ネットワーク経由で送信される音声に問題があります。距離のない私のローカルシステムでは問題はありませんが、リモートシステムでテストするときはいつでもオーディオがありますが、音声入力ではなく、途切れ/遅れなどが必要です.オーディオの送信をどのように処理しているかを信じていますが、私は今4日間試しましたが、解決策が見つかりません.

関連するすべてのコードを投稿し、できる限り説明します

これらは定数/グローバル値です

    #initilaize Speex
    speex_enc = speex.Encoder()
    speex_enc.initialize(speex.SPEEX_MODEID_WB)
    speex_dec = speex.Decoder()
    speex_dec.initialize(speex.SPEEX_MODEID_WB)

    #いくつかの定数値
    チャンク = 320
    フォーマット = pyaudio.paInt16
    チャネル = 1
    レート = 44100

サンプルレートの値を調整すると、より多くのノイズが許容されることがわかりました

以下は、オーディオ デバイスを初期化するための pyAudio コードです。これもグローバルです。

    #PyAudio の初期化
    p = pyaudio.PyAudio()
    ストリーム = p.open(フォーマット = フォーマット、
                    チャネル = チャネル、
                    率 = 率、
                    入力 = 真、
                    出力 = 真、
                    frames_per_buffer = チャンク)

この次の機能は、マイクからデータを書き込み、クライアント機能を使用して送信するキープレス機能です。これは、私が問題を抱えていると思われる場所です。

これをどのように処理しているかが問題だと思います。オーディオを取得するために押したままにすると、ループして各反復で送信されるからです。ここで何をすべきかわかりません。(アイデア!!!)

    def keypress(イベント):
        #chunklist = []
        #RECORD_SECONDS = 5
        if event.keysym == 'エスケープ':
            root.destroy()
        #x = event.char
        if event.keysym == 'Control_L':   
            # for i in range(0, 44100 / chunk * RECORD_SECONDS):
            試す:
                #マイクからデータを取得
                data = stream.read(チャンク)
            例として IOError を除く:
                ex[1] != pyaudio.paInputOverflowed の場合:
                    高める
                データ = '\x00' * チャンク
            encda​​ta = speex_enc.encode(data) #データをエンコードします。
            #chunklist.append(encda​​ta)
            #音声を送信
            client(chr(CMD_AUDIO), encrypt_my_audio_message(encda​​ta))

オーディオを処理するサーバー コード

    ### サーバー機能 ###
    デフサーバー():
        ポート = 9001
        ### ソケットの初期化
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind((socket.gethostbyname(socket.gethostname()), PORT))
        # socket.gethostbyname(socket.gethostname())
        server_socket.listen(5)
        read_list = [サーバーソケット]
        ### 受信ループを開始
        True の間:
            読み取り可能、書き込み可能、​​エラー = select.select(read_list, [], [])
            for s in readable:
                s が server_socket の場合:
                    conn, addr = s.accept()
                    read_list.append(接続)
                    print "接続元", addr
                そうしないと:
                    メッセージ = conn.recv(2048)
                    メッセージの場合:                
                        cmd、msg = ord(msg[0])、msg[1:]
                        ## GUI からテキスト メッセージを取得する
                        cmd == CMD_MSG の場合:
                            listb1.insert(END, decrypt_my_message(msg).strip() + "\n")
                            listb1.yview(END)
                        ## 音声メッセージを受け取る
                        elif コマンド == CMD_AUDIO:
                            # 長さが 16 であることを確認 --- HACK ---
                            len(msg) % 16 != 0 の場合:
                                msg += '\x00' * (16 - len(msg) % 16)
                            #オーディオの復号化
                            データ = decrypt_my_message(msg)
                            decdata = speex_dec.decode(データ)
                            #データをスピーカーに書き戻す
                            stream.write(decdata, チャンク)
                    そうしないと:
                        s.close()
                        read_list.remove(s)

Tkinter でのキーボードのバインドを完了する

    root.bind_all('', キープレス)

そのキープレスメソッドを必要に応じて機能させる方法や、より良い方法を提案する方法、または完全に間違ったことをしている可能性があるアイデアは大歓迎です

*乾杯

暗号化方法なしでも同じことをテストしたことに注意してください:-)

4

1 に答える 1

0

ping または ttcp を実行して、2 つのホスト間のネットワーク パフォーマンスをテストしましたか?

レイテンシ スパイクが発生したり、一部のパケットがドロップされたりすると、音声ストリームを送信するアプローチが大きく損なわれます。TCP は失われたパケットを待ち、失われたことを報告し、再送信を待ちます。

損失のあるリンク上で UDP を使用し、失われたパケットを適切に処理するオーディオ圧縮を使用する必要があります。この場合も、発信パケットにタイムスタンプを付ける必要があります。

于 2012-10-27T17:25:17.863 に答える