Tuesday, May 29, 2007

ReadSpeaker without nasty page reloads

Readspeaker's a great service that makes it easy for any website owners to provide audio versions of their content on the fly. This is clearly preferable to re-recording content manually every time a couple of words get changed and the quality of the synthesized voice is actually very natural and lifelike.

Every implemetation of ReadSpeaker that I've seen works by providing a link near the text which, when clicked, either forces a page reload so that an audio player can be embedded or - and this is my personal anti favourite - opens a new page containing only the audio player and shrinks the browser window to the size of the player. Take a look at the O'Reilly Radar (click on the 'listen' link) or any number of examples on ReadSpeaker's site to see what I mean.

While in most cases it's probably true that having a badly implemented audio version of a page is better than no audio version, it is possible to implement ReadSpeaker in a nice, elegant and accessible way.

The reason why it's difficult to find any examples is that the ReadSpeaker documentation doesn't make it very clear that it's possible. However, it is possible to retrieve the URL of the generated mp3 file.

This means that it's possible to pass the mp3 url to an audio player that's embedded in the page when it first loads. If this is implemented with a suitable Flash mp3 player, the mp3 won't be downloaded unless the user decides to play the audio.

The way to retrieve the un-encoded URL of the mp3 is to make the following call to ReadSpeaker (if you want the URL to be encoded, set the 'type' parameter to 101):


http://asp.readspeaker.net/cgi-bin/[CUSTOMER_NAME]rsone?customerid=[CUSTOMER_ID]&url=[URL_OF_PAGE_TO_READ]&type=100

where CUSTOMER_NAME and CUSTOMER_ID are supplied to you by ReadSpeaker when you open an account.

Your Flash player may be capable of using this URL as it is but if you need to pass the player an actual mp3 URL, you'll need to write a script to retrieve the URL of the mp3 up front.

Here's a Python script that I wrote for use with Plone but it should be easy to adapt to any other platform:


# Python script to retrieve the URL of an MP3 audio file from readspeaker.com.

# Import required functions
from urllib import urlopen, quote

def getReadSpeakerURL(customer_name, customer_id, page_to_read_url):
url_to_open = "http://asp.readspeaker.net/cgi-bin/%srsone?customerid=%s&url=%s&type=100" % (customer_name, customer_id, page_to_read_url)
mp3file = ''

try:
fp = urlopen(url_to_open) # this retrieves a page containing the url of the mp3 file
mp3file = fp.readline() # this retrieves the mp3 url itself

# check for errors
except IOError:
mp3file = ''

# return two versions of the mp3 url, one with the URL encoded and one without
return (mp3file, quote(mp3file))

Then place the following HTML into any pages that you want to be ReadSpeaker-ed (this example is written for Plone so uses Template Attribute Language (TAL) syntax. Sorry if you're not familiar with this but I hope you can still follow it):


<div class="readspeaker" define="customer_name string:[CUSTOMER_NAME]; customer_id string:[CUSTOMER_ID]; rs_url_array python: here.getReadSpeakerURL(customer_name, customer_id, here.absolute_url() + '?hidereadspeaker=1'); rs_url_unquoted python:rs_url_array[0]; rs_url_quoted python:rs_url_array[1];">
<h2>Hear this page read out loud</h2>
<object type="application/x-shockwave-flash" define="flashplayer string:/flash/emff_comments.swf?src=${rs_url_quoted}" attributes="data flashplayer" align="middle" height="28" width="200">
<param value="" name="movie" attributes="value flashplayer">
<p>To hear this page read aloud, get the Flash Player from <a href="www.adobe.com">Adobe's web site</a></p>
</object>
<p><a href="" attributes="href rs_url_unquoted">Download</a> - <a href="" attributes="href string:${here/portal_url}/help/index_html#readspeaker-help">Help</a></p>
</div>

This way you can have an accessible method of providing audio content without nasty page reloads.

No comments: