如何在Python socket中流式传输实时数据
我正在开发一个实时应用程序。这个应用程序会接收实时音频,发送给识别器,然后得到结果。我使用一个套接字来进行发送和接收。为了调试,我使用了一个波形文件。所以我读取音频,想要像实时播放一样发送音频。我尝试使用time.sleep来同步发送,但这导致发送速度比实时还慢。我是不是应该使用两个线程,一个用于发送,一个用于接收呢?
while True:
readable, writable, exceptional = select.select([s], [s], [])
if readable:
try:
data = s.recv(1024)
except:
break
if data == "":
break
else:
for line in data.split("\n"):
if not line: continue
t, w = line.split()
if w == "<EOL>":
w = ""
addResult(t, w)
if writable:
now = time.time()
if (now - start_time) / 0.01 >= frame_count - 5:
frame_count += 1
data = wav.readframes(80)
if data is None:
s.shutdown(s.SHUT_WR)
continue
s.send(struct.pack('I', len(data)) + data)
else:
time.sleep(0.005)
if exceptional:
print "Hangup"
break
1 个回答
4
发送实时数据有两种方法:
- 发送方以特定的速率发送数据:在这种情况下,发送方会在特定的时间段内发送数据,然后再发送下一段。由于每个数据包在传输过程中可能会有不同的延迟,因此会添加某种时间戳,以便接收方知道什么时候播放这个数据包。在这种情况下,使用TCP并不是一个好主意,因为如果数据包丢失,TCP会重新发送,而重新发送的数据包到达时可能已经太晚了。所以通常会使用UDP,并且编码器需要能够处理数据包丢失。这种协议的典型例子是RTP,它在VoIP和其他场景中使用。
- 接收方以特定的速率接收数据:这仅适用于软实时场景,比如延迟几秒钟或更长时间是可以接受的。在这种情况下,发送方只需使用TCP发送数据,每个流中的“帧”都包含一些时间戳,以便接收方知道什么时候播放它。接收方会根据需要快速或慢速读取数据包。如果数据包到达的速度比需要的慢,它就需要暂停播放,等待更多数据(就像在YouTube等平台上看到的那样);如果数据包到达的速度比需要的快,它会慢慢读取,这样会自动导致发送方减慢发送速度(这是TCP的固有特性)。
你程序的原始方法是发送方以特定的速率传输数据。要继续这种方式,你应该:
- 使用UDP而不是TCP,这样就不会因为数据包丢失而导致的重传造成延迟
- 使用能够处理数据包丢失的编码器,比如G.711或类似的
- 给每个数据包添加时间戳,以便发送方知道什么时候播放它
- 添加准确的时间控制:使用sleep本身并不能考虑发送数据包前所需的时间,因此你应该记录开始时间,并计算每个数据包需要发送的时间(例如
next_time = last_time + time_span_in_packet
)。然后只需睡眠next_time - current_time
的时间。