Streaming audio with Python


10 posts
by gazzwi86 » Thu Nov 22, 2012 10:48 am
I've bought myself a 3D sound USB sound card and hooked it up to my iPod. I'm trying to stream the audio to my computer now.

I have installed PyAudio on the Raspberry Pi (Raspian), and have portaudio installed on my Mac and now both scripts at least attempt to run. However, I keep getting errors at both end. Firstly, the client script will not even start and the server script starts occasionally but with errors.

Can anyone help?

Client Script

Code: Select all
import pyaudio, sys, socket

chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 15000
timer = 0

p = pyaudio.PyAudio()

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

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((socket.gethostname(),5000))
server_socket.listen(5)

print "Your IP address is: ", socket.gethostbyname(socket.gethostname())
print "Server Waiting for client on port 5000"

while 1:

    client_socket, address = server_socket.accept()
    client_socket.sendall(stream.read(chunk))


Server Script

Code: Select all
import pyaudio
import sys
import socket

ip = "192.168.1.241"

[b][/b]chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 15000
timer = 0

p = pyaudio.PyAudio()

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

while 1:

    #Create a socket connection for connecting to the server:
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((str(ip),5000))

    #Recieve data from the server:
    data = client_socket.recv(1024)
    stream.write(data,chunk)


Client Error
Code: Select all
Traceback (most recent call last):
  File "audioStreamClient.py", line 21, in <module>
    client_socket.connect((str(ip),5000))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 61] Connection refused


Server Error
Code: Select all
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.front.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM front
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.surround40.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM surround40
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.surround51.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM surround41
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.surround51.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM surround50
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.surround51.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM surround51
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.surround71.0:CARD=0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM surround71
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.iec958.0:CARD=0,AES0=4,AES1=130,AES2=0,AES3=2'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM iec958
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.iec958.0:CARD=0,AES0=4,AES1=130,AES2=0,AES3=2'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM spdif
ALSA lib confmisc.c:1286:(snd_func_refer) Unable to find definition 'cards.BRCM bcm2835 AL.pcm.iec958.0:CARD=0,AES0=4,AES1=130,AES2=0,AES3=2'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM spdif
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Timeout

ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Timeout

ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
ALSA lib pcm_direct.c:877:(snd1_pcm_direct_initialize_slave) slave plugin does not support mmap interleaved or mmap noninterleaved access
ALSA lib pcm_dmix.c:1030:(snd_pcm_dmix_open) unable to initialize slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
Traceback (most recent call last):
  File "audioStream.py", line 11, in <module>
    stream = p.open(format = FORMAT,channels = CHANNELS,rate = RATE,input = True,output = True,frames_per_buffer = chunk)
  File "/usr/lib/pymodules/python2.7/pyaudio.py", line 714, in open
    stream = Stream(self, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/pyaudio.py", line 396, in __init__
    self._stream = pa.open(**arguments)
IOError: [Errno Invalid input device (no default output device)] -9996
Posts: 16
Joined: Thu Oct 04, 2012 4:02 pm
by gazzwi86 » Thu Nov 22, 2012 10:54 am
Just for added details:

Code: Select all
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 011: ID 0d8c:000e C-Media Electronics, Inc. Audio Adapter (Planet UP-100, Genius G-Talk)

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: Device [Generic USB Audio Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
Posts: 16
Joined: Thu Oct 04, 2012 4:02 pm
by ski522 » Thu Nov 22, 2012 12:00 pm
Not sure if this is your problem but try making the USB sound card your first card. Do this by:
sudo nano /etc/modprobe.d/cat alsa-base.conf
Code: Select all
options snd-usb-audio index=0 nrpacks=1

nrpacks=1 option might not be needed, I needed it for my sound card though. aplay -l should then show the cards opposite from what you currently have
Code: Select all
**** List of PLAYBACK Hardware Devices ****
[b]card 0[/b]: DAC [USB Audio DAC], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
Posts: 394
Joined: Sun Sep 30, 2012 2:22 pm
by Tom Swirly » Fri Nov 23, 2012 7:24 pm
Important note here - pyaudio spews out tons of diagnostics, including apparent "errors", even in correct operation. This is a decidedly negative feature - my program starting up emits pages of crap from pyaudio and I've repeatedly missed tiny errors because of this, either errors from pyaudio or errors from my own program.

I have this marked as a bug against the program, and when I have time (next year, most likely) I'm going to fork pyaudio and have some better control of errors.

If you think about it, a library emitting errors to stderr is about the most useless thing you can do - because the person who sees them is the enduser, who can do nothing about them. Surely these errors should be being passed back to your calling program, which can then decide what to do about them!
Posts: 160
Joined: Tue Sep 25, 2012 1:08 am
by yeahbox » Sat Nov 24, 2012 2:08 pm
Nice work so far but I'm afraid you've got multiple issues and many of them will not work.

  • Keep it simple. Always a good strategy when you try out something new
  • Make sure it works by testing small bits of code and expand functionality as you go along
  • If it doesn't work, go back and read the errors, make your code simpler and then try again.

So, here's some comments about your code.

In your client, the variable RATE = 15000 is very odd. Normally you would choose a sample rate that is what the soundcard supports. It is usually a multiple of either 32000, 44100 or 48000 [Hz]. So a rate of 22050 is ok (half of 44100). 16000 is also ok (half of 32000). 12000 is also ok (48000/4)

In your your server, open your socket outside the while loop. You don't want to create the socket every time you loop

In your client, remove the socket.gethostname() and hardcode the IP number. Keep It Simple

Try it without the audio stuff. This is probably my best advise to you for now. If your client/server is set up correct you should be able to send simple data like for example data=bytearray('DEADBEEF'.decode('hex')) from one to another. If this doesn't work there is no point in trying to send audio. Keep It Simple.

Try the audio stuff locally on each machine. That must also work before you try something like network stuff.

Don't forget to close your streams, both the audio and the sockets. The error socket.error: [Errno 61] Connection refused could easily be because you've opened a socket before and didn't close it so now it is "hanging in the air".

Finally a general comment, what you are trying to achieve is a little bit tricky for many reasons. But it can certainly be done. All your calls are what is known as "blocking calls". This means that your code will not continue to the next line until it is finished. In practice this means that when your socket is receiving data, it will wait until it has received all data it expects. But in order to play audio out on your soundcard you need 12000*2 bytes (12000 is the rate and your paInt16 is 2 bytes) _every_ second to play audio without stuttering/dropouts. So if your socket is waiting for data the soundcard will not have anything to play and you will hear dropouts at the best.

I'm sure that you will make this work. You have come a long way and you just need to sort out some of the issues.

Good luck!
Posts: 36
Joined: Sun May 27, 2012 10:35 pm
Location: Manchester, UK
by yeahbox » Sat Nov 24, 2012 2:27 pm
Tom Swirly wrote:Important note here - pyaudio spews out tons of diagnostics, including apparent "errors", even in correct operation.

PyAudio is only providing bindings for Portaudio. Portaudio is then talking to for example ALSA on a linux machine and MME on a WinXP. So the error messages that you talk about is most likely from Portaudio or even more likely from ALSA.

Tom Swirly wrote:I have this marked as a bug against the program, and when I have time (next year, most likely) I'm going to fork pyaudio and have some better control of errors.

Which "program" are you talking about? PyAudio, Portaudio or ALSA? And why do you feel like you need "to fork it" to fix this? Isn't it better to make the improvements in PyAudio, Portaudio or ALSA directly so that everybody else will benefit from these improvements? As far as I know all three of the mentioned packages are actively maintained.

Tom Swirly wrote:If you think about it, a library emitting errors to stderr is about the most useless thing you can do - because the person who sees them is the enduser, who can do nothing about them. Surely these errors should be being passed back to your calling program, which can then decide what to do about them!

Well an error message is an error message and should be passed to stderr. That is were error messages live. If your code is not using the libraries in a correct way you might get an error printed to stderr and your program chrashes. This is not the same as if the library (or some other parts of your program) throws an exception that you later catch and make the decision to ignore or take action against. PyAudio certainly throws exception and returns error codes from Portaudio.
Posts: 36
Joined: Sun May 27, 2012 10:35 pm
Location: Manchester, UK
by gazzwi86 » Tue Nov 27, 2012 2:13 pm
I got it working. I had to move the socket accept connection out of the while loop, remove the bind address and also make sure I close off all of the streams and sockets on completion.

You may have to play around with the chunk size as PortAudio (the c library below pyaudio) can run into issues if you throw to much data at it.

Thanks all for your help!!

Sever:
Code: Select all
import pyaudio, sys, socket

port = 5000
chunk = 512
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100

p = pyaudio.PyAudio()
stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, output = True, frames_per_buffer = chunk)

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create the socket
server_socket.bind(('', port)) # listen on port 5000
server_socket.listen(5) # queue max 5 connections
client_socket, address = server_socket.accept()

print "Your IP address is: ", socket.gethostbyname(socket.gethostname())
print "Server Waiting for client on port ", port

while True:

    # test string
    #data = bytearray('DEADBEEF'.decode('hex'))
    #client_socket.sendall(data)
   
   try:
      client_socket.sendall(stream.read(chunk))
   except IOError,e:
      if e[1] == pyaudio.paInputOverflowed:
         print e
         x = '\x00'*16*256*2 #value*format*chunk*nb_channels

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


Client
Code: Select all
import pyaudio, sys, socket

port = 5000
ip = "change to your ip address"

chunk = 512
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100

p = pyaudio.PyAudio()
stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True,output = True, frames_per_buffer = chunk)

