HTML5 audio caching
One of my latest coding endeavors is a text-to-speech interface for JavaScript using HTML5 <audio> elements to output synthesized speech from a server. To reduce the latency between a speech request and actual speech output, I'm using various levels of caching. One of these is the regular browser disk cache based on HTTP headers.
It turns out that browser caching behavior for <audio> data varies wildly among browsers. The following table shows the HTML5 <audio> caching behavior of various browsers. I tested all of them on OS X 10.6 with the standard Mac Apache server hosting all of the tested audio files.
| Browser | <audio> Behavior |
|---|---|
| Firefox 3.6 | Respects cache headers for the sound data. Only contacts the server when the cache item expires. <audio> elements pointing to the same src reuse the cache data. |
| Chrome 5.0.322.2 | Contacts the server on every load(). When it receives a 304 response, does not refetch content.* |
| Safari 4.0.4 | Contacts the server to fetch first two bytes of the audio file on every load(). Receives a 206 response with partial content. Fetches the additional bytes from the file. Receives another 206 response with the partial content. Performs another fetch and receives a 304 response with no data. Continues to alternate between fetches that receive 206 partial data responses and 304 not modified responses. Nothing appears to get cached. |
| Webkit r54921 | Same behavior as Safari 4.0.4. |
* Though not cache related, audio output in Chrome is often clipped before the end of the actual audio data. When this occurs, Chrome fires the onended event even before the audible output finishes.
Except for Firefox 3.6, all of these browsers seem to exhibit pretty terrible caching behavior when it comes to audio. I've reported bugs where I thought appropriate, but maybe I'm missing something. Am I supposed to include additional headers in the server-side response? Or maybe I'm glossing over some key part of the <audio> API? If so, please let me know. If not, yikes: <audio> support has definite room for improvement.
Spaceship! code at GitHub
I cloned the code for Spaceship! at GitHub to facilitate easier development by anyone interested. I'll push any future improvements I make there and consider my personal subversion repository dead.
pyttsx
pyttsx is a cross-platform text-to-speech package for Python. It has a simple API for producing speech, setting some basic engine properties, and getting start/stop/word callbacks. pyttsx currently supports SAPI5, NSSpeechSynthesizer, and espeak, but it can be extended to support other engines and libraries.
The project BSD licensed and hosted on Launchpad. PyPI tracks downloads for the latest stable version and documentation.
GtkBuilder/Glade on IronPython
Thanks to Stephane for his answer to my query about using GtkBuilder in IronPython. It turns out his Gtk#Beans package provides the magic sauce that is currently missing from gtk# trunk the current stable release.
For completeness, here's the code I sent him that accomplishes the same thing using the older Glade.XML object for those that are interested. It answers a long standing mailing list question about using Glade.XML.Autoconnect in IronPython.
import clr clr.AddReference('gtk-sharp') clr.AddReference('glade-sharp') import Gtk import Glade def PyGladeAutoconnect(gxml, target): def _connect(handler_name, event_obj, signal_name, *args): name = ''.join([frag.title() for frag in signal_name.split('_')]) event = getattr(event_obj, name) event += getattr(target, handler_name) # add all widgets for widget in gxml.GetWidgetPrefix(''): setattr(target, gxml.GetWidgetName(widget), widget) # connect all signals gxml.SignalAutoconnectFull(_connect) class Application: def __init__(self): gxml = Glade.XML("test.glade", "window1", None) PyGladeAutoconnect(gxml, self) # window1 comes from glade file self.window1.ShowAll() def onWindowDelete(self, o, args): # connected via glade file definition Gtk.Application.Quit() Gtk.Application.Init() app = Application() Gtk.Application.Run()