Python 网络音频问题

发布于 2024-12-09 01:36:49 字数 3763 浏览 0 评论 0原文

您好,我在通过网络发送音频时遇到问题。在我的本地系统上,没有距离,没有问题,但每当我在远程系统上测试时,都会有音频,但不是语音输入,我希望它断断续续/滞后等。我相信这与我处理音频发送的方式有关,但是我现在已经尝试了 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)

的服务器代码非常感谢任何想法,我如何使按键方法根据需要工作或建议更好的方法,或者也许我做错了什么完全

*干杯

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

Hello I am having problems with audio being sent over the network. On my local system with no distance there is no problems but whenever I test on a remote system there is audio but its not the voice input i want its choppy/laggy etc. I believe its in how I am handling the sending of the audio but I have tried now for 4 days and can not find a solution.

I will post all relevant code and try and explain it the best I can

these are the constant/global values


    #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

I found adjusting the sample rate value would allow for more noise

Below is the pyAudio code to initialize the audio device this is also global


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

This next function is the keypress function which writes the data from the mic and sends it using the client function This is where I believe I am having problems.

I believe how I am handling this is the problem because if I press and hold to get audio it loops and sends on each iteration. I am not sure what to do here. (Ideas!!!)


    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))

The server code to handle the audio


    ### 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)

and for completion the binding of the keyboard in Tkinter


    root.bind_all('', keypress)

Any ideas are greatly appreciated how I can make that keypress method work as needed or suggest a better way or maybe I am doing something wrong altogether

*cheers

Please note I have tested it without the encryption methods also and same thing :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

‘画卷フ 2024-12-16 01:36:49

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

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

您应该在有损链路上使用 UDP 和音频压缩,以优雅地处理丢失的数据包。同样在这种情况下,您必须为传出数据包添加时间戳。

Did you run ping or ttcp to test network performance between the 2 hosts?

If you have latency spikes or if some packets are dropped your approach to sending voice stream will suffer badly. TCP will wait for missing packet, report it being lost, wait for retransmit, etc.

You should be using UDP over lossy links and audio compression that handles missing packets gracefully. Also in this case you have to timestamp outgoing packets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文