断断续续地通过UDP接收语音数据

时间:2019-04-03 13:35:26

标签: python sockets udp voip

我正在尝试通过UDP套接字发送语音数据,但是客户端接收到的语音数据不稳定。

当前,我在同一台计算机上运行server.pyclient.py。也许这可能是问题所在?另一种可能性是正在发送简短的语音数据包,然后播放速度足够快,以至于在短时间内结束。这也可能是硬件问题(我目前正在使用2015 Macbook Pro)。

我已经在TCP中实现了该程序,并且可以完美运行。但是,该程序的主要目的是处理大量客户。

我将尝试在不同的计算机上运行这些脚本,以查看其是否有效。理想的结果是使接收到的语音数据流畅地播放,而不是使音频以断断续续的形式播放。

server.py

import socket
import pyaudio
import threading
from os import system

system('clear')

# Socket
host = socket.gethostbyname(socket.gethostname())
port = 6000
buffer = 2048
clients = []

# Audio
audio = pyaudio.PyAudio()
chunk = int(1024 * 4)


def client_listener():
    while True:
        data, address = host_socket.recvfrom(buffer)
        if address not in clients:
            print(f'New client: {address[0]}:{address[1]}')
            clients.append(address)
            print(clients)


with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as host_socket:
    try:
        host_socket.bind((host, port))
        print(f'Server hosted at {host}:{port}\n')

        print('Starting listener thread...')
        listener_thread = threading.Thread(target=client_listener)
        listener_thread.daemon = True
        listener_thread.start()
        print('Listener thread started!')

        print('Initiating microphone...')
        stream = audio.open(format=pyaudio.paInt16,
                            channels=1,
                            rate=44100,
                            input=True,
                            frames_per_buffer=chunk)

        print('Recording!')
        while True:
            voice_data = stream.read(chunk, exception_on_overflow=False)
            for client in clients:
                host_socket.sendto(voice_data, client)
    except socket.error as error:
        print(str(error))
        stream.close()
        host_socket.close()
    except KeyboardInterrupt:
        stream.close()
        host_socket.close()
    finally:
        stream.close()
        host_socket.close()

client.py

import socket
import pyaudio
from os import system

# Socket
host = socket.gethostbyname(socket.gethostname())
port = 6000

system('clear')

# Audio
audio = pyaudio.PyAudio()
chunk = int(1024 * 4)

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client_socket:
    try:
        client_socket.sendto(' '.encode('utf-8'), (host, port))

        stream = audio.open(format=pyaudio.paInt16,
                            channels=1,
                            rate=44100,
                            output=True,
                            frames_per_buffer=chunk)

        while True:
            voice_data = client_socket.recv(chunk)
            print(voice_data)
            stream.write(voice_data)
    except socket.error as error:
        print(str(error))
        stream.close()
        client_socket.close()
    except KeyboardInterrupt:
        stream.close()
        client_socket.close()
    finally:
        stream.close()
        client_socket.close()

2 个答案:

答案 0 :(得分:0)

从网络角度来看,我可以理解为什么TCP在UDP上可以完美地工作。 传输控制协议是一种纠错协议(也称为无损协议),它跟踪发送的内容以确定错误。如果由于某种原因发送的数据不完整,则会要求重新发送。 用户数据报协议不是纠错,而是像流媒体一样进行流媒体传输。 我不了解python,但是我建议如果您创建自己的错误纠正方法,那么如果您要使用UDP,它将获得与TCP相同的效果。诸如MD5检查之类的东西,接收者会知道“此信息包已完成”。

答案 1 :(得分:0)

您需要某种抖动缓冲区-看一下一些开源SIP / RTP应用程序,因为此功能在实践中可能非常复杂,还可以处理数据包重新排序,再加上某种PLC来补偿数据包丢失,并且自适应延迟取决于实际的网络抖动。如果您拥有多个设备,那么也很难避免时钟偏斜。

我也不完全确定python是否适用于具有大量客户端的服务器。我想python + pjsip更典型。