网络问题上的Python音频

时间:2011-10-11 02:55:06

标签: python tcp speex pyaudio

您好,我遇到通过网络发送音频的问题。在没有距离的本地系统上没有任何问题但是每当我在远程系统上测试时都有音频,但不是语音输入我想要它的波动/滞后等等。我相信它在我如何处理发送音频但是我已经尝试了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)

    #some constant values
    chunk = 320
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 44100

我发现调整采样率值会产生更多噪音

下面是初始化音频设备的pyAudio代码,这也是全局的


    #initalize PyAudio
    p = pyaudio.PyAudio()
    stream = p.open(format = FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    input = True,
                    output = True,
                    frames_per_buffer = chunk)

下一个功能是按键功能,它从麦克风写入数据并使用客户端功能发送它。这是我认为我遇到问题的地方。

我相信我如何处理这个问题是因为如果我按住它来获取音频,它会循环播放并在每次迭代时发送。我不知道该怎么做。 (思想!!!)


    def keypress(event):
        #chunklist = []
        #RECORD_SECONDS = 5
        if event.keysym == 'Escape':
            root.destroy()
        #x = event.char
        if event.keysym == 'Control_L':   
            #for i in range(0, 44100 / chunk * RECORD_SECONDS):
            try:
                #get data from mic
                data = stream.read(chunk)
            except IOError as ex:
                if ex[1] != pyaudio.paInputOverflowed:
                    raise
                data = '\x00' * chunk
            encdata = speex_enc.encode(data)        #Encode the data.
            #chunklist.append(encdata)
            #send audio
            client(chr(CMD_AUDIO), encrypt_my_audio_message(encdata))

处理音频的服务器代码


    ### Server function ###
    def server():
        PORT = 9001
        ### Initialize socket 
        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 = [server_socket]
        ### Start receive loop
        while True:
            readable, writable, errored = select.select(read_list, [], [])
            for s in readable:
                if s is server_socket:
                    conn, addr = s.accept()
                    read_list.append(conn)
                    print "Connection from ", addr
                else:
                    msg = conn.recv(2048)
                    if msg:                
                        cmd, msg = ord(msg[0]),msg[1:]
                        ## get a text message from GUI
                        if cmd == CMD_MSG:
                            listb1.insert(END, decrypt_my_message(msg).strip() + "\n")
                            listb1.yview(END)
                        ## get an audio message
                        elif cmd == CMD_AUDIO:
                            # make sure length is 16 --- HACK ---
                            if len(msg) % 16 != 0:
                                msg += '\x00' * (16 - len(msg) % 16)
                            #decrypt audio
                            data = decrypt_my_message(msg)
                            decdata = speex_dec.decode(data)
                            #Write the data back out to the speaker
                            stream.write(decdata, chunk)
                    else:
                        s.close()
                        read_list.remove(s)

并完成键盘在Tkinter中的绑定


    root.bind_all('', keypress)

我非常感谢任何想法如何使按键方法按需运行或建议更好的方式或者我完全做错了

*欢呼声

请注意我在没有加密方法的情况下进行了测试,同样的事情: - )

1 个答案:

答案 0 :(得分:0)

您是否运行ping或ttcp来测试两台主机之间的网络性能?

如果您有延迟峰值或者某些数据包被丢弃,您发送语音流的方法将会受到严重影响。 TCP将等待丢失数据包,报告丢失,等待重新传输等等。

您应该使用UDP通过有损链接和音频压缩来正常处理丢失的数据包。同样在这种情况下,您必须为传出的数据包加上时间戳。