2

I have been trying to find a reliable method to play sound on my Pi Zero W, in Python. By default, Zero does not have audio output, but I have set up an I2S amp and speaker, following this guide: http://www.lucadentella.it/en/2017/04/26/raspberry-pi-zero-audio-output-via-i2s/

In general, the audio output is good. For example, I can use headless vlc player to stream audio from youtube or various internet radio stations.

But I was quite surprised the options are quite poor when you need to play sound from Python. Pyglet seems to be abandoned, at least the AVbin lib it relies on definately is. Launching an external player in separate process to play sounds might be acceptable for a "media player" application, but not reliable when you need to play little bits of sounds with precise timing. So a method more native to Python is sought.

Despite the load of heavy reference requirements, I've currently settled on pygame. But unfortunately it behaves bad, when the app has been running for long time. I've described symptoms here: https://stackoverflow.com/questions/54564107/pygame-mixer-music-ogg-playback-distorted-after-long-period-of-idling

If there are reliable alternative to pygame, I'd gladly use that. Currently I am stuck with pygame, that has this weird glitch, where the only workaround is to do secret re-initialisation at regular time intervals.

Passiday
  • 119
  • 2
  • 5

3 Answers3

1

On a Pi Zero with a recent Raspbian and Python 3.6 I tried a few things1 that didn't work that well out of the box and finally I settled for vlc. It's using a USB soundcard and alsa but it's likely to work with an I2S soundcard as well.

Installed vlc along with approx. 150 other packages and Python-bindings for vlc via

sudo apt-get install vlc 
sudo pip3 install python-vlc

Playing from Python worked straight forward:

import vlc
instance = vlc.Instance('--aout=alsa')
p = instance.media_player_new()
m = instance.media_new('something.mp3') 
p.set_media(m)
p.play() 
p.pause() 
vlc.libvlc_audio_set_volume(p, volume)  # volume 0..100

Didn't do any long time running tests though (feel free to post another answer about that if going that way).

time-critical playback of short sound bits

Not doing any measurements, but:

  • play feels immediate (push enter, hear sample start)
  • pause seems to have a small but noticable lag, so likely in the range of a few tens to hundreds of milliseconds.

It is noteworthy that one could instantiate more than one player if that helps (and have them play samples at the same time).

Alternative: gstreamer got Python bindings and mp3 as well as ogg decoding.


Further reading:


1 Installed ffmpeg along with sdl2 and ffpyplayer - didn't get it to play, both using pip3 and installing from github. Checked ffmpeg-python which in fact worked for cool stuff like creating video overlays and converting audio and video, didn't seem to be the right choice for simply playing audio. Tried pyglet which needed avbin for which I didn't find a source or an ARM binary. Tested pygame that didn't work with sdl2 - and I did not want to install another version of the sdl.

Ghanima
  • 15,855
  • 15
  • 61
  • 119
  • For media-player style song playback, I tested running vlc in subprocess, and killing the subprocess if I want to stop the playback. Perhaps very brutal, but appears to work without big problems. But I am looking for time-critical playback of short sound bits (for example percussions in specific pattern). An external player is not viable for this purpose. Luckily, my installation of pygame generally works, but with that stupid degradation when mixer is idle for long time. – Passiday Feb 15 '19 at 21:44
  • 1
    Fair enough, but note that the approach as outlined in my answer is not creating a new subprocess each time but instantiates a player once and reuses that. This may or may not behave differently with respect to any delays. I would guess that you're the best candidate to measure that with your setup and according to your requirements. Feel free to give us an update about your findings. – Ghanima Feb 15 '19 at 21:55
0

G'day Passiday, I'm looking for exactly your solution. I'm just wondering, would you happen to have the code to setup the Pi Zero pins, I assume you have to set them up in order for them to work or are the modifications to config.txt etc and the connections outlined in the link you provided (http://www.lucadentella.it/en/2017/04/26/raspberry-pi-zero-audio-output-via-i2s/) enough to make it work with the vlc commands? Thanks in advance.

Lyster
  • 1
  • 2
0

I used mpg321 in subprocess. https://www.raspberrypi.org/forums/viewtopic.php?f=32&t=231250&p=1416572&hilit=mpg321#p1416572 it's possible to pipe info in and out (for instance fft for graphics, volume, pause etc.

paddyg
  • 325
  • 1
  • 11
  • I am looking for a solution that is capable of real-time sound effect playback. Anything that relies on external player, mpg321 or vlc, will have noticable variable-length delay that makes it unreliable for such purpose. – Passiday Feb 15 '19 at 21:34
  • I've also used csound on the RPI which might be more the kind of thing you want. There is a python wrapper but it takes a bit of effort to use the meta language – paddyg Feb 17 '19 at 08:18