我应该如何使用 pyaudio 直播

how am I supposed to live stream with pyaudio

我似乎无法让我的代码工作。我希望能够使用 python 将声音实时流式传输到另一台计算机,而我的代码只是在 windows 上退出。我该如何解决这个问题?

开发框:LinuxMint 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:\installers&apps\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "E:\installers&apps\Python38\lib\threading.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:\t\t"+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 & 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 & windows aborts connecting to linux
    ps.listen(1)
    connection, addr = ps.accept()
    print("--- THREAD RECEIVE:\n\tgot 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...连接超时???

连接中止没有任何问题,但我接收声音的方式有问题。

在我的播放线程中,在 while 循环中,我将第一行代码从 data = ps.recv(64 * 2 *2) 改为 data = connection.recv(64 * 2 * 2)。这解决了我的问题,现在我只需要学习更多的音频编码,因为现在我收到“alsa underrun”错误。