3

I am trying to do something like a walkie talkie. 1 device is my laptop and the other being the raspberry pi.

What I have working. I am able to record the microphone, transmit it over a socket and save the recording audio into a wav file.

Only issue I am having is playing the audio live while being sent by the socket. It seems to always breaking in sound. It gets like maybe a 1/4 second of audio then just breaks and then hear another random sound it tried to play, but doesn't.

When I take these scripts and run them both on the same machine there is no issue. So, my thought is there is something going wrong when sending it over or it isn't reading it quick enough or trying to do too much at a time.

Could be how much data that is being transfer that is the issue in which it is failing to play the sound properly.

I have been able to save the wav file and play it with aplay and can confirm the speakers do work and that audio data is at least being transmitted.


Edit:

I tried the suggested UDP method, but kept getting desync audio. Completely inaudible. Just sounded like pieces of audio just were completely gone, which makes sense, but no clue how I can stitch the sound together to even sound close to the original sound.

I was able to sort of getting it to work with TCP. On the client side I end up randomly getting [Errno -9981] Input overflowed at some point which then closes the stream. [Errno -9988] Stream closed.

Not much has change on the code. CHUNK sizes requires playing with sometimes.

I can hear my voice, but after couple of seconds the stream closes due to the errors and I tried having a handle for it, but still goes about closing the stream.

The server tends to spit out this in the terminal

Increasing the CHUNK helps with the underrun issue, however the stream still closes on its own.

Server.py (PI)

import Queue
import socket
import wave
import pyaudio
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
WAVE_OUTPUT_FILENAME = "server_output.wav"
WIDTH = 2
HOST = '192.168.2.90' # 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
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(WIDTH),
 channels=CHANNELS,
 rate=RATE,
 output=True,
 frames_per_buffer=CHUNK)
q = Queue.Queue()
frames = []
stream.start_stream()
def main():
 data = conn.recv(CHUNK)
 while data != '':
 q.put(data)
 if not q.empty():
 stream.write(q.get())
 # stream.write(data)
 data = conn.recv(CHUNK)
 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()
if __name__ == '__main__':
 main()

Client.py

import socket
import pyaudio
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
HOST = '192.168.2.90' # 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)
stream.start_stream()
def main():
 print("*_>recording")
 for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
 try:
 data = stream.read(CHUNK)
 except Exception as e:
 print e
 data = '\x00' * CHUNK
 print len(data)
 s.sendall(data)
 print("*_>done recording")
 stream.stop_stream()
 stream.close()
 p.terminate()
 s.close()
 print("*_>closed")
if __name__ == '__main__':
 main()
asked Jan 31, 2017 at 1:01
3
  • i don't sure about your python code. but i am sure if you use gstreamer tcpserversink if is very easy to play live audio over tcp. Commented Jan 31, 2017 at 16:21
  • 2
    That's what UDP is used for. TCP does error checking and retries Commented Feb 1, 2017 at 9:24
  • +1 - TCP is not an ideal mechanism for streaming media, where it doesn't particularly matter if you drop a frame or two along the way and really just want the packets slung as quickly as is possible. Commented Feb 1, 2017 at 13:44

1 Answer 1

0

So after some research I found a post suggesting the RPI2 may not be fast enough.

I found a quick RPI3 and it works. Or at least with a large enough CHUNK size to process within the appropriate time for ALSA to play the audio.

The other suggestion was to somehow improve how fast the bytes get sent to ALSA, but really seems simply just to get to RPI3.

No really satisfying answer, but was able to get it working.

answered Feb 1, 2017 at 20:43
2
  • Any chance of adding a link to your research. I think I may have the exact same problem. Intermittent stream closure by the rPi. nb: in my use case I just used a try: except: around my read line to catch the stream closure and simply reopened the stream when needed. I get a break in the audio every few seconds but that was fine for me. Mine is an RPI1b. I'd prefer to be sure about your answer in my case and find a better solution though. Commented Sep 10, 2018 at 21:33
  • Please accept your answer. Only this will finally finish the question after years now and it will never pop up again. Commented Dec 1, 2019 at 10:13

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.