Wednesday, June 12, 2013

Real time voice chat example in python using pyaudio

PyAudio home page:

http://people.csail.mit.edu/hubert/pyaudio

There is download links and install instructions for windows/OSX/linux. Following is the code for the audio transmission between server and client in one direction. First the client records the audio from the mic and store in a buffer and then transmit by TCP socket. The server receives the data and play out by speaker.
For Client:

import socket
import pyaudio
import wave

#record
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 40

HOST = ''    # The remote host
PORT = 50007              # The same port as used by the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

p = pyaudio.PyAudio()

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

print("*recording")

frames = []

for i in range(0, int(RATE/CHUNK*RECORD_SECONDS)):
 data  = stream.read(CHUNK)
 frames.append(data)
 s.sendall(data)

print("*done recording")

stream.stop_stream()
stream.close()
p.terminate()
s.close()

print("*closed")

For Server:


# Echo server program
import socket
import pyaudio
import wave
import time

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 4
WAVE_OUTPUT_FILENAME = "server_output.wav"
WIDTH = 2
frames = []

p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(WIDTH),
                channels=CHANNELS,
                rate=RATE,
                output=True,
                frames_per_buffer=CHUNK)


HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
data = conn.recv(1024)

i=1
while data != '':
    stream.write(data)
    data = conn.recv(1024)
    i=i+1
    print i
    frames.append(data)

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

stream.stop_stream()
stream.close()
p.terminate()
conn.close()

In the server part, I store the received audio into an wav file just for record. If you want to do voice chat, you can add another process and deal with the echo cancellation. Also for better audio quality and noise reduction, you may add threshold at the client. Also for better performance under worse network situation, you may need to try compress the audio before transmission.

4 comments:

  1. How to run it on different machines

    ReplyDelete
  2. can I use this server code to recieve audio from android.

    ReplyDelete
  3. I know this is one of the most meaningful information for me. And I'm animated reading your article. But should remark on some general things, the website style is perfect; the articles are great. Thanks for the ton of tangible and attainable help. Allo Talk

    ReplyDelete