Python网络音频问题
你好,我在网络上传输音频时遇到了一些问题。在我的本地系统上,距离没有问题,但每当我在远程系统上测试时,虽然有音频,但不是我想要的声音输入,听起来很卡顿/延迟。我觉得问题出在我处理音频发送的方式上,但我已经尝试了四天,还是找不到解决办法。
我会把所有相关的代码贴出来,并尽量解释清楚。
这些是常量/全局值
#initilaize Speex speex_enc = speex.Encoder() speex_enc.initialize(speex.SPEEX_MODEID_WB) speex_dec = speex.Decoder() speex_dec.initialize(speex.SPEEX_MODEID_WB) #some constant values chunk = 320 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100
我发现调整采样率的值可以让更多的噪音通过。
下面是用来初始化音频设备的pyAudio代码,这也是全局的。
#initalize PyAudio p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, output = True, frames_per_buffer = chunk)
下一个函数是按键函数,它从麦克风写入数据并通过客户端函数发送。我认为我在这里遇到了问题。
我觉得我处理这个的方式有问题,因为如果我按住键来获取音频,它会循环并在每次迭代时发送。我不太确定该怎么做。(有什么想法吗!!!)
def keypress(event): #chunklist = [] #RECORD_SECONDS = 5 if event.keysym == 'Escape': root.destroy() #x = event.char if event.keysym == 'Control_L': #for i in range(0, 44100 / chunk * RECORD_SECONDS): try: #get data from mic data = stream.read(chunk) except IOError as ex: if ex[1] != pyaudio.paInputOverflowed: raise data = '\x00' * chunk encdata = speex_enc.encode(data) #Encode the data. #chunklist.append(encdata) #send audio client(chr(CMD_AUDIO), encrypt_my_audio_message(encdata))
这是处理音频的服务器代码。
### Server function ### def server(): PORT = 9001 ### Initialize socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((socket.gethostbyname(socket.gethostname()), PORT)) # socket.gethostbyname(socket.gethostname()) server_socket.listen(5) read_list = [server_socket] ### Start receive loop while True: readable, writable, errored = select.select(read_list, [], []) for s in readable: if s is server_socket: conn, addr = s.accept() read_list.append(conn) print "Connection from ", addr else: msg = conn.recv(2048) if msg: cmd, msg = ord(msg[0]),msg[1:] ## get a text message from GUI if cmd == CMD_MSG: listb1.insert(END, decrypt_my_message(msg).strip() + "\n") listb1.yview(END) ## get an audio message elif cmd == CMD_AUDIO: # make sure length is 16 --- HACK --- if len(msg) % 16 != 0: msg += '\x00' * (16 - len(msg) % 16) #decrypt audio data = decrypt_my_message(msg) decdata = speex_dec.decode(data) #Write the data back out to the speaker stream.write(decdata, chunk) else: s.close() read_list.remove(s)
为了完整性,这里是Tkinter中键盘绑定的代码。
root.bind_all('', keypress)
如果你有什么想法,如何让这个按键方法正常工作,或者建议更好的方法,或者我是不是完全做错了什么,都非常感谢。
*谢谢
请注意,我也测试过没有加密方法的情况,结果也是一样的:-)
1 个回答
0
你有没有用 ping 或 ttcp 来测试这两个主机之间的网络性能?
如果你发现延迟有波动,或者有一些数据包丢失,那么你发送语音流的方式就会受到很大影响。因为 TCP 会等着丢失的数据包,报告它丢失了,然后再等着重新发送等等。
在网络不稳定的情况下,你应该使用 UDP,并且使用能够优雅处理丢失数据包的音频压缩方法。此外,你还需要给发送出去的数据包加上时间戳。