#Create a socket connection for connecting to the server:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, port))

while True:

   #Recieve data from the server:
   data = client_socket.recv(1024)
   stream.write(data,chunk)
   #print data
   
   
socket.close()
Posts: 16
Joined: Thu Oct 04, 2012 4:02 pm
by gazzwi86 » Tue Dec 11, 2012 2:43 pm
So while the above works the quality is now really bad. I was hoping a better USB sounds card such as:

http://www.amazon.co.uk/Dynamode-Channe ... =8-2-fkmr0
(I can't see a better one, I need it as small as possible)

plus the new 512 RPi would help (still waiting for this to arrive). However, would anyone be able to suggest how I could improve the sound quality? It seems to be worse than when I last tried it.

Also, I want to play the stream on a website. Is there a way of creating a file I could stream, maybe an mp3?
Posts: 16
Joined: Thu Oct 04, 2012 4:02 pm
by proderius » Fri Jan 04, 2013 2:08 pm
gazzwi86 wrote:So while the above works the quality is now really bad. I was hoping a better USB sounds card such as:


Hi, I've tested some hardware and I have such $3 "sound-card" but I would NOT recommend you such cheap hardware for recording. As for listening or playing It's quite ok, but I used very different mic's with this sound card and even expensive one produces cracks and noise unacceptable for streaming or listening. I found also small but not so cheap such as http://en.store.creative.com/sound-blas ... 17892.aspx
Posts: 1
Joined: Fri Jan 04, 2013 1:35 pm
by Shyam » Thu Oct 10, 2013 1:39 am
Thank you for this useful post. It is possible to stream .wav file (eg. song) in similar way?
Posts: 1
Joined: Thu Oct 10, 2013 1:31 am