Skip to content

Instantly share code, notes, and snippets.

@abhigenie92
Last active April 22, 2016 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abhigenie92/5ef6ac6f535a8c70509ff6de3e3da05b to your computer and use it in GitHub Desktop.
Save abhigenie92/5ef6ac6f535a8c70509ff6de3e3da05b to your computer and use it in GitHub Desktop.
from twisted.internet.protocol import ClientFactory
import pdb,json
from twisted.protocols.basic import NetstringReceiver
from twisted.internet.defer import inlineCallbacks
from twisted.internet.threads import deferToThread
from Queue import Queue
# audio imports
import pyaudio,wave,threading
class AudioClient(NetstringReceiver):
#audio parameters
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
## initialisation
def __init__(self,factory,canvas_obj):
'''initiates with factory and canvas object
Reasons:
factory:
canvas object:
'''
self.factory = factory
self.canvas_obj=canvas_obj
def connectionMade(self):
'''sends the username of the client to register the protocol at remore server with corresponding
address'''
print "Connected to audio remote server"
self.sendString(json.dumps({'username':self.factory.username}))
# start recording and sending audio
if self.factory.canvas_obj.allow_all or self.factory.canvas_obj.client_state=='server' \
or self.factory.canvas_obj.client_audio_send:
self.start_audio_stream()
# start receiving and playing audio
self.receive_audio_stream()
## record and send
def start_audio_stream(self):
'''creates an audio stream for sending data
A callback is defined on send_audio_data() to send the stream
'''
# create PyAudio Object
self.send_stream_Pyobj=pyaudio.PyAudio()
self.send_rate=int(self.send_stream_Pyobj.get_device_info_by_index(0)['defaultSampleRate']/4)
# create stream
self.send_stream=self.send_stream_Pyobj.open(format=self.FORMAT,channels=self.CHANNELS,
rate=self.send_rate,input=True,frames_per_buffer=self.CHUNK,output=False)
# start the stream
self.send_stream.start_stream()
self.send_audio_data_thread = threading.Thread(name='send_audio_data'\
,target=self.send_audio_data)
self.send_audio_data_thread.daemon=True
self.send_audio_data_thread.start()
@inlineCallbacks
def send_audio_data(self):
'''sends the audio chunk to remote server as string'''
while True:
audio_data = yield self.send_stream.read(self.CHUNK)
self.sendString(audio_data)
## receive and play
def receive_audio_stream(self):
''' 1. creates an audio stream for receiving data
2. creates an audio queue
3. initiates a thread for playing the received audio
'''
# create PyAudio Object
self.receive_stream_Pyobj=pyaudio.PyAudio()
self.receive_rate=int(self.receive_stream_Pyobj.get_device_info_by_index(0)['defaultSampleRate']/4)
# create stream
self.stream_receive = self.receive_stream_Pyobj.open(format=self.FORMAT,channels=self.CHANNELS,
rate=self.receive_rate,output=True,input=False)
# start the receiving stream
self.stream_receive.start_stream()
# create a queue which gets filled in from data received
self.recv_audio_queue=DeferredQueue() # queue that stores the audio received
# create and start the thread for playing the received audio
self.play_audio_received_thread = threading.Thread(name='play_audio_received'\
,target=self.play_audio_received)
self.play_audio_received_thread.daemon=True
self.play_audio_received_thread.start()
def stringReceived(self,data):
'''appends the audio string received to queue(recv_audio_queue) which is played by
play_audio_received thread'''
self.recv_audio_queue.put(data)
def play_audio_received(self):
while True:
data=self.recv_audio_queue.get() # get data from queue
self.stream_receive.write(data)
self.recv_audio_queue.task_done()
## close streams, terminate pyaudio objects and stop threads
def connectionLost(self, reason):
# close send audio if exists
try:
self.send_stream.stop_stream()
self.send_stream.close()
self.send_stream_Pyobj.terminate()
except:
print "Send audio stream and object doesn't exist"
# close receive audio stream and thread
try:
self.stream_receive.stop_stream()
self.stream_receive.close()
self.receive_stream_Pyobj.terminate()
self.play_audio_received_thread.stopped=True
except:
print "Receive audio stream and object doesn't exist"
class AudioClientFactory(ClientFactory):
def __init__(self, canvas_obj,username):
self.canvas_obj = canvas_obj
self.username=username
def buildProtocol(self, addr):
self.protocol=AudioClient(self,self.canvas_obj)
return self.protocol
if __name__ == '__main__':
from twisted.internet import reactor
reactor.connectTCP("127.0.0.1",3036,AudioClientFactory('junkcanvas_obj','something'))
reactor.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment