微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何让语音延迟消失?

如何解决如何让语音延迟消失?

我试图做一些类似于 VoIP 的事情,我记录语音并使用 UDP 将其发送到网络上的另一个程序,这不是关于加密的问题,但是当我运行代码时,它起作用了,除了声音断断续续。

换句话说,在我丢弃的某些词中,我可以完整地听到它们,但其他较长的短语总是可以识别出信号被中断并且他等待另一个数据包被传送以继续传输的时刻。

我想问如何让我的声音在接收端听起来柔和?因为我尝试使用线程来尝试优化录制但没有太大区别,我不知道还能去哪里。

服务器端:

import sounddevice as sd
import socket,pickle

s = socket.socket(socket.AF_INET,socket.soCK_DGRAM)

h = socket.gethostbyname(socket.gethostname())

s.bind((h,9001))

print("Servidor Rodando em "+str(h)+":9001")

while True:
    r = pickle.loads(s.recvfrom(102400)[0])
    sd.play(r,4410)

客户端:

import sounddevice as sd
import socket,pickle,threading

s = socket.socket(socket.AF_INET,socket.soCK_DGRAM)

ip = input("IP >> ")

data = None

def Enviar():
    global data
    s.sendto(pickle.dumps(data),(ip,9001))

while True:
    data = sd.rec(4410,samplerate=4410,channels=2)
    sd.wait()
    threading.Thread(target=Enviar,args=()).start()

解决方法

对于计算机音频,接收计算机的声卡有一个采样时钟,用于确定将音频采样值转换为驱动扬声器的电信号的速度。采样时钟以固定速率运行(例如每秒 48000 次采样,或您设置的任何值),并且为了使音频听起来正确,必须每隔 1/48000 将一个新的音频采样送入声卡一秒钟。

为了减少主机的 CPU 负载,声卡通常会内置音频缓冲区,这样就不必强制 CPU 每 1/48000 秒唤醒一次,只发送一个样本,您可以改为让 CPU 唤醒,例如每 100mS 一次,一次写入 4800 个样本。然后,声卡的内部电子设备将管理从该缓冲区馈送单个样本。

因此,连续声音的秘诀是永远不要让声卡的缓冲区变空。当缓冲区被排空时(因此声卡无法在需要播放的瞬间播放下一个样本),这被称为音频欠载,它会导致故障在音频中,正如你所听到的。

防止欠载的最简单方法是在接收计算机上缓冲更多音频,以便在欠载发生之前可以通过更多时间而不接收数据。当然,这样做的缺点是发送方发送数据和接收方播放数据之间会有更多的延迟;这可能没问题,例如流式传输录制的音乐,但不太适合进行实时语音对话。

更难的方法是确保所有数据在短时间内通过网络;要以保证的可靠性做到这一点,您需要一个 special networking switch that allows devices to pre-reserve bandwidth 以便他们可以保证他们的音频数据包不会被丢弃。没有这个保证,你只能希望得到最好的结果;在有线以太网连接上,您通常可以避开少量音频通道,但通过 WiFi,正如您所见,网络通常非常不可靠,因此在许多情况下您可能会听到欠载故障,除非你拨了很多缓冲。

某些协议使用 Forward Error Correction 数学来编码音频,即使 UDP 数据包的某些子集丢失,原始音频样本值仍然可以从接收到的剩余数据包中重建。这在一定程度上增加了整体带宽使用量,但只要丢弃的数据包数量相对较少,它就可以避免音频出现故障。不过,我对它们的工作方式不是很熟悉,所以我不能多说。

最后一种方法(我认为这就是您要问的)是让接收计算机以某种方式尝试通过为丢失的音频制作自己的替换样本值来“覆盖”丢失的音频。有一些语音协议试图做到这一点,取得了不同程度的成功(你可能在手机连接不好的情况下交谈时听到了结果),但恕我直言,这并不值得实施,因为仍然会有明显的故障在音频中;只是一个听起来不同的故障。如果您没有更多的样本跟随它们(至少避免突然的“流行”),然后在接收到新的(欠载后)音频之后,将接收到的音频的最后一个样本淡出到零可能是值得的,淡入新接收的音频的第一个样本(以避免第二次“流行”),但这只会使故障不那么烦人;它没有摆脱它。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?