UDP音频传输:播放的声音有很大的噪音。

9
我不知道如何解决这个问题,请帮助我 :)
我想将一个PC录制的声音通过UDP发送到另一台PC并播放它。
程序可能工作得很好,但声音中仍含有不适的噪音。 当我尝试在一个程序序列中录制和播放声音时,它可以正常工作,没有噪音。 但是,在使用UDP时,即使在同一台PC上使用IP 127.0.0.1,也会出现噪音。 起初,我认为原因是由于在其他PC上播放的声音超出了范围,我通过制作缓冲区来解决它。 它减少了一点噪音,但几乎所有的噪音仍然存在。
以下是代码
客户端
import pyaudio
import socket
from threading import Thread

frames = []

def udpStream():
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    

    while True:
        if len(frames) > 0:
            udp.sendto(frames.pop(0), ("127.0.0.1", 12345))

    udp.close()

def record(stream, CHUNK):    
    while True:
        frames.append(stream.read(CHUNK))

if __name__ == "__main__":
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    RATE = 44100

    p = pyaudio.PyAudio()

    stream = p.open(format = FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    input = True,
                    frames_per_buffer = CHUNK,
                    )

    Tr = Thread(target = record, args = (stream, CHUNK,))
    Ts = Thread(target = udpStream)
    Tr.setDaemon(True)
    Ts.setDaemon(True)
    Tr.start()
    Ts.start()
    Tr.join()
    Ts.join()

服务器

import pyaudio
import socket
from threading import Thread

frames = []

def udpStream(CHUNK):

    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.bind(("127.0.0.1", 12345))

    while True:
        soundData, addr = udp.recvfrom(CHUNK)
        frames.append(soundData)

    udp.close()

def play(stream, CHUNK):
    BUFFER = 10
    while True:
            if len(frames) == BUFFER:
                while True:
                    stream.write(frames.pop(0), CHUNK)

if __name__ == "__main__":
    FORMAT = pyaudio.paInt16
    CHUNK = 1024
    CHANNELS = 2
    RATE = 44100

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                    channels = CHANNELS,
                    rate = RATE,
                    output = True,
                    frames_per_buffer = CHUNK,
                    )

    Ts = Thread(target = udpStream, args=(CHUNK,))
    Tp = Thread(target = play, args=(stream, CHUNK,))
    Ts.setDaemon(True)
    Tp.setDaemon(True)
    Ts.start()
    Tp.start()
    Ts.join()
    Tp.join()

抱歉源代码比较长,欢迎尝试这个程序。


它是否有噪音(例如由于数据包丢失或错误的数据处理而导致数据损坏),或者是否出现卡顿(即是否存在时间/延迟/并发问题(我不确定Python的“线程”是否是解耦流检索和播放流的正确选择)。 - Dr. Jan-Philip Gehrcke
你应该将发送和接收的内容进行比较。也许它们不同。我可以想象,网络层会在你的数据上切换高位和低位或类似的事情。这将导致严重的噪音。 - Alfe
@Jan-PhilipGehrcke,我没有注意到数据包丢失的问题,因为当我尝试使用“image” UDP传输的版本时,它能够正常工作。谢谢!我会考虑数据包丢失的问题,并尝试进行TCP实现以比较数据。 - ami_GS
@Alfe 谢谢!我想你也可能会谈到数据包丢失。我尝试比较这些数据。 - ami_GS
首先尝试使用TCP。如果发现TCP的性能不合理,那我再考虑使用UDP。 - Clarus
2个回答

10

我已经搜索了这个噪音的原因。最终我能够检测出为什么会发生这种情况。

实际上,这个程序的UDP传输没有引起数据包丢失。

即使它引起了数据包丢失,声音也不会有如此严重的噪音。


这个程序正确地发送了数据,几乎没有数据包丢失,但是 "receive" 方法无法正确接收数据。


在服务器程序中

def udpStream(CHUNK):

    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.bind(("127.0.0.1", 12345))

    while True:
        soundData, addr = udp.recvfrom(CHUNK)
        frames.append(soundData)

    udp.close()

这个程序只能读取到“25%”的数据。(我已经检查了数据的数量)

因此,我尝试接收多倍的数据(CHANNELS * 2)。

        soundData, addr = udp.recvfrom(CHUNK * CHANNELS * 2)

这意味着声音数据可以完全接收。

最终,一个电脑记录的声音在另一个电脑中播放时没有噪音。


问题与此问题有关(我在Windows上遇到了10040错误):https://stackoverflow.com/questions/9378146/how-to-easily-solve-the-10040-message-too-long-error-on-wsock2。感谢您的代码,它非常适合培训目的! - bomben

0

我遇到了同样的问题,但是你的解决方案并没有帮到我。我发现使用

stream.write(frames.pop(0))

替代

stream.write(frames.pop(0), CHUNK)

清除接收信号中的所有噪音。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接