Channels ▼
RSS

Tools

Voice Throwing with Python and Android


When coding in front of a computer all day, I prefer to don my Sennheiser HD 280 pro headphones and enter alpha wave flow by listening to melodic instrumental music or SomaFM streams like Groove Salad or Space Station Soma. Unfortunately, that means I can't hear when my Android phone is alerting me to a text message, Hangout invite, or a personal email. I solved this inconvenience by sending notifications received on my phone to a tiny Web server running on my computer, then rendering the message to audio via the operating system's default text-to-speech engine.

With just a few lines of Python code and a terrific little Android workflow utility called Tasker, I'll show you how you can do this with your Mac or PC as well.

Setting Up the Server

If you're running Linux or OSX on your desktop, you already have Python installed. If you're running Windows, download your preferred version of Python from python.org.

When creating Python-based Web applications, I typically opt for the Django framework. But for the minimal capabilities required for this project, I don't need the heavy lifting that Django provides. I avoid its bulky overhead by using a popular and lightweight Python Web micro framework called Bottle. Install Bottle using the usual Python third-party library installation routine. I use the pip (which supposedly stands for "python install python"), but you can also use easy_install on the Mac if you haven't configured pip on your computer. You can also install the package manually by downloading the bottle package, unzipping it, and running "python setup.py install" at the command prompt or terminal within the unzipped folder. Here's what my Bottle install session looked like on OSX using pip:

$ sudo pip install bottle
Downloading/unpacking bottle
  Downloading bottle-0.11.6-py2.py3-none-any.whl (77kB): 77kB downloaded
Installing collected packages: bottle
Successfully installed bottle
Cleaning up...

In order for my computer to speak incoming messages sent by an Android phone, I had to import a cross-platform Python speech library called pyttsx. Just as with Bottle, run either easy_install, pip (sudo easy_install pyttsx on OSX), or manually install the library. If you are using Microsoft Windows, you will need to install an additional dependency called pywin32. This library exposes Windows-specific function calls for use in Python scripts. Here's a sample install session using pip on OSX:

$ sudo pip install pyttsx
Downloading/unpacking pyttsx
  Downloading pyttsx-1.1.tar.gz
  Running setup.py (path:/private/tmp/pip_build_root/pyttsx/setup.py) 
  egg_info for package pyttsx
    
Installing collected packages: pyttsx
  Running setup.py install for pyttsx
    
Successfully installed pyttsx
Cleaning up...

Be aware that if you're running a 64-bit version of Windows (such as Windows 8 or higher), you will need to manually install the 64-bit version of the pywin32 package. You can download this package from the "Python for Windows" extensions page on SourceForge. Make sure to download the build for the Windows version of Python that you're running.

With the Bottle Web micro-framework and the pyttsx cross-platform text to speech library installed, you're ready to code your server.

Coding the Server

Create a new file called "desknotify.py" using your favorite text editor (I prefer using the Python-friendly cross-platform Sublime Text editor). Then write the following code:

from bottle import Bottle, post, request, run
import pyttsx
app = Bottle()

engine = pyttsx.init()

@app.post('/say')
def notify():
	engine.say(request.forms.message)
	engine.runAndWait()
	return

run(app, host='0.0.0.0', port=8224, reloader=True)

The first two lines import the Bottle and pyttsx libraries. I then create a bottle object and assign it to app. I also initialize pyttsx and assign it to engine. Next, I define a function called notify() that will respond to Web POST requests delivering a string assigned to the variable message. When the string is received, it is passed to the say function of the engine object. Then I tell the engine object to speak the string via the runAndWait() function. Finally, I call Bottle's run method to tell it to spin up its built-in WSGI-compliant Web server and listen for local and external inbound requests on port 8224 (this just happens to be the arbitrarily assigned port number). The final parameter in the run() method allows Bottle to reload any changes made to the desknotify.py file even if the server is running. This can be helpful if you want to iteratively enhance the application without having to constantly stop and restart the script.

Open up a terminal or command-prompt window, enter to the directory where you saved the desknotify.py file, and run the script. If no syntax errors or missing library dependencies are encountered, your script's execution should look similar to the following output.

$ python desknotify.py 
Bottle v0.11.6 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:8224/
Hit Ctrl-C to quit.

If you're running this script on Windows, approve any firewall permissions that might pop up asking to allow the script to listen for inbound requests. If you encounter any errors, analyze the output, address any syntax or dependency issues, and try again.

Now that the server is ready for action, let's use Tasker for Android to send messages received and displayed within Android's notification area to the Bottle Web application.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video