pifon: an audio baby monitor for two Raspberry Pis

Becoming a dad does not only completely change your life but also changes the scope of your hobby projects (If time still permits :)) My first self-made project made especially for my newborn baby boy Felix is called pifon and is an audio baby monitor realized with two Raspberry Pi devices.

the pifon project: two Raspberry Pis converted into an audio baby monitor

Hardware

The hardware setup is fairly simple: one Pi, the pifon server, has a USB web cam attached. I use its internal microphone to record the voice of my little boy. The other Pi is the pifon monitor and has a set of analog speakers attached for the output. Additionaly, the mon device has an Adafruit RGB LCD Plate attached and I use the LCD on this little plate as output device and its 5 keys as user input. I did not mount the plate directly on the Pi but used a ribbon cable to detach it: This allows me to package the plate in its own housing (As it is easier to find a case for the plate alone):

pifon/mon: the listening Pi with the control panel attached

Software

To get started quickly, I tried to use as many off-the-shelve components for the software as I could: For the audio recording and streaming I opted for the Icecast audio streaming server that gets its input stream recorded from the webcam microphone with the darkice live audio streamer. This setup is proven to be stable and already documented in various projects – also on the Pi.

What’s missing is some kind on status messaging I wanted to have: The pifon server shall analyse the recorded audio stream and when something special (e.g. baby crying) happens it sends an event to the monitor client. So the client can start streaming the live audio only when something interesting is happening. Then the audio stream will stay live until the event is over and then stop streaming.

For the messaging between the server and the monitor I decided to use XMPP, the well known standard for Internet instant messaging. The pifon server and the monitor will then be two “bots” sitting in a chat room and exchanging events by “typing” messages. The advantage of this approach is that you can simply join the chat as a user and also watch for incoming events for the server – that’s also really helpful for debugging :)

I run my own XMPP server on the pifon server Pi and use the prosody server implementation. My code contribution in the project is the bot code and that is written in Python using the SleekXMPP for the XMPP communication. Additionally, I use Adafruit’s Python Code for accessing the LCD and reading the 5 buttons via the I2C bus.

Audio recording is done on the server with SoX‘s rec tool and using an ALSA dsnoop device that allows mutliple applications to share an input device (here the USB cam’s mic).

For audio playback on the pifon mon Pi I use the well known MPD that is controlled by my scripts with the MPC command line tool. It directly supports streaming by adding the stream server URL in the play list.

pifon's mon status and control panel

Features

The pifon project is now in daily production use and has the following list of features:

  • pifon audio server
    • Stream baby’s audio via standard MP3 stream server to any streaming capable device
    • Constantly analyse the audio signal and watch out for loudness periods
    • Provides local XMPP chat server with private chat room for pifon eventing
    • Send events as XMPP chat messages whenever something happens on the audio channel
    • Listen on chat messages that allow to control the parameters of the analyse algorithm
  • pifon monitor
    • Automatically joins the XMPP chat and watches out for events from the server
    • Can stream the audio to your local audio out with mpd
    • LCD displays current state of the server including
      • audio detector state: idle, attack, active, sustain, respite
      • connection: is mon connected to XMPP server?
      • server ping: does the audio server reply my pings?
      • shows peak and current RMS audio level during active phase
    • The LCD has an RGB backlight. It is used to display the server state:
      • BLUE: mon is running but server is not connected yet
      • WHITE: mon is running and server is connected. no audio event happened
      • RED: audio is active (loud) but playback is not enabled
      • GREEN: audio is active (load) and playback is enabled
      • YELLOW: blanking is disabled otherwise similar to WHITE
    • 5 Keys allow to directly toggle:
      • Listen: toggle direct streaming from server. This allows to listen into baby’s room without the audio detector triggering the playback
      • Mute: do not start audio streaming even if an audio event occurred. Use this if you want to watch out for audio events but do not start streaming the audio stream. You will then see the audio event with the LCD backlight only.
      • Chime: the mon client plays a short signal sound before starting or stopping the streaming playback. You can disable playback of these sound icons with this button.
      • Blank: if no audio event occurrs then the LCD is automatically blanked after 10s if no button is pressed. If you want to see the display permanently then toggle this button.
      • Menu: open the parameter menu. Press the button again to leave the menu. Inside the menu the four directional keys allow you to navigate through the menu items and alter the values. See the description of the detector parameters for details below.
  • Both devices are more or less portable if your network technology allows this (I use PowerLAN, but WLAN works as well)
  • Use your Mac/PC or mobile phone as an alternate client: Use an XMPP chat client (I use Adium) to watch for server events and an internet stream player (e.g. VLC) to listen to the audio stream. Talk with the server to alter parameters.

Audio Detector Parameters

The audio detector used in pifon’s audio server has several parameters that allow you to adjust the responsitivity of the detector.

The audio detecter is modeled as a state machine that analyses the max RMS value of the samples recorded in a given period and uses this value to decide on state traversal.

The following states are defined:

  • Idle: nothing special happens on audio
  • Attack: audio level peaks and it might be the begin of a loudness phase if its long enough
  • Active: attack period was long enough, we enter active mode and start streaming audio
  • Sustain: if audio is silent during the active phase for a longer time then the sustain phase is entered and will lead to end of playback if its long enough
  • Respite: This phase enforces a quiet period right after the end of an active phase. Even if audio events occur in this phase they are ignored. This phase was introduced to avoid very frequent start/stop playback cycles.

The mon displays some additonal states in the LCD, but they are not audio related:

  • Connect: initial connect to XMPP server
  • Online: mon is in chat room and gets pings from audio server
  • Offline: no ping and disconnected from XMPP server
  • No Ping: mon is connected to XMPP server but audio server does not reply on pings

The following audio detector parameters can be adjusted:

  • trace (boolean): allows to show the audio RMS value all the time. This is useful for debugging and adjusting the other parameters
  • alevel (int, 0-100): level of audio signal must be higher than this value to enter attack state
  • slevel (int, 0-100): level of audio signal muse be lower than this value to enter sustain state
  • update (int, 1-..): update interval of audio state in 100 ms
  • attack (int, 0-..): duration in [s] of peak audio values that must be audible so that active state is entered
  • sustain (int, 1-..): duration in [s] of silence so that active state is left
  • respite (int, 0-..): duration in [s] after an active period where no new active period is started

You can alter these parameters in the XMPP chat with the following commands:

get audio *
set audio trace False
set audio alevel 10
set audio slevel 5
set audio update 5
set audio attack 0
set audio sustain 5
set audio respite 10

The ‘*’ allows to get all values available.

Build your own pifon!

Yes you can build your own clone of the pifon if you like. Everything you need is freely available: all used tools and my code.

The source of my code contributions are found on GitHub: cnvogelg/raspi. Just clone the repository and use it.

This repository includes a detailed instruction manual on how to setup everything. If you need hints on setting up your Pi itself I have all notes I use for my Pi setup stored in install.txt.

Now hack on and build your own uber-geeky baby monitor!

6 comments to pifon: an audio baby monitor for two Raspberry Pis

  • Immobilizer

    Hi lallafa,

    I’m trying to figure out step 4.2 — i am unable to register a new user at the server. I’m using pidgin instead of adium, and am registering as @pifon.local but nothing seems to be happening on the Pi’s end. When i try to register as @, the pi sees the request but gives me this message:


    pi@pifon ~ $ sudo tail /var/log/prosody/prosody.log
    May 12 15:33:49 mod_posix warn Received SIGTERM
    May 12 15:33:49 general info Shutting down: Received SIGTERM
    May 12 15:33:49 general info Shutting down...
    May 12 15:33:49 general info Shutdown status: Cleaning up
    May 12 15:33:49 general info Shutdown status: Closing all active sessions
    May 12 15:33:49 general info Shutdown status: Closing all server connections
    May 12 15:33:49 general info Shutdown complete
    May 12 15:34:08 general info Hello and welcome to Prosody version 0.8.2
    May 12 15:34:08 general info Prosody is using the select backend for connection handling
    May 12 15:34:09 localhost:posix info Successfully daemonized to PID 2141
    pi@pifon ~ $ sudo tail /var/log/prosody/prosody.log
    May 12 15:35:26 c2s538cf0 info Client disconnected: This server does not serve 10.0.1.14
    May 12 15:35:26 c2s538cf0 info Destroying session for (unknown) ((unknown)@10.0.1.14)

    Any ideas on what’s going wrong?

    One other thing — in raspi-master\doc\install.txt, I think there is a typo:

    ** Hostname
    -> /etc/hosts add "yourhost" as 127.0.0.1

    One of those zeros should be a one :)

  • Immobilizer

    Whoops, above comment should say:
    u...@pifon.local
    user@[my ip address]

    html > me

  • Immobilizer

    Looks like I found the problem! I was using a windows machine which couldn’t resolve the hostname (pifon). To get around this I used the Pi’s IP address which allowed me to connect, but using OS X solves that problem completely.

    However, the files specified in section 6.1 and 6.2 (pifon/mon/rc.pifon & pifon/srv/rc.pifon) do not exist in your github repository. Instead, in the srv folder I find detector.py and recorder.py, in the mon folder rc.pifon_mon, and in the fon folder rc.pifon_fon. I’m trying to figure how I can use these in place of the files specified in the instructions. Any suggestions?

  • Oops… I forgot to upload the last changes… Please pull current git. There the correct startup files are mentioned.

  • Immobilizer

    Thanks lallafa!

    Have you had problems with SoX alsa over-runs? The following error repeats itself over and over:

    > tmux attach -t audio

    ...
    /usr/bin/rec WARN alsa: over-run
    /usr/bin/rec WARN alsa: over-run
    ...

    The icecast stream sounds great, though I haven’t had a chance to listen to anything handled by SoX.
    Perhaps changing the buffer size can solve the over-run problems?

  • I had a look in my current production system and there is a single over-run message reported. The system has a current uptime of 3 months so I don’t think this is a big problem here…

    Maybe the load on your system is different… Are there any other tasks running? The pifon server is the only thing running on the recording side here.

Leave a Reply