Choppy получил голосовые данные по UDP - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь отправить голосовые данные через сокет UDP, однако полученные голосовые данные клиентом изменчивы.

В настоящее время я использую server.py и client.py на одной машине. Возможно, это может быть проблемой? Другая возможность заключается в том, что короткие пакеты голосовых данных отправляются, а затем воспроизводятся достаточно быстро, чтобы на короткое время они заканчивались. Это также может быть аппаратная проблема (в настоящее время я использую Macbook Pro 2015 года).

Я реализовал эту программу в 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 голосов
/ 03 апреля 2019

Вам нужен какой-то буфер дрожания - взгляните на некоторые приложения SIP / RTP с открытым исходным кодом, так как эта функция может быть довольно сложной на практике, обрабатывая также переупорядочение пакетов в сочетании с каким-либо ПЛК для компенсации потери пакетов и садаптивная задержка в зависимости от фактического дрожания сети.Если у вас есть более одного устройства, было бы также трудно избежать перекоса часов.

Я также не совсем уверен, является ли Python хорошим выбором для сервера с большим количеством клиентов.Я думаю, что Python + PJSIP является более типичным.

0 голосов
/ 03 апреля 2019

С сетевой точки зрения я понимаю, почему TCP работал безупречно по UDP. Протокол управления передачей - это протокол исправления ошибок - он же без потерь - он отслеживает то, что отправляется для определения ошибок. Если отправленные данные не полны по какой-либо причине, он просит отправить их повторно. Протокол пользовательских дейтаграмм не исправляет ошибки и больше похож на потоковую передачу - один за другим. Я не знаю Python, но я хотел бы предложить, что если вы создадите свой собственный метод исправления ошибок, то он получит тот же эффект, что и TCP, если вы собираетесь использовать UDP. Что-то вроде проверки MD5, что-то, что получатель узнает, что «этот пакет информации завершен».

...