在 Python Socket 中流式传输实时数据

在进行一项实时应用程序的开发中,该应用程序需要对实时音频进行录制,随后将其发送给语音识别器,并接收识别结果。其中,需要使用 Socket 进行数据发送和接收,并在调试过程中使用了一个 wave 文件。在进行音频读取时,需要将音频发送出去并模拟成正在实时播放的效果。最初,使用 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. 解决方案

对于发送实时数据,有两种方法可供选择:

  • 发送者以特定速率发送数据: 在这种情况下,发送者会针对特定时间帧发送数据,之后再发送下一帧数据,以此类推。由于每个数据包在传输过程中可能会有不同的延迟,因此需要添加某种时间戳,以便接收者知道何时播放该数据包。TCP 不是一个好的选择,因为它会在数据包丢失时进行重传,而重传的数据包会到达得太晚。因此,在这些情况下通常使用 UDP,并且编解码器需要能够处理数据包丢失的情况。这种协议的一个典型例子是 RTP,它用于 VoIP 和其他场合。
  • 接收者以特定速率接收数据: 这只适用于软实时,例如可以接受几秒或更长时间的延迟的情况。在这种情况下,发送者只需使用 TCP 发送数据,并且流中的每个“帧”都包含一些时间戳,以便接收者知道何时播放它。接收者会根据需要以快或慢的速度读取数据包。如果数据包到达速度慢于所需速度,则需要暂停播放并等待更多数据(如在 YouTube 等网站上看到的那样);如果数据包到达速度快于所需速度,则只会以所需的慢速度读取这些数据包,这将自动导致发送者降低发送速度(TCP 的固有行为)。

根据程序的原始方法,发送者以特定速度传输数据。若要继续使用这种方法,应进行以下操作:

  • 使用 UDP 代替 TCP,这样可以避免因数据包丢失而导致的重传引起的延迟。
  • 使用能够处理数据包丢失的编解码器,例如 G.711 或类似编解码器。
  • 向每个数据包添加时间戳,以便发送者知道何时播放该数据包。
  • 添加精确的计时:使用 sleep 本身并不能计入发送数据包之前所需的时间,因此应该存储开始时间并计算每个数据包需要发送的时间(例如 next_time = last_time+time_span_in_packet)。然后,仅针对 next_time - current_time 进行睡眠。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值