I have been trying to transmit an audio stream over the network with pyaudio using RTP/UDP.
Since I could find any RTP library so I did my own encoding with some help from articles online.
The problem I am facing right now is when I don't use the RTP library everything works well but when I use the RTP encoding there is some latency issue, I receive chopped-up audio on the receiver side.
I am sharing sender , reveiver and rtp code here.
Any help is appreciated.
Sender_rtp.py
import pyaudio
import sys
import socket
import datetime
import pyrtp_2 as rtp
import random
HOST = sys.argv[1]
PORT = sys.argv[2]
data = bytes() # Stream of audio bytes
CHUNK_SIZE = 1024
BROADCAST_SIZE = 1024
CHANNELS = 1
FORMAT = pyaudio.paInt16 # 2 bytes size
RATE = 16000
# instantiate PyAudio (1)
p = pyaudio.PyAudio()
# define callback (2)
def pyaudio_callback(in_data, frame_count, time_info, status):
global data
data += in_data
return (None, pyaudio.paContinue)
# open stream (3)
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK_SIZE,
stream_callback=pyaudio_callback)
# start the stream (4)
stream.start_stream()
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#sock.bind((HOST, int(PORT)))
def send_data():
global data
print()
if (len(data) > BROADCAST_SIZE):
packet_vars = {'version' : 2,
'padding' : 0,
'extension' : 0,
'csi_count' : 0,
'marker' : 0,
'payload_type' : 97,
'sequence_number' : random.randint(1,9999),
'timestamp' : random.randint(1,9999),
'ssrc' : 185755418,
'payload' : data}
rtp_packet = rtp.GenerateRTP(packet_vars)
sock.sendto(rtp_packet[:BROADCAST_SIZE], (HOST, int(PORT)))
data = data[BROADCAST_SIZE:]
print(f'Sent {str(BROADCAST_SIZE)} bytes of audio. {datetime.datetime.now().time()}')
try:
while True:
send_data()
except KeyboardInterrupt:
print('\nClosing stream...')
stream.stop_stream()
stream.close()
p.terminate()
sock.close()
Receiver_rtp.py
import pyaudio
import sys
import socket
import pyrtp_2 as rtp
HOST = sys.argv[1]
PORT = sys.argv[2]
data = bytes() # Stream of audio bytes
is_receiving = False
CHUNK_SIZE = 1024 # Size of frame window to write audio (frames_per_buffer)
BROADCAST_SIZE = 1024 # Socket receives audio with this size
BUFFER_SIZE = BROADCAST_SIZE * 4 # Receive this amount of data before playback
CHANNELS = 1
FORMAT = pyaudio.paInt16 # 2 bytes size
RATE = 16000
# instantiate PyAudio (1)
p = pyaudio.PyAudio()
# define callback (2)
def pyaudio_callback(in_data, frame_count, time_info, status):
if not is_receiving:
return (bytes([0] * frame_count * CHANNELS * 2), pyaudio.paContinue)
global data
try:
# Cut the data, if it started to bufferize
if len(data) >= BUFFER_SIZE * 2:
print('Cutting Audio Buffer..')
data = data[-BUFFER_SIZE:]
avail_data_count = min(frame_count * CHANNELS * 2, len(data))
return_data = data[:avail_data_count]
data = data[avail_data_count:]
# Inflate end of the array with zeros, if there is not enough audio.
return_data += bytes([0] * (frame_count * CHANNELS * 2 - avail_data_count))
return (return_data, pyaudio.paContinue)
except:
print('Exception in pyaudio_callback...')
# open stream (3)
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
output=True,
frames_per_buffer=CHUNK_SIZE,
stream_callback=pyaudio_callback)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((HOST, int(PORT)))
#sock.listen(1)
#connection, client_address = sock.accept()
print('Socket bind succeed.')
try:
while True:
new_data = sock.recv(BROADCAST_SIZE)
print(f"Incoming raw data : {type(new_data)}")
rtp_packet = rtp.DecodeRTP(new_data)
payload = rtp_packet['payload']
##break
data += rtp_packet['payload']
if len(data) >= BUFFER_SIZE and not is_receiving:
is_receiving = True
# start stream (4)
stream.start_stream()
print(f'Stream started, when {len(data)} bytes of data were received.\nThis causes {str(len(data) / RATE)} seconds of latency')
except KeyboardInterrupt:
print('\nClosing socket and stream...')
sock.close()
stream.stop_stream()
stream.close()
p.terminate()
pyrtp.py
def GenerateRTP(packet_vars):
#The first twelve octates are present in every RTP packet.
#The first octet is the version number of the RTP packet.
#The second octet is the padding bit.
#The third octet is the extension bit.
#The fourth octet is the CSRC count.
#The fifth octet is the marker bit.
#The sixth octet is the payload type.
#The seventh to twelve octets are the sequence number.
#The thirteen to eighteen octets are the timestamp.
#The nineteen to twenty-four octets are the synchronization source (SSRC).
#The remaining octets are the payload data.
#Generate fist byte of the header a binary string:
version = format(packet_vars['version'], 'b').zfill(2)
padding = format(packet_vars['padding'], 'b')
extension = format(packet_vars['extension'], 'b')
csrc_count = format(packet_vars['csi_count'], 'b').zfill(4)
byte1 = format(int((version + padding + extension + csrc_count), 2), 'x').zfill(2)
#Generate second byte of the header as binary string:
marker = format(packet_vars['marker'], 'b')
payload_type = format(packet_vars['payload_type'], 'b').zfill(7)
byte2 = format(int((marker + payload_type), 2), 'x').zfill(2)
sequence_number = format(packet_vars['sequence_number'], 'x').zfill(4)
timestamp = format(packet_vars['timestamp'], 'x').zfill(8)
ssrc = format(packet_vars['ssrc'], 'x').zfill(8)
payload = packet_vars['payload'].hex()
packet = byte1 + byte2 + sequence_number + timestamp + ssrc + payload
return packet.encode()
def DecodeRTP(packet_bytes):
#return dict of variables from the packet
packet_vars = {}
byte1 = packet_bytes[0:2]
byte1 = int(byte1, 16)
byte1 = format(byte1, 'b').zfill(8)
packet_vars['version'] = int(byte1[0:2],2)
packet_vars['padding'] = int(byte1[2:3],2)
packet_vars['extension'] = int(byte1[3:4])
packet_vars['csi_count'] = int(byte1[4:8], 2)
byte2 = packet_bytes[2:4]
byte2 = int(byte2, 16)
byte2 = format(byte2, 'b').zfill(8)
packet_vars['marker'] = int(byte2[0:1])
packet_vars['payload_type'] = int(byte2[1:8], 2)
packet_vars['sequence_number'] = int(packet_bytes[4:8], 16)
packet_vars['timestamp'] = int(packet_bytes[8:16], 16)
packet_vars['ssrc'] = int(packet_bytes[16:24], 16)
payload = packet_bytes[24:]
packet_vars['payload'] = bytes.fromhex(payload.decode())
#print(f"payload 4: {type(payload)} {payload}")
return packet_vars
Related
I am creating a very simple rdt 2.2 socket program that transfers an image file dictated as "Cat.bmp" from client to server. Once the client reads the first line of data from the bmp file, it sends it to the server, and then the server will continue to repeat reading this same line in an infinite loop. I have no idea why this won't allow the client to send new data. Any suggestions on how to fix this would be very appreciated.
Client.py
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
senderSocket.sendto(sendPacket, (IP, Port))
def dataError(receivePacket):
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
def isACK(receivePacket, ACKVal):
if (receivePacket[0] == ACKVal):
return True
else:
return False
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
unpacker = struct.Struct('I I 8s 32s')
senderSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
senderSocket.connect((IP , Port))
print("UDP IP:", IP)
print("UDP port:", Port)
filename = 'Cat.bmp'
file = open(filename , 'rb')
# current data item being processed
data = file.read(bufferSize)
currentSequence = 0
currentACK = 0
while (data):
rdtSend(currentSequence, currentACK , data)
packet, addr = senderSocket.recvfrom(bufferSize)
print(packet)
print("Received from: ", addr)
receivePacket = unpacker.unpack(packet)
if(dataError(receivePacket) == False and isACK(receivePacket , currentACK) == True):
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
data = file.read(bufferSize)
print("sending more data")
else:
print("Resending packet")
file.close()
senderSocket.close
Server.py
import socket
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
#This is where it gets the UDP packet
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
receiverSocket.sendto(sendPacket, (IP, Port))
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
#Function that checks the packet for corruption
def dataError(receivePacket):
# Calculate new checksum of the [ ACK, SEQ, DATA ]
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
#IP Address for local communications
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
# Integer, Integer, 8 letter char array, 32 letter char array
unpacker = struct.Struct('I I 8s 32s')
# Create the actual UDP socket for the server
receiverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the local IP address and port
receiverSocket.bind((IP, Port))
currentACK = 0
currentSequence = 0
dataFile = open('receive.bmp' , 'wb')
print("Listening")
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
#Where the previous functions are used to send the packets back to the client
while receivedPacket[2]:
print("Received from:", addr)
print("Data Received:" , receivedPacket[2])
#This compares checksums to see if there are errors
if not dataError(receivedPacket):
dataFile.write(receivedPacket[2])
# Built checksum [ACK, SEQ, DATA]
ACK = receivedPacket[0]
SEQ = receivedPacket[1]
DATA = b''
print('Packeting')
rdtSend(currentSequence , currentACK , DATA)
print('Sent')
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
else:
print('Packet error')
checksumVal = makeChecksum(packet[0] + 1, (packet[1] + 1) % 2, b'')
packet = makepacket(packet[0] + 1, (packet[1] + 1) % 2, b'', checksumVal)
print('Packeting')
receiverSocket.sendto(packet, addr)
print('Sent')
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
dataFile.close()
receiverSocket.close```
I am trying to write a bit of code to create a 2 person live chat application using Python 3. The code is working in the sense of having live audio and live video, (as tested by running the server and 2 clients on the same device), with the Client-Side code running most of the logic and running the camera and audio feeds to send through the server, (which also works as a form of handshake between the 2 clients with little logic aside from if a client sends video and/or audio to send it to the other client), to have the client-side code to get the audio and video to play.
fair warning, this code is a bit messy and is not optimized for fast performance
Client-Side Code:
import cv2
from socket import socket, AF_INET, SOCK_STREAM
from imutils.video import WebcamVideoStream
import pyaudio
from array import array
from threading import Thread
import numpy as np
import zlib
import struct
HOST = input("Enter Server IP\n")
PORT_VIDEO = 3000
PORT_AUDIO = 4000
BufferSize = 4096
CHUNK=1024
lnF = 640*480*3
FORMAT=pyaudio.paInt16
CHANNELS=2
RATE=44100
def SendAudio():
while True:
data = stream.read(CHUNK)
dataChunk = array('h', data)
vol = max(dataChunk)
clientAudioSocket.sendall(data)
def RecieveAudio():
while True:
data = recvallAudio(BufferSize)
stream.write(data)
def recvallAudio(size):
databytes = b''
while len(databytes) != size:
to_read = size - len(databytes)
if to_read > (4 * CHUNK):
databytes += clientAudioSocket.recv(4 * CHUNK)
else:
databytes += clientAudioSocket.recv(to_read)
return databytes
def SendFrame():
while True:
try:
frame = wvs.read()
cv2_im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = cv2.resize(frame, (640, 480))
frame = np.array(frame, dtype = np.uint8).reshape(1, lnF)
jpg_as_text = bytearray(frame)
databytes = zlib.compress(jpg_as_text, 9)
length = struct.pack('!I', len(databytes))
bytesToBeSend = b''
clientVideoSocket.sendall(length)
while len(databytes) > 0:
if (5000 * CHUNK) <= len(databytes):
bytesToBeSend = databytes[:(5000 * CHUNK)]
databytes = databytes[(5000 * CHUNK):]
clientVideoSocket.sendall(bytesToBeSend)
else:
bytesToBeSend = databytes
clientVideoSocket.sendall(bytesToBeSend)
databytes = b''
# ~ print("##### Data Sent!! #####")
except:
continue
def RecieveFrame():
while True:
try:
lengthbuf = recvallVideo(4)
length, = struct.unpack('!I', lengthbuf)
databytes = recvallVideo(length)
img = zlib.decompress(databytes)
if len(databytes) == length:
# ~ print("Recieving Media..")
# ~ print("Image Frame Size:- {}".format(len(img)))
img = np.array(list(img))
img = np.array(img, dtype = np.uint8).reshape(480, 640, 3)
cv2.imshow("Stream", img)
if cv2.waitKey(1) == 27:
cv2.destroyAllWindows()
else:
print("Data CORRUPTED")
except:
continue
def recvallVideo(size):
databytes = b''
while len(databytes) != size:
to_read = size - len(databytes)
if to_read > (5000 * CHUNK):
databytes += clientVideoSocket.recv(5000 * CHUNK)
else:
databytes += clientVideoSocket.recv(to_read)
return databytes
clientVideoSocket = socket(family=AF_INET, type=SOCK_STREAM)
clientVideoSocket.connect((HOST, PORT_VIDEO))
wvs = WebcamVideoStream(0).start()
clientAudioSocket = socket(family=AF_INET, type=SOCK_STREAM)
clientAudioSocket.connect((HOST, PORT_AUDIO))
audio=pyaudio.PyAudio()
stream=audio.open(format=FORMAT,channels=CHANNELS, rate=RATE, input=True, output = True,frames_per_buffer=CHUNK)
initiation = clientVideoSocket.recv(5).decode()
if initiation == "start":
SendFrameThread = Thread(target=SendFrame).start()
SendAudioThread = Thread(target=SendAudio).start()
RecieveFrameThread = Thread(target=RecieveFrame).start()
RecieveAudioThread = Thread(target=RecieveAudio).start()
Server-Side Code:
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
import struct
HOST = input("Enter Host IP\n")
PORT_VIDEO = 3000
PORT_AUDIO = 4000
lnF = 640*480*3
CHUNK = 1024
BufferSize = 4096
addressesAudio = {}
addresses = {}
threads = {}
def ConnectionsVideo():
while True:
try:
clientVideo, addr = serverVideo.accept()
print("{} is connected!!".format(addr))
addresses[clientVideo] = addr
if len(addresses) > 1:
for sockets in addresses:
if sockets not in threads:
threads[sockets] = True
sockets.send(("start").encode())
Thread(target=ClientConnectionVideo, args=(sockets, )).start()
else:
continue
except:
continue
def ConnectionsSound():
while True:
try:
clientAudio, addr = serverAudio.accept()
print("{} is connected!!".format(addr))
addressesAudio[clientAudio] = addr
Thread(target=ClientConnectionSound, args=(clientAudio, )).start()
except:
continue
def ClientConnectionVideo(clientVideo):
while True:
try:
lengthbuf = recvall(clientVideo, 4)
length, = struct.unpack('!I', lengthbuf)
recvall(clientVideo, length)
except:
continue
def ClientConnectionSound(clientAudio):
while True:
try:
data = clientAudio.recv(BufferSize)
broadcastSound(clientAudio, data)
except:
continue
def recvall(clientVideo, BufferSize):
databytes = b''
i = 0
while i != BufferSize:
to_read = BufferSize - i
if to_read > (1000 * CHUNK):
databytes = clientVideo.recv(1000 * CHUNK)
i += len(databytes)
broadcastVideo(clientVideo, databytes)
else:
if BufferSize == 4:
databytes += clientVideo.recv(to_read)
else:
databytes = clientVideo.recv(to_read)
i += len(databytes)
if BufferSize != 4:
broadcastVideo(clientVideo, databytes)
# ~ print("YES!!!!!!!!!" if i == BufferSize else "NO!!!!!!!!!!!!")
if BufferSize == 4:
broadcastVideo(clientVideo, databytes)
return databytes
def broadcastVideo(clientSocket, data_to_be_sent):
for clientVideo in addresses:
if clientVideo != clientSocket:
clientVideo.sendall(data_to_be_sent)
def broadcastSound(clientSocket, data_to_be_sent):
for clientAudio in addressesAudio:
if clientAudio != clientSocket:
clientAudio.sendall(data_to_be_sent)
serverVideo = socket(family=AF_INET, type=SOCK_STREAM)
try:
serverVideo.bind((HOST, PORT_VIDEO))
except OSError:
print("Server Busy")
serverAudio = socket(family=AF_INET, type=SOCK_STREAM)
try:
serverAudio.bind((HOST, PORT_AUDIO))
except OSError:
print("Server Busy")
serverAudio.listen(2)
print("Waiting for audio connection..")
AcceptThreadAudio = Thread(target=ConnectionsSound)
AcceptThreadAudio.start()
serverVideo.listen(2)
print("Waiting for video connection..")
AcceptThreadVideo = Thread(target=ConnectionsVideo)
AcceptThreadVideo.start()
AcceptThreadVideo.join()
serverVideo.close()
Both of these codes are what I have put together in a bit longer of time than I would have liked, but I noticed when doing a bit of testing with these codes that the audio and video were off by anywhere between 3 and 7 seconds. I tried a bit of troubleshooting but couldn't find any issues with the code, aside from the fact that it looks like a kid threw it all together. I am fine with importing a new Python package, but I would prefer to use the Python Packages that I already have in place. Keep in mind I am thinking about eventually converting both the codes into separate .exe files to allow for easy access to send the codes to individual people.
I'm trying to write my own socket streamer where I connect to a know mp3 source using python's socket, stream the data and try and pass it into alsaaudio as pcm data.
I know have to get the icy-metaint, read that many bytes, get the first byte for the metadata length then continue reading metaint bytes.
Unfortunately I've run out of knowlege and the code below results in white noise being played.
Any help would be amazing. Thank you!
#!/usr/bin/env python
import socket
import sys
import alsaaudio
import time
import threading
import Queue
class Player(threading.Thread):
def __init__(self, messageQueue, metaint):
threading.Thread.__init__(self)
self.metaint = metaint
self.messageQueue = messageQueue
self.device = alsaaudio.PCM()
self.rate = 44100
self.famesize = self.rate
self.device.setrate(self.rate)
self.buffer = ""
def sendPCM(self):
print("Buffer length: " + str(len(self.buffer)))
if len(self.buffer) > self.metaint + 255:
pcmData = self.buffer[:self.metaint]
self.device.write(pcmData)
self.buffer = self.buffer[self.metaint:]
print ("New buffer length 1: " + str(len(self.buffer)))
metaDataLength = ord(self.buffer[:1]) * 16
print ("Metadata length: " + str(metaDataLength))
self.buffer = self.buffer[1:]
print ("New buffer length 2: " + str(len(self.buffer)))
metaData = self.buffer[:metaDataLength]
print len(metaData)
self.buffer = self.buffer[metaDataLength:]
print ("New buffer length 3: " + str(len(self.buffer)))
def run(self):
self.sendPCM()
while True:
message = self.messageQueue.get()
if message: self.buffer += message
self.sendPCM()
self.messageQueue.task_done()
def getResponseHeaders(socket):
data = socket.recv(1024)
while not "\r\n\r\n" in data:
data = data + socket.recv(1024)
return data
def getHeaders(response):
headers = {}
for line in response.splitlines():
if line == '\r\n':
break # end of headers
if ':' in line:
key, value = line.split(':', 1)
headers[key] = value
return headers
HOST = 'bbcmedia.ic.llnwd.net'
GET = '/stream/bbcmedia_lc1_radio1_p?s=1420917253&e=1420931653&h=1ff16ea945bd420669c48ae72d003c09'
PORT = 80
#create an INET, STREAMing socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))
client_socket.send("GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent:%s\r\nIcy-MetaData:%s\r\nRange:%s\r\n\r\n" % (GET, HOST,"VLC/2.0.5 LibVLC/2.0.5", "1", "bytes=0-"))
responseHeaders = getResponseHeaders(client_socket)
headers = getHeaders(responseHeaders)
metaint = int(headers['icy-metaint'])
br = int(headers['icy-br'])
print (metaint)
queue = Queue.Queue()
player = Player(queue, metaint)
player.daemon = True
player.start()
while 1:
queue.put(client_socket.recv(4096))
client_socket.close()
sys.exit(0)
It doesn't look like you are actually decoding the audio data.
You are attempting to demux the audio data from the metadata, but you must also run the audio data through the codec to get PCM samples. SHOUTcast/Icecast servers do not send raw PCM. They usually use MP3 or AAC wrapped in ADTS.
I'm not a Python coder so I do not know what all you have available to you. An easy way to decode is to use FFmpeg. It supports STDIO, so you can easily pipe data to it and let it handle the stream and return PCM samples.
I want to record and play my voice using pyaudio and wave lib but I don't know how to do it because wave lib requires a path to a file and even if I'm trying to set it as a variable with list of bytes recorded a few second ago, still doesn't work beacuse I can't use 'read' for a list. Does someone have some idea? I want to make a looper like KORG stuff, etc
I want to play it immediately after stopped recording, like real looper, without saving record as file.
There is my code (Python 3.4):
def record(self): #recording a voice
#var for bytes from recording
self.stream = self.player.open(format = self.FORMAT,
channels = self.CHANNELS,
rate = self.RATE,
input = True,
frames_per_buffer = self.CHUNK)
print("Recording")
self.frames = [] #byte list
#recoring for a few seconds (5sec at this moment)
for i in range(0, int(self.RATE / self.CHUNK * self.RECORD_SECONDS)):
self.data = self.stream.read(self.CHUNK) #sing stream do data var
self.frames.append(self.data) #add bytes to the end of a list
print("Stop recording")
self.stopRecording()
def stopRecording(self):
self.stream.stop_stream()
self.stream.close()
print("Recording has been stopped")
self.play()
def play(self): #playing a record
print("Playing")
f = wave.open(self.frames,"rb")
#read data
data = f.readframes(CHUNK)
#play stream
while data != '':
self.stream.write(data)
data = f.readframes(CHUNK)
self.stopPlaying()
After stop your record you need join your appended data, use data = ''.join(self.frames), and at the end build a loop (for, while) to stream all your byte list, here is how i did:
import pyaudio
chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 41000
RECORD_SECONDS = 5
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)
print ("***Recording***")
all = []
for i in range(0, RATE / chunk * RECORD_SECONDS):
data = stream.read(chunk)
all.append(data)
print("***Stop recording***")
print ("***START PLAY***")
data = ''.join(all)
for i in range(0, len(data), chunk):
stream.write(data[i:i+chunk])
Hello I am trying to figure out some code which is suppose to send voice over the network. I am having problems with the audio it sends but its just a series of loud beeps and not the audio I input
After the beeps are finished I get an EOFError
I have spent the last 48 hours trying to figure this out any ideas are greatly appreciated
The relevant code
import pyaudio
import speex
import sys
chunk = 320
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
### Server function ###
def server():
### Initialize socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
### Start recieve loop
while True:
...
elif cmd == CMD_AUDIO:
d = speex.Decoder()
d.initialize(speex.SPEEX_MODEID_WB)
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)
#voice = cPickle.loads(decrypt_my_message(msg))
voice = cPickle.loads(msg)
print voice
for i in range(len(voice)):
decdata = d.decode(voice[i])#DECODE my data. (YaY)#DECODE my data. (YaY)
stream.write(str(voice), chunk) #Write the data back out to the speakers
stream.stop_stream()
stream.close()
p.terminate()
d.destroy()
if not msg: break
conn.close()
### READ DATA FROM THE MIC ###
def sendAudio():
chunklist = []
init_my_audio = speex.Encoder()
init_my_audio.initialize(speex.SPEEX_MODEID_WB)
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)
for i in range(0, 44100 / chunk * RECORD_SECONDS):
try:
data = stream.read(chunk)
except IOError:
pass
encdata = init_my_audio.encode(data)
chunklist.append(encdata)
client(chr(CMD_AUDIO), cPickle.dumps((chunklist), 1))
stream.stop_stream()
stream.close()
p.terminate()
init_my_audio.destroy()