Проблемы со звуком в сети Python

Здравствуйте, у меня проблемы с передачей звука по сети. В моей локальной системе без расстояния нет проблем, но всякий раз, когда я тестирую удаленную систему, есть звук, но это не голосовой ввод, я хочу его прерывистый / медленный и т. Д. Я верю, что это в том, как я обрабатываю отправку звука, но Я пробовал уже 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)

Приветствуются любые идеи, как я могу заставить этот метод нажатия клавиш работать по мере необходимости или предложить лучший способ, или, может быть, я вообще что-то делаю не так

*ваше здоровье

Обратите внимание, что я тестировал его и без методов шифрования, и то же самое :-)


person ADE    schedule 11.10.2011    source источник
comment
Что ты пытаешься сделать? Это приложение для голосового чата? Должен ли пользователь должен удерживать нажатой клавишу для отправки звука? Почему вы записываете 5 полных секунд звука перед кодированием и отправкой?   -  person John Lyon    schedule 11.10.2011
comment
Привет, Джоззас, да, это приложение голосового чата, и пятисекундная запись была просто для проверки некоторых вещей, которые в настоящее время закомментированы :-) Это должно быть. Вы удерживаете левую клавишу управления и отправляете звук, но, как я сказал в моей локальной системе, это работает нормально, но при отправке в удаленную систему я слышу щелчок щелчок щелчок :-) Я попытался немного поиграть с частотой дискретизации, но я действительно не уверен, что нужно сделать * Ура Спасибо за ваш ответ   -  person ADE    schedule 11.10.2011


Ответы (1)


Вы запускали ping или ttcp для проверки производительности сети между двумя хостами?

Если у вас есть всплески задержки или если некоторые пакеты отброшены, ваш подход к отправке голосового потока сильно пострадает. TCP будет ждать пропущенного пакета, сообщать о его потере, ждать повторной передачи и т. Д.

Вы должны использовать UDP по каналам с потерями и сжатие звука, которое корректно обрабатывает пропущенные пакеты. Также в этом случае вы должны поставить метку времени для исходящих пакетов.

person Dima Tisnek    schedule 27.10.2012