как я должен вести прямую трансляцию с pyaudio

#python-3.x #linux #windows #sockets #pyaudio

#python-3.x #linux #Windows #сокеты #pyaudio

Вопрос:

Кажется, я не могу заставить свой код работать. Я хотел бы иметь возможность транслировать звук с помощью python на другой компьютер, и мой код просто завершает работу в Windows. Как я смогу это исправить?

блок разработки: Linux Mint 20 64-разрядный
тестовый компьютер: Windows 10

Я использую pyaudio для записи звука и во время записи отправляю его на другой компьютер. Я не получаю аудиовыхода, и обе Windows и Linux просто случайным образом остановят приложение.

Ошибки Linux:

 starting
IP address: 192.168.0.11
Port:       65535
Send IP:    192.168.0.10
Send Port:  65535

threads starting
--- starting stream ---
sending data to: 192.168.0.10:65534
--- starting receive ---
--- THREAD RECEIVE:
    got connection from: 192.168.0.10
---
ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:869:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:869:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:869:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:869:(find_matching_chmap) Found no matching channel map
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
ALSA lib pcm_oss.c:377:(_snd_pcm_oss_open) Unknown field port
ALSA lib pcm_oss.c:377:(_snd_pcm_oss_open) Unknown field port
ALSA lib pcm_usb_stream.c:486:(_snd_pcm_usb_stream_open) Invalid type for card
ALSA lib pcm_usb_stream.c:486:(_snd_pcm_usb_stream_open) Invalid type for card
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/henrik/PycharmProjects/AudioChat/main.py", line 51, in play
    data = ps.recv(64 * 2 * 2)  # var #1: chunk; var #2: channels; var #3: just to have a safe overhead
OSError: [Errno 107] Transport endpoint is not connected
  

Ошибки Alsa, я думаю, в порядке, разве они просто не указывают на отсутствие микрофона?

ошибки Windows:

 starting
IP address: 192.168.0.10
Port:       65534
Send IP:    192.168.0.11
Send Port:  65535

threads starting
--- starting stream ---
sending data to: 192.168.0.11:65535
--- starting receive ---
Exception in thread Thread-1:
Traceback (most recent call last):
  File "E:installersamp;appsPython38libthreading.py", line 932, in _bootstrap_inner
    self.run()
  File "E:installersamp;appsPython38libthreading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "E:main.py", line 35, in record
    rs.send(data)  # send the sound to the send_to_ip
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
  

из ошибок кажется, что код подключен к Linux, но соединение было прервано, в то время как Linux пытался подключиться к Windows и время ожидания истекло. Linux также считает, что соединение было прервано. почему это должно быть?

мой код:

 #!/usr/bin/python3
# Python Audio Server for realtime audio.

import threading, socket, pyaudio, time  # import all needed codes
from tkinter import *


def startThreads(send_ip, send_to_ip, kill_event):  # function to start threads
    print("IP address:t" send_ip[0] "nPort:tt" str(send_ip[1]))  # print ip address and port
    print("Send IP:t" send_to_ip[0] "nSend Port:t" str(send_ip[1]) "n")  # print the second address set
    print("threads starting")
    r_thread = threading.Thread(target=record, args=(send_to_ip, kill_event))  # create threads
    p_thread = threading.Thread(target=play, args=(send_ip, kill_event))
    r_thread.start()  # start threads
    p_thread.start()


def record(send_to_ip, kill_event):  # the r_thread function
    print("--- starting stream ---")
    print("sending data to: " send_to_ip[0] ":" str(send_to_ip[1]))  # print ip address and port yet again
    rs = socket.socket()  # start socket
    rs.connect((send_to_ip[0], int(send_to_ip[1])))
    # todo: figure out why linux times out connecting to windows amp; windows aborts connecting to linux
    # I believe below code will work?
    rp = pyaudio.PyAudio()  # start pyaudio
    chunk = 64  # pyaudio config
    sample_format = pyaudio.paInt16
    channels = 2
    fs = 44100
    rtime = 3600
    while not kill_event.wait(0):
        rstream = rp.open(format=sample_format, channels=channels, rate=fs, frames_per_buffer=chunk, input=True)  # start recording
        for i in range(0, int(fs / chunk * rtime)):  # record sounds
            data = rstream.read(chunk)  # read sound data
            rs.send(data)  # send the sound to the send_to_ip
        rstream.stop_stream()  # stop recording, then loop
        rstream.close()
    rp.terminate()


def play(send_ip, kill_event):  # the p_thread function
    print("--- starting receive ---")  # working client code
    ps = socket.socket()
    ps.bind((send_ip[0], int(send_ip[1])))  # todo: figure out why linux times out connecting to windows amp; windows aborts connecting to linux
    ps.listen(1)
    connection, addr = ps.accept()
    print("--- THREAD RECEIVE:ntgot connection from: " addr[0] "n---")
    pp = pyaudio.PyAudio()  # start pyaudio
    stream = pp.open(format=pyaudio.paInt16, channels=2, rate=44100, frames_per_buffer=64, output=True)  # open play sound
    while not kill_event.wait(0):
        data = ps.recv(64 * 2 * 2)  # var #1: chunk; var #2: channels; var #3: just to have a safe overhead
        stream.write(data, 64)


if __name__ == "__main__":
    print("starting")
    kill_event = threading.Event()
    UI = Tk()  # creating UI
    UI.title("Audio Connect")  # set window title
    UI.configure(bg="#FFF")  # set window color
    UI.resizable(False, False)  # stop window from being able to resize

    #  this block of code is the title and IP field
    TitleLabel = Label(UI, text="Audio Connect", bg="white").grid(column=0, columnspan=2, padx=1, pady=1)  # the title label
    Label(UI, text="IP: ", bg="white", bd=1).grid(row=1, column=0, padx=1, pady=1)  # IP fields
    IPField = Entry(UI, bd=1)  # IP entry
    IPField.grid(row=1, column=1, padx=1, pady=1)  # write the ip entry to the screen

    # this block of code is the Port field
    Label(UI, text="PORT: ", bg="white", bd=1).grid(row=2, column=0, padx=1, pady=1)  # port fields
    PortField = Entry(UI, text="65535", bd=1)  # port entry
    PortField.grid(row=2, column=1, padx=1, pady=1)  # draw the port entry

    # this is the connect to section, IP
    Label(UI, text="Send To IP: ", bg="white", bd=1).grid(row=3, column=0, padx=1, pady=1)
    SendIP = Entry(UI, bd=1)
    SendIP.grid(row=3, column=1, padx=1, pady=1)

    # connect to port
    Label(UI, text="Port: ", bg="white", bd=1).grid(row=4, column=0, padx=1, pady=1)
    SendPort = Entry(UI, bd=1)
    SendPort.grid(row=4, column=1, padx=1, pady=1)

    # this block of code is the connect button and the scripts for that
    lambdafunc = lambda: startThreads((IPField.get(), int(PortField.get())), (SendIP.get(), SendPort.get()), kill_event)  # the function to run when ConnectButton is pressed
    ConnectButton = Button(UI, text="connect", bg="white", bd=1, relief="solid", command=lambdafunc)
        .grid(row=5, column=0, columnspan=2, sticky="EW", padx=1, pady=1)

    UI.mainloop()

    kill_event.set()
    time.sleep(1)
    exit(0)

  

Не стесняйтесь играть с этим!
Кроме того, правильно ли я отправляю аудио?

резюме: попытка отправить аудио с одного компьютера на другой:
Windows подключается к linux. Соединение прерывается????
linux пытается подключиться к Windows … время ожидания соединения истекло???

Ответ №1:

Не было никаких проблем с прерыванием соединения, а скорее проблема с тем, как я получал звук.

В моем потоке воспроизведения, в цикле while, я изменил свою первую строку кода с data = ps.recv(64 * 2 *2) I needed to put data = connection.recv(64 * 2 * 2) вместо. Это устранило мою проблему, и теперь мне просто нужно изучить еще немного аудиокодирования, потому что теперь я получаю ошибки «alsa underrun